tools/PascalParser.hs
changeset 6453 11c578d30bd3
parent 6452 7c6f9b6672dc
child 6467 090269e528df
equal deleted inserted replaced
6452:7c6f9b6672dc 6453:11c578d30bd3
    14 import PascalBasics
    14 import PascalBasics
    15 
    15 
    16 data PascalUnit =
    16 data PascalUnit =
    17     Program Identifier Implementation Phrase
    17     Program Identifier Implementation Phrase
    18     | Unit Identifier Interface Implementation (Maybe Initialize) (Maybe Finalize)
    18     | Unit Identifier Interface Implementation (Maybe Initialize) (Maybe Finalize)
       
    19     | System
    19     deriving Show
    20     deriving Show
    20 data Interface = Interface Uses TypesAndVars
    21 data Interface = Interface Uses TypesAndVars
    21     deriving Show
    22     deriving Show
    22 data Implementation = Implementation Uses TypesAndVars
    23 data Implementation = Implementation Uses TypesAndVars
    23     deriving Show
    24     deriving Show
    55         | WhileCycle Expression Phrase
    56         | WhileCycle Expression Phrase
    56         | RepeatCycle Expression [Phrase]
    57         | RepeatCycle Expression [Phrase]
    57         | ForCycle Identifier Expression Expression Phrase
    58         | ForCycle Identifier Expression Expression Phrase
    58         | WithBlock Reference Phrase
    59         | WithBlock Reference Phrase
    59         | Phrases [Phrase]
    60         | Phrases [Phrase]
    60         | SwitchCase Expression [([InitExpression], Phrase)] (Maybe Phrase)
    61         | SwitchCase Expression [([InitExpression], Phrase)] (Maybe [Phrase])
    61         | Assignment Reference Expression
    62         | Assignment Reference Expression
    62         | NOP
    63         | NOP
    63     deriving Show
    64     deriving Show
    64 data Expression = Expression String
    65 data Expression = Expression String
    65     | BuiltInFunCall [Expression] Reference
    66     | BuiltInFunCall [Expression] Reference
    76     | SetExpression [Identifier]
    77     | SetExpression [Identifier]
    77     | Null
    78     | Null
    78     deriving Show
    79     deriving Show
    79 data Reference = ArrayElement [Expression] Reference
    80 data Reference = ArrayElement [Expression] Reference
    80     | FunCall [Expression] Reference
    81     | FunCall [Expression] Reference
    81     | TypeCast Identifier Reference
    82     | TypeCast Identifier Expression
    82     | SimpleReference Identifier
    83     | SimpleReference Identifier
    83     | Dereference Reference
    84     | Dereference Reference
    84     | RecordField Reference Reference
    85     | RecordField Reference Reference
    85     | Address Reference
    86     | Address Reference
       
    87     | RefExpression Expression
    86     deriving Show
    88     deriving Show
    87 data InitExpression = InitBinOp String InitExpression InitExpression
    89 data InitExpression = InitBinOp String InitExpression InitExpression
    88     | InitPrefixOp String InitExpression
    90     | InitPrefixOp String InitExpression
    89     | InitReference Identifier
    91     | InitReference Identifier
    90     | InitArray [InitExpression]
    92     | InitArray [InitExpression]
    93     | InitNumber String
    95     | InitNumber String
    94     | InitHexNumber String
    96     | InitHexNumber String
    95     | InitString String
    97     | InitString String
    96     | InitChar String
    98     | InitChar String
    97     | BuiltInFunction String [InitExpression]
    99     | BuiltInFunction String [InitExpression]
    98     | InitSet [Identifier]
   100     | InitSet [InitExpression]
       
   101     | InitAddress InitExpression
    99     | InitNull
   102     | InitNull
   100     deriving Show
   103     | InitRange Range
   101     
   104     | InitTypeCast Identifier InitExpression
   102 knownTypes = ["shortstring"]
   105     deriving Show
       
   106     
       
   107 knownTypes = ["shortstring", "char", "byte"]
   103 
   108 
   104 pascalUnit = do
   109 pascalUnit = do
   105     comments
   110     comments
   106     u <- choice [program, unit]
   111     u <- choice [program, unit]
   107     comments
   112     comments
   124 
   129 
   125     
   130     
   126 reference = buildExpressionParser table term <?> "reference"
   131 reference = buildExpressionParser table term <?> "reference"
   127     where
   132     where
   128     term = comments >> choice [
   133     term = comments >> choice [
   129         parens pas (reference >>= postfixes) >>= postfixes
   134         parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes
   130         , typeCast >>= postfixes
   135         , try $ typeCast >>= postfixes
   131         , char '@' >> liftM Address reference >>= postfixes
   136         , char '@' >> liftM Address reference >>= postfixes
   132         , liftM SimpleReference iD >>= postfixes 
   137         , liftM SimpleReference iD >>= postfixes 
   133         ] <?> "simple reference"
   138         ] <?> "simple reference"
   134 
   139 
   135     table = [ 
   140     table = [ 
   136             [Infix (try (char '.' >> notFollowedBy (char '.')) >> return RecordField) AssocLeft]
       
   137         ]
   141         ]
   138     
   142     
   139     postfixes r = many postfix >>= return . foldl (flip ($)) r
   143     postfixes r = many postfix >>= return . foldl (flip ($)) r
   140     postfix = choice [
   144     postfix = choice [
   141             parens pas (option [] parameters) >>= return . FunCall
   145             parens pas (option [] parameters) >>= return . FunCall
   142           , char '^' >> return Dereference
   146           , char '^' >> return Dereference
   143           , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement
   147           , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement
       
   148           , (char '.' >> notFollowedBy (char '.')) >> liftM RecordField reference
   144         ]
   149         ]
   145 
   150 
   146     typeCast = do
   151     typeCast = do
   147         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
   152         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
   148         r <- parens pas reference
   153         e <- parens pas expression
   149         comments
   154         comments
   150         return $ TypeCast (Identifier t) r
   155         return $ TypeCast (Identifier t) e
   151         
   156         
   152     
   157     
   153 varsDecl1 = varsParser sepEndBy1    
   158 varsDecl1 = varsParser sepEndBy1    
   154 varsDecl = varsParser sepEndBy
   159 varsDecl = varsParser sepEndBy
   155 varsParser m endsWithSemi = do
   160 varsParser m endsWithSemi = do
   291         t <- typeDecl
   296         t <- typeDecl
   292         comments
   297         comments
   293         semi pas
   298         semi pas
   294         comments
   299         comments
   295         return $ TypeDeclaration i t
   300         return $ TypeDeclaration i t
       
   301 
   296         
   302         
   297 rangeDecl = choice [
   303 rangeDecl = choice [
   298     try $ rangeft
   304     try $ rangeft
   299     , iD >>= return . Range
   305     , iD >>= return . Range
   300     ] <?> "range declaration"
   306     ] <?> "range declaration"
   301     where
   307     where
   302     rangeft = do
   308     rangeft = do
   303     e1 <- initExpression
   309     e1 <- initExpression
   304     string ".."
   310     string ".."
   305     e2 <- initExpression
   311     e2 <- initExpression
   306     return $ RangeFromTo e1 e2
   312     return $ RangeFromTo e1 e2        
   307     
   313     
   308 typeVarDeclaration isImpl = (liftM concat . many . choice) [
   314 typeVarDeclaration isImpl = (liftM concat . many . choice) [
   309     varSection,
   315     varSection,
   310     constSection,
   316     constSection,
   311     typeSection,
   317     typeSection,
   383                 return Nothing
   389                 return Nothing
   384         return $ [FunctionDeclaration i ret vs b]
   390         return $ [FunctionDeclaration i ret vs b]
   385         
   391         
   386     functionDecorator = choice [
   392     functionDecorator = choice [
   387         try $ string "inline;"
   393         try $ string "inline;"
   388         , try $ string "cdecl;"
   394         , try $ caseInsensitiveString "cdecl;"
   389         , try $ string "overload;"
   395         , try $ string "overload;"
       
   396         , try $ string "export;"
       
   397         , try $ string "varargs;"
   390         , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";"
   398         , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";"
   391         ] >> comments
   399         ] >> comments
   392         
   400         
   393         
   401         
   394 program = do
   402 program = do
   429 
   437 
   430 expression = buildExpressionParser table term <?> "expression"
   438 expression = buildExpressionParser table term <?> "expression"
   431     where
   439     where
   432     term = comments >> choice [
   440     term = comments >> choice [
   433         builtInFunction expression >>= \(n, e) -> return $ BuiltInFunCall e (SimpleReference (Identifier n))
   441         builtInFunction expression >>= \(n, e) -> return $ BuiltInFunCall e (SimpleReference (Identifier n))
   434         , parens pas $ expression 
   442         , try (parens pas $ expression >>= \e -> notFollowedBy (comments >> char '.') >> return e)
   435         , brackets pas (commaSep pas iD) >>= return . SetExpression
   443         , brackets pas (commaSep pas iD) >>= return . SetExpression
   436         , try $ natural pas >>= \i -> notFollowedBy (char '.') >> (return . NumberLiteral . show) i
   444         , try $ natural pas >>= \i -> notFollowedBy (char '.') >> (return . NumberLiteral . show) i
   437         , float pas >>= return . FloatLiteral . show
   445         , float pas >>= return . FloatLiteral . show
   438         , natural pas >>= return . NumberLiteral . show
   446         , natural pas >>= return . NumberLiteral . show
   439         , stringLiteral pas >>= return . StringLiteral
   447         , stringLiteral pas >>= return . StringLiteral
   488         , switchCase
   496         , switchCase
   489         , withBlock
   497         , withBlock
   490         , forCycle
   498         , forCycle
   491         , (try $ reference >>= \r -> string ":=" >> return r) >>= \r -> expression >>= return . Assignment r
   499         , (try $ reference >>= \r -> string ":=" >> return r) >>= \r -> expression >>= return . Assignment r
   492         , procCall
   500         , procCall
       
   501         , char ';' >> comments >> return NOP
   493         ]
   502         ]
   494     optional $ char ';'
   503     optional $ char ';'
   495     comments
   504     comments
   496     return o
   505     return o
   497 
   506 
   570     comments
   579     comments
   571     cs <- many1 aCase
   580     cs <- many1 aCase
   572     o2 <- optionMaybe $ do
   581     o2 <- optionMaybe $ do
   573         try $ string "else" >> notFollowedBy alphaNum
   582         try $ string "else" >> notFollowedBy alphaNum
   574         comments
   583         comments
   575         o <- phrase
   584         o <- many phrase
   576         comments
   585         comments
   577         return o
   586         return o
   578     string "end"
   587     string "end"
   579     comments
   588     comments
   580     return $ SwitchCase e cs o2
   589     return $ SwitchCase e cs o2
   581     where
   590     where
   582     aCase = do
   591     aCase = do
   583         e <- (commaSep pas) initExpression
   592         e <- (commaSep pas) $ (liftM InitRange rangeDecl <|> initExpression)
   584         comments
   593         comments
   585         char ':'
   594         char ':'
   586         comments
   595         comments
   587         p <- phrase
   596         p <- phrase
   588         comments
   597         comments
   615 
   624 
   616 initExpression = buildExpressionParser table term <?> "initialization expression"
   625 initExpression = buildExpressionParser table term <?> "initialization expression"
   617     where
   626     where
   618     term = comments >> choice [
   627     term = comments >> choice [
   619         liftM (uncurry BuiltInFunction) $ builtInFunction initExpression 
   628         liftM (uncurry BuiltInFunction) $ builtInFunction initExpression 
   620         , try $ brackets pas (commaSep pas $ iD) >>= return . InitSet
   629         , try $ brackets pas (commaSep pas $ initExpression) >>= return . InitSet
   621         , try $ parens pas (commaSep pas $ initExpression) >>= return . InitArray
   630         , try $ parens pas (commaSep pas $ initExpression) >>= return . InitArray
   622         , parens pas (semiSep pas $ recField) >>= return . InitRecord
   631         , parens pas (sepEndBy recField (char ';' >> comments)) >>= return . InitRecord
   623         , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . InitNumber . show) i
   632         , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . InitNumber . show) i
   624         , try $ float pas >>= return . InitFloat . show
   633         , try $ float pas >>= return . InitFloat . show
   625         , try $ integer pas >>= return . InitNumber . show
   634         , try $ integer pas >>= return . InitNumber . show
   626         , stringLiteral pas >>= return . InitString
   635         , stringLiteral pas >>= return . InitString
   627         , char '#' >> many digit >>= \c -> comments >> return (InitChar c)
   636         , char '#' >> many digit >>= \c -> comments >> return (InitChar c)
   628         , char '$' >> many hexDigit >>= \h -> comments >> return (InitHexNumber h)
   637         , char '$' >> many hexDigit >>= \h -> comments >> return (InitHexNumber h)
       
   638         , char '@' >> initExpression >>= \c -> comments >> return (InitAddress c)
   629         , try $ string "nil" >> return InitNull
   639         , try $ string "nil" >> return InitNull
       
   640         , itypeCast
   630         , iD >>= return . InitReference
   641         , iD >>= return . InitReference
   631         ]
   642         ]
   632         
   643         
   633     recField = do
   644     recField = do
   634         i <- iD
   645         i <- iD
   664            , Infix (try $ string "shr" >> return (InitBinOp "or")) AssocNone
   675            , Infix (try $ string "shr" >> return (InitBinOp "or")) AssocNone
   665           ]
   676           ]
   666         , [Prefix (try (string "not") >> return (InitPrefixOp "not"))]
   677         , [Prefix (try (string "not") >> return (InitPrefixOp "not"))]
   667         ]
   678         ]
   668 
   679 
       
   680     itypeCast = do
       
   681         t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes
       
   682         i <- parens pas initExpression
       
   683         comments
       
   684         return $ InitTypeCast (Identifier t) i
       
   685         
   669 builtInFunction e = do
   686 builtInFunction e = do
   670     name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin
   687     name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin
   671     spaces
   688     spaces
   672     exprs <- parens pas $ commaSep1 pas $ e
   689     exprs <- parens pas $ commaSep1 pas $ e
   673     spaces
   690     spaces