tools/PascalParser.hs
changeset 7374 514138949c76
parent 7317 3534a264b27a
child 7429 fcf13e40d6b6
equal deleted inserted replaced
7304:8b3575750cd2 7374:514138949c76
    12 import Data.Maybe
    12 import Data.Maybe
    13 import Data.Char
    13 import Data.Char
    14 
    14 
    15 import PascalBasics
    15 import PascalBasics
    16 import PascalUnitSyntaxTree
    16 import PascalUnitSyntaxTree
    17     
    17 
    18 knownTypes = ["shortstring", "ansistring", "char", "byte"]
    18 knownTypes = ["shortstring", "ansistring", "char", "byte"]
    19 
    19 
    20 pascalUnit = do
    20 pascalUnit = do
    21     comments
    21     comments
    22     u <- choice [program, unit, systemUnit]
    22     u <- choice [program, unit, systemUnit]
    25 
    25 
    26 iD = do
    26 iD = do
    27     i <- liftM (flip Identifier BTUnknown) (identifier pas)
    27     i <- liftM (flip Identifier BTUnknown) (identifier pas)
    28     comments
    28     comments
    29     return i
    29     return i
    30         
    30 
    31 unit = do
    31 unit = do
    32     string "unit" >> comments
    32     string "unit" >> comments
    33     name <- iD
    33     name <- iD
    34     semi pas
    34     semi pas
    35     comments
    35     comments
    36     int <- interface
    36     int <- interface
    37     impl <- implementation
    37     impl <- implementation
    38     comments
    38     comments
    39     return $ Unit name int impl Nothing Nothing
    39     return $ Unit name int impl Nothing Nothing
    40 
    40 
    41     
    41 
    42 reference = buildExpressionParser table term <?> "reference"
    42 reference = buildExpressionParser table term <?> "reference"
    43     where
    43     where
    44     term = comments >> choice [
    44     term = comments >> choice [
    45         parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes
    45         parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes
    46         , try $ typeCast >>= postfixes
    46         , try $ typeCast >>= postfixes
    47         , char '@' >> liftM Address reference >>= postfixes
    47         , char '@' >> liftM Address reference >>= postfixes
    48         , liftM SimpleReference iD >>= postfixes 
    48         , liftM SimpleReference iD >>= postfixes 
    49         ] <?> "simple reference"
    49         ] <?> "simple reference"
    50 
    50 
    51     table = [ 
    51     table = [
    52         ]
    52         ]
    53     
    53 
    54     postfixes r = many postfix >>= return . foldl (flip ($)) r
    54     postfixes r = many postfix >>= return . foldl (flip ($)) r
    55     postfix = choice [
    55     postfix = choice [
    56             parens pas (option [] parameters) >>= return . FunCall
    56             parens pas (option [] parameters) >>= return . FunCall
    57           , char '^' >> return Dereference
    57           , char '^' >> return Dereference
    58           , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement
    58           , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement
    62     typeCast = do
    62     typeCast = do
    63         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
    63         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
    64         e <- parens pas expression
    64         e <- parens pas expression
    65         comments
    65         comments
    66         return $ TypeCast (Identifier t BTUnknown) e
    66         return $ TypeCast (Identifier t BTUnknown) e
    67         
    67 
    68     
    68 varsDecl1 = varsParser sepEndBy1
    69 varsDecl1 = varsParser sepEndBy1    
       
    70 varsDecl = varsParser sepEndBy
    69 varsDecl = varsParser sepEndBy
    71 varsParser m endsWithSemi = do
    70 varsParser m endsWithSemi = do
    72     vs <- m (aVarDecl endsWithSemi) (semi pas)
    71     vs <- m (aVarDecl endsWithSemi) (semi pas)
    73     return vs
    72     return vs
    74 
    73 
    75 aVarDecl endsWithSemi = do
    74 aVarDecl endsWithSemi = do
    76     unless endsWithSemi $
    75     isVar <- liftM (== Just "var") $
    77         optional $ choice [
    76         if not endsWithSemi then
    78             try $ string "var"
    77             optionMaybe $ choice [
    79             , try $ string "const"
    78                 try $ string "var"
    80             , try $ string "out"
    79                 , try $ string "const"
    81             ]
    80                 , try $ string "out"
       
    81                 ]
       
    82             else
       
    83                 return Nothing
    82     comments
    84     comments
    83     ids <- do
    85     ids <- do
    84         i <- (commaSep1 pas) $ (try iD <?> "variable declaration")
    86         i <- (commaSep1 pas) $ (try iD <?> "variable declaration")
    85         char ':'
    87         char ':'
    86         return i
    88         return i
    91         char '='
    93         char '='
    92         comments
    94         comments
    93         e <- initExpression
    95         e <- initExpression
    94         comments
    96         comments
    95         return (Just e)
    97         return (Just e)
    96     return $ VarDeclaration False (ids, t) init
    98     return $ VarDeclaration isVar False (ids, t) init
    97 
    99 
    98 
   100 
    99 constsDecl = do
   101 constsDecl = do
   100     vs <- many1 (try (aConstDecl >>= \i -> semi pas >> return i) >>= \i -> comments >> return i)
   102     vs <- many1 (try (aConstDecl >>= \i -> semi pas >> return i) >>= \i -> comments >> return i)
   101     comments
   103     comments
   112             return t
   114             return t
   113         char '='
   115         char '='
   114         comments
   116         comments
   115         e <- initExpression
   117         e <- initExpression
   116         comments
   118         comments
   117         return $ VarDeclaration (isNothing t) ([i], fromMaybe (DeriveType e) t) (Just e)
   119         return $ VarDeclaration False (isNothing t) ([i], fromMaybe (DeriveType e) t) (Just e)
   118         
   120 
   119 typeDecl = choice [
   121 typeDecl = choice [
   120     char '^' >> typeDecl >>= return . PointerTo
   122     char '^' >> typeDecl >>= return . PointerTo
   121     , try (string "shortstring") >> return (String 255)
   123     , try (string "shortstring") >> return (String 255)
   122     , try (string "string") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
   124     , try (string "string") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
   123     , try (string "ansistring") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
   125     , try (string "ansistring") >> optionMaybe (brackets pas $ integer pas) >>= return . String . fromMaybe 255
   209         comments
   211         comments
   210         semi pas
   212         semi pas
   211         comments
   213         comments
   212         return $ TypeDeclaration i t
   214         return $ TypeDeclaration i t
   213 
   215 
   214         
       
   215 rangeDecl = choice [
   216 rangeDecl = choice [
   216     try $ rangeft
   217     try $ rangeft
   217     , iD >>= return . Range
   218     , iD >>= return . Range
   218     ] <?> "range declaration"
   219     ] <?> "range declaration"
   219     where
   220     where
   220     rangeft = do
   221     rangeft = do
   221     e1 <- initExpression
   222     e1 <- initExpression
   222     string ".."
   223     string ".."
   223     e2 <- initExpression
   224     e2 <- initExpression
   224     return $ RangeFromTo e1 e2        
   225     return $ RangeFromTo e1 e2
   225     
   226 
   226 typeVarDeclaration isImpl = (liftM concat . many . choice) [
   227 typeVarDeclaration isImpl = (liftM concat . many . choice) [
   227     varSection,
   228     varSection,
   228     constSection,
   229     constSection,
   229     typeSection,
   230     typeSection,
   230     funcDecl,
   231     funcDecl,
   249         try $ string "type"
   250         try $ string "type"
   250         comments
   251         comments
   251         t <- typesDecl <?> "type declaration"
   252         t <- typesDecl <?> "type declaration"
   252         comments
   253         comments
   253         return t
   254         return t
   254         
   255 
   255     operatorDecl = do
   256     operatorDecl = do
   256         try $ string "operator"
   257         try $ string "operator"
   257         comments
   258         comments
   258         i <- manyTill anyChar space
   259         i <- manyTill anyChar space
   259         comments
   260         comments
   274                 liftM Just functionBody
   275                 liftM Just functionBody
   275                 else
   276                 else
   276                 return Nothing
   277                 return Nothing
   277         return $ [OperatorDeclaration i rid ret vs b]
   278         return $ [OperatorDeclaration i rid ret vs b]
   278 
   279 
   279         
   280 
   280     funcDecl = do
   281     funcDecl = do
   281         fp <- try (string "function") <|> try (string "procedure")
   282         fp <- try (string "function") <|> try (string "procedure")
   282         comments
   283         comments
   283         i <- iD
   284         i <- iD
   284         vs <- option [] $ parens pas $ varsDecl False
   285         vs <- option [] $ parens pas $ varsDecl False
   298         b <- if isImpl && (not forward) then
   299         b <- if isImpl && (not forward) then
   299                 liftM Just functionBody
   300                 liftM Just functionBody
   300                 else
   301                 else
   301                 return Nothing
   302                 return Nothing
   302         return $ [FunctionDeclaration i ret vs b]
   303         return $ [FunctionDeclaration i ret vs b]
   303         
   304 
   304     functionDecorator = choice [
   305     functionDecorator = choice [
   305         try $ string "inline;"
   306         try $ string "inline;"
   306         , try $ caseInsensitiveString "cdecl;"
   307         , try $ caseInsensitiveString "cdecl;"
   307         , try $ string "overload;"
   308         , try $ string "overload;"
   308         , try $ string "export;"
   309         , try $ string "export;"
   309         , try $ string "varargs;"
   310         , try $ string "varargs;"
   310         , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";"
   311         , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";"
   311         ] >> comments
   312         ] >> comments
   312         
   313 
   313         
   314 
   314 program = do
   315 program = do
   315     string "program"
   316     string "program"
   316     comments
   317     comments
   317     name <- iD
   318     name <- iD
   318     (char ';')
   319     (char ';')
   394         , [
   395         , [
   395              Infix (char '=' >> return (BinOp "=")) AssocNone
   396              Infix (char '=' >> return (BinOp "=")) AssocNone
   396           ]
   397           ]
   397         ]
   398         ]
   398     strOrChar [a] = CharCode . show . ord $ a
   399     strOrChar [a] = CharCode . show . ord $ a
   399     strOrChar a = StringLiteral a    
   400     strOrChar a = StringLiteral a
   400     
   401 
   401 phrasesBlock = do
   402 phrasesBlock = do
   402     try $ string "begin"
   403     try $ string "begin"
   403     comments
   404     comments
   404     p <- manyTill phrase (try $ string "end" >> notFollowedBy alphaNum)
   405     p <- manyTill phrase (try $ string "end" >> notFollowedBy alphaNum)
   405     comments
   406     comments
   406     return $ Phrases p
   407     return $ Phrases p
   407     
   408 
   408 phrase = do
   409 phrase = do
   409     o <- choice [
   410     o <- choice [
   410         phrasesBlock
   411         phrasesBlock
   411         , ifBlock
   412         , ifBlock
   412         , whileCycle
   413         , whileCycle
   457     comments
   458     comments
   458     string "do"
   459     string "do"
   459     comments
   460     comments
   460     o <- phrase
   461     o <- phrase
   461     return $ foldr WithBlock o rs
   462     return $ foldr WithBlock o rs
   462     
   463 
   463 repeatCycle = do
   464 repeatCycle = do
   464     try $ string "repeat" >> space
   465     try $ string "repeat" >> space
   465     comments
   466     comments
   466     o <- many phrase
   467     o <- many phrase
   467     string "until"
   468     string "until"
   486     string "do"
   487     string "do"
   487     comments
   488     comments
   488     p <- phrase
   489     p <- phrase
   489     comments
   490     comments
   490     return $ ForCycle i e1 e2 p
   491     return $ ForCycle i e1 e2 p
   491     
   492 
   492 switchCase = do
   493 switchCase = do
   493     try $ string "case"
   494     try $ string "case"
   494     comments
   495     comments
   495     e <- expression
   496     e <- expression
   496     comments
   497     comments
   513         char ':'
   514         char ':'
   514         comments
   515         comments
   515         p <- phrase
   516         p <- phrase
   516         comments
   517         comments
   517         return (e, p)
   518         return (e, p)
   518     
   519 
   519 procCall = do
   520 procCall = do
   520     r <- reference
   521     r <- reference
   521     p <- option [] $ (parens pas) parameters
   522     p <- option [] $ (parens pas) parameters
   522     return $ ProcCall r p
   523     return $ ProcCall r p
   523 
   524 
   524 parameters = (commaSep pas) expression <?> "parameters"
   525 parameters = (commaSep pas) expression <?> "parameters"
   525         
   526 
   526 functionBody = do
   527 functionBody = do
   527     tv <- typeVarDeclaration True
   528     tv <- typeVarDeclaration True
   528     comments
   529     comments
   529     p <- phrasesBlock
   530     p <- phrasesBlock
   530     char ';'
   531     char ';'
   557         , char '@' >> initExpression >>= \c -> comments >> return (InitAddress c)
   558         , char '@' >> initExpression >>= \c -> comments >> return (InitAddress c)
   558         , try $ string "nil" >> return InitNull
   559         , try $ string "nil" >> return InitNull
   559         , itypeCast
   560         , itypeCast
   560         , iD >>= return . InitReference
   561         , iD >>= return . InitReference
   561         ]
   562         ]
   562         
   563 
   563     recField = do
   564     recField = do
   564         i <- iD
   565         i <- iD
   565         spaces
   566         spaces
   566         char ':'
   567         char ':'
   567         spaces
   568         spaces
   568         e <- initExpression
   569         e <- initExpression
   569         spaces
   570         spaces
   570         return (i ,e)
   571         return (i ,e)
   571 
   572 
   572     table = [ 
   573     table = [
   573           [
   574           [
   574              Prefix (char '-' >> return (InitPrefixOp "-"))
   575              Prefix (char '-' >> return (InitPrefixOp "-"))
   575           ]
   576           ]
   576         , [  Infix (char '*' >> return (InitBinOp "*")) AssocLeft
   577         , [  Infix (char '*' >> return (InitBinOp "*")) AssocLeft
   577            , Infix (char '/' >> return (InitBinOp "/")) AssocLeft
   578            , Infix (char '/' >> return (InitBinOp "/")) AssocLeft
   601     itypeCast = do
   602     itypeCast = do
   602         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
   603         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
   603         i <- parens pas initExpression
   604         i <- parens pas initExpression
   604         comments
   605         comments
   605         return $ InitTypeCast (Identifier t BTUnknown) i
   606         return $ InitTypeCast (Identifier t BTUnknown) i
   606         
   607 
   607 builtInFunction e = do
   608 builtInFunction e = do
   608     name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin
   609     name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin
   609     spaces
   610     spaces
   610     exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e
   611     exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e
   611     spaces
   612     spaces