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 |
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, |
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 ';') |
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 |