1 module PascalParser where |
1 module PascalParser ( |
|
2 pascalUnit |
|
3 ) |
|
4 where |
2 |
5 |
3 import Text.Parsec |
6 import Text.Parsec |
4 import Text.Parsec.Char |
|
5 import Text.Parsec.Token |
7 import Text.Parsec.Token |
6 import Text.Parsec.Language |
|
7 import Text.Parsec.Expr |
8 import Text.Parsec.Expr |
8 import Text.Parsec.Prim |
|
9 import Text.Parsec.Combinator |
|
10 import Text.Parsec.String |
|
11 import Control.Monad |
9 import Control.Monad |
12 import Data.Maybe |
10 import Data.Maybe |
13 import Data.Char |
11 import Data.Char |
14 |
12 |
15 import PascalBasics |
13 import PascalBasics |
16 import PascalUnitSyntaxTree |
14 import PascalUnitSyntaxTree |
17 |
15 |
|
16 knownTypes :: [String] |
18 knownTypes = ["shortstring", "ansistring", "char", "byte"] |
17 knownTypes = ["shortstring", "ansistring", "char", "byte"] |
19 |
18 |
|
19 pascalUnit :: Parsec String u PascalUnit |
20 pascalUnit = do |
20 pascalUnit = do |
21 comments |
21 comments |
22 u <- choice [program, unit, systemUnit, redoUnit] |
22 u <- choice [program, unit, systemUnit, redoUnit] |
23 comments |
23 comments |
24 return u |
24 return u |
25 |
25 |
|
26 iD :: Parsec String u Identifier |
26 iD = do |
27 iD = do |
27 i <- identifier pas |
28 i <- identifier pas |
28 comments |
29 comments |
29 when (i == "not") $ unexpected "'not' used as an identifier" |
30 when (i == "not") $ unexpected "'not' used as an identifier" |
30 return $ Identifier i BTUnknown |
31 return $ Identifier i BTUnknown |
31 |
32 |
|
33 unit :: Parsec String u PascalUnit |
32 unit = do |
34 unit = do |
33 string "unit" >> comments |
35 string' "unit" >> comments |
34 name <- iD |
36 name <- iD |
35 semi pas |
37 void $ semi pas |
36 comments |
38 comments |
37 int <- interface |
39 int <- interface |
38 impl <- implementation |
40 impl <- implementation |
39 comments |
41 comments |
40 return $ Unit name int impl Nothing Nothing |
42 return $ Unit name int impl Nothing Nothing |
41 |
43 |
42 |
44 |
|
45 reference :: Parsec String u Reference |
43 reference = buildExpressionParser table term <?> "reference" |
46 reference = buildExpressionParser table term <?> "reference" |
44 where |
47 where |
45 term = comments >> choice [ |
48 term = comments >> choice [ |
46 parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes |
49 parens pas (liftM RefExpression expression >>= postfixes) >>= postfixes |
47 , try $ typeCast >>= postfixes |
50 , try $ typeCast >>= postfixes |
48 , char '@' >> liftM Address reference >>= postfixes |
51 , char' '@' >> liftM Address reference >>= postfixes |
49 , liftM SimpleReference iD >>= postfixes |
52 , liftM SimpleReference iD >>= postfixes |
50 ] <?> "simple reference" |
53 ] <?> "simple reference" |
51 |
54 |
52 table = [ |
55 table = [ |
53 ] |
56 ] |
54 |
57 |
55 postfixes r = many postfix >>= return . foldl (flip ($)) r |
58 postfixes r = many postfix >>= return . foldl (flip ($)) r |
56 postfix = choice [ |
59 postfix = choice [ |
57 parens pas (option [] parameters) >>= return . FunCall |
60 parens pas (option [] parameters) >>= return . FunCall |
58 , char '^' >> return Dereference |
61 , char' '^' >> return Dereference |
59 , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement |
62 , (brackets pas) (commaSep1 pas $ expression) >>= return . ArrayElement |
60 , (char '.' >> notFollowedBy (char '.')) >> liftM (flip RecordField) reference |
63 , (char' '.' >> notFollowedBy (char' '.')) >> liftM (flip RecordField) reference |
61 ] |
64 ] |
62 |
65 |
63 typeCast = do |
66 typeCast = do |
64 t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes |
67 t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes |
65 e <- parens pas expression |
68 e <- parens pas expression |
66 comments |
69 comments |
67 return $ TypeCast (Identifier t BTUnknown) e |
70 return $ TypeCast (Identifier t BTUnknown) e |
68 |
71 |
|
72 varsDecl1, varsDecl :: Bool -> Parsec String u [TypeVarDeclaration] |
69 varsDecl1 = varsParser sepEndBy1 |
73 varsDecl1 = varsParser sepEndBy1 |
70 varsDecl = varsParser sepEndBy |
74 varsDecl = varsParser sepEndBy |
|
75 |
|
76 varsParser :: |
|
77 (Parsec String u TypeVarDeclaration |
|
78 -> Parsec String u String |
|
79 -> Parsec |
|
80 String u [TypeVarDeclaration]) |
|
81 -> Bool |
|
82 -> Parsec |
|
83 String u [TypeVarDeclaration] |
71 varsParser m endsWithSemi = do |
84 varsParser m endsWithSemi = do |
72 vs <- m (aVarDecl endsWithSemi) (semi pas) |
85 vs <- m (aVarDecl endsWithSemi) (semi pas) |
73 return vs |
86 return vs |
74 |
87 |
|
88 aVarDecl :: Bool -> Parsec String u TypeVarDeclaration |
75 aVarDecl endsWithSemi = do |
89 aVarDecl endsWithSemi = do |
76 isVar <- liftM (== Just "var") $ |
90 isVar <- liftM (== Just "var") $ |
77 if not endsWithSemi then |
91 if not endsWithSemi then |
78 optionMaybe $ choice [ |
92 optionMaybe $ choice [ |
79 try $ string "var" |
93 try $ string "var" |
321 try $ string "inline;" |
340 try $ string "inline;" |
322 , try $ caseInsensitiveString "cdecl;" |
341 , try $ caseInsensitiveString "cdecl;" |
323 , try $ string "overload;" |
342 , try $ string "overload;" |
324 , try $ string "export;" |
343 , try $ string "export;" |
325 , try $ string "varargs;" |
344 , try $ string "varargs;" |
326 , try (string "external") >> comments >> iD >> optional (string "name" >> comments >> stringLiteral pas)>> string ";" |
345 , try (string' "external") >> comments >> iD >> optional (string' "name" >> comments >> stringLiteral pas) >> string' ";" >> return "external" |
327 ] |
346 ] |
328 comments |
347 comments |
329 return d |
348 return d |
330 |
349 |
331 |
350 |
|
351 program :: Parsec String u PascalUnit |
332 program = do |
352 program = do |
333 string "program" |
353 string' "program" |
334 comments |
354 comments |
335 name <- iD |
355 name <- iD |
336 (char ';') |
356 (char' ';') |
337 comments |
357 comments |
338 comments |
358 comments |
339 u <- uses |
359 u <- uses |
340 comments |
360 comments |
341 tv <- typeVarDeclaration True |
361 tv <- typeVarDeclaration True |
342 comments |
362 comments |
343 p <- phrase |
363 p <- phrase |
344 comments |
364 comments |
345 char '.' |
365 char' '.' |
346 comments |
366 comments |
347 return $ Program name (Implementation u (TypesAndVars tv)) p |
367 return $ Program name (Implementation u (TypesAndVars tv)) p |
348 |
368 |
|
369 interface :: Parsec String u Interface |
349 interface = do |
370 interface = do |
350 string "interface" |
371 string' "interface" |
351 comments |
372 comments |
352 u <- uses |
373 u <- uses |
353 comments |
374 comments |
354 tv <- typeVarDeclaration False |
375 tv <- typeVarDeclaration False |
355 comments |
376 comments |
356 return $ Interface u (TypesAndVars tv) |
377 return $ Interface u (TypesAndVars tv) |
357 |
378 |
|
379 implementation :: Parsec String u Implementation |
358 implementation = do |
380 implementation = do |
359 string "implementation" |
381 string' "implementation" |
360 comments |
382 comments |
361 u <- uses |
383 u <- uses |
362 comments |
384 comments |
363 tv <- typeVarDeclaration True |
385 tv <- typeVarDeclaration True |
364 string "end." |
386 string' "end." |
365 comments |
387 comments |
366 return $ Implementation u (TypesAndVars tv) |
388 return $ Implementation u (TypesAndVars tv) |
367 |
389 |
|
390 expression :: Parsec String u Expression |
368 expression = do |
391 expression = do |
369 buildExpressionParser table term <?> "expression" |
392 buildExpressionParser table term <?> "expression" |
370 where |
393 where |
371 term = comments >> choice [ |
394 term = comments >> choice [ |
372 builtInFunction expression >>= \(n, e) -> return $ BuiltInFunCall e (SimpleReference (Identifier n BTUnknown)) |
395 builtInFunction expression >>= \(n, e) -> return $ BuiltInFunCall e (SimpleReference (Identifier n BTUnknown)) |
373 , try (parens pas $ expression >>= \e -> notFollowedBy (comments >> char '.') >> return e) |
396 , try (parens pas $ expression >>= \e -> notFollowedBy (comments >> char' '.') >> return e) |
374 , brackets pas (commaSep pas iD) >>= return . SetExpression |
397 , brackets pas (commaSep pas iD) >>= return . SetExpression |
375 , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . NumberLiteral . show) i |
398 , try $ integer pas >>= \i -> notFollowedBy (char' '.') >> (return . NumberLiteral . show) i |
376 , float pas >>= return . FloatLiteral . show |
399 , float pas >>= return . FloatLiteral . show |
377 , try $ integer pas >>= return . NumberLiteral . show |
400 , try $ integer pas >>= return . NumberLiteral . show |
378 , try (string "_S" >> stringLiteral pas) >>= return . StringLiteral |
401 , try (string' "_S" >> stringLiteral pas) >>= return . StringLiteral |
379 , try (string "_P" >> stringLiteral pas) >>= return . PCharLiteral |
402 , try (string' "_P" >> stringLiteral pas) >>= return . PCharLiteral |
380 , stringLiteral pas >>= return . strOrChar |
403 , stringLiteral pas >>= return . strOrChar |
381 , try (string "#$") >> many hexDigit >>= \c -> comments >> return (HexCharCode c) |
404 , try (string' "#$") >> many hexDigit >>= \c -> comments >> return (HexCharCode c) |
382 , char '#' >> many digit >>= \c -> comments >> return (CharCode c) |
405 , char' '#' >> many digit >>= \c -> comments >> return (CharCode c) |
383 , char '$' >> many hexDigit >>= \h -> comments >> return (HexNumber h) |
406 , char' '$' >> many hexDigit >>= \h -> comments >> return (HexNumber h) |
384 --, char '-' >> expression >>= return . PrefixOp "-" |
407 --, char' '-' >> expression >>= return . PrefixOp "-" |
385 , char '-' >> reference >>= return . PrefixOp "-" . Reference |
408 , char' '-' >> reference >>= return . PrefixOp "-" . Reference |
386 , (try $ string "not" >> notFollowedBy comments) >> unexpected "'not'" |
409 , (try $ string' "not" >> notFollowedBy comments) >> unexpected "'not'" |
387 , try $ string "nil" >> return Null |
410 , try $ string' "nil" >> return Null |
388 , reference >>= return . Reference |
411 , reference >>= return . Reference |
389 ] <?> "simple expression" |
412 ] <?> "simple expression" |
390 |
413 |
391 table = [ |
414 table = [ |
392 [ Prefix (reservedOp pas "not">> return (PrefixOp "not")) |
415 [ Prefix (reservedOp pas "not">> return (PrefixOp "not")) |
393 , Prefix (try (char '-') >> return (PrefixOp "-"))] |
416 , Prefix (try (char' '-') >> return (PrefixOp "-"))] |
394 , |
417 , |
395 [ Infix (char '*' >> return (BinOp "*")) AssocLeft |
418 [ Infix (char' '*' >> return (BinOp "*")) AssocLeft |
396 , Infix (char '/' >> return (BinOp "/")) AssocLeft |
419 , Infix (char' '/' >> return (BinOp "/")) AssocLeft |
397 , Infix (try (string "div") >> return (BinOp "div")) AssocLeft |
420 , Infix (try (string' "div") >> return (BinOp "div")) AssocLeft |
398 , Infix (try (string "mod") >> return (BinOp "mod")) AssocLeft |
421 , Infix (try (string' "mod") >> return (BinOp "mod")) AssocLeft |
399 , Infix (try (string "in") >> return (BinOp "in")) AssocNone |
422 , Infix (try (string' "in") >> return (BinOp "in")) AssocNone |
400 , Infix (try $ string "and" >> return (BinOp "and")) AssocLeft |
423 , Infix (try $ string' "and" >> return (BinOp "and")) AssocLeft |
401 , Infix (try $ string "shl" >> return (BinOp "shl")) AssocLeft |
424 , Infix (try $ string' "shl" >> return (BinOp "shl")) AssocLeft |
402 , Infix (try $ string "shr" >> return (BinOp "shr")) AssocLeft |
425 , Infix (try $ string' "shr" >> return (BinOp "shr")) AssocLeft |
403 ] |
426 ] |
404 , [ Infix (char '+' >> return (BinOp "+")) AssocLeft |
427 , [ Infix (char' '+' >> return (BinOp "+")) AssocLeft |
405 , Infix (char '-' >> return (BinOp "-")) AssocLeft |
428 , Infix (char' '-' >> return (BinOp "-")) AssocLeft |
406 , Infix (try $ string "or" >> return (BinOp "or")) AssocLeft |
429 , Infix (try $ string' "or" >> return (BinOp "or")) AssocLeft |
407 , Infix (try $ string "xor" >> return (BinOp "xor")) AssocLeft |
430 , Infix (try $ string' "xor" >> return (BinOp "xor")) AssocLeft |
408 ] |
431 ] |
409 , [ Infix (try (string "<>") >> return (BinOp "<>")) AssocNone |
432 , [ Infix (try (string' "<>") >> return (BinOp "<>")) AssocNone |
410 , Infix (try (string "<=") >> return (BinOp "<=")) AssocNone |
433 , Infix (try (string' "<=") >> return (BinOp "<=")) AssocNone |
411 , Infix (try (string ">=") >> return (BinOp ">=")) AssocNone |
434 , Infix (try (string' ">=") >> return (BinOp ">=")) AssocNone |
412 , Infix (char '<' >> return (BinOp "<")) AssocNone |
435 , Infix (char' '<' >> return (BinOp "<")) AssocNone |
413 , Infix (char '>' >> return (BinOp ">")) AssocNone |
436 , Infix (char' '>' >> return (BinOp ">")) AssocNone |
414 ] |
437 ] |
415 {-, [ Infix (try $ string "shl" >> return (BinOp "shl")) AssocNone |
438 {-, [ Infix (try $ string' "shl" >> return (BinOp "shl")) AssocNone |
416 , Infix (try $ string "shr" >> return (BinOp "shr")) AssocNone |
439 , Infix (try $ string' "shr" >> return (BinOp "shr")) AssocNone |
417 ] |
440 ] |
418 , [ |
441 , [ |
419 Infix (try $ string "or" >> return (BinOp "or")) AssocLeft |
442 Infix (try $ string' "or" >> return (BinOp "or")) AssocLeft |
420 , Infix (try $ string "xor" >> return (BinOp "xor")) AssocLeft |
443 , Infix (try $ string' "xor" >> return (BinOp "xor")) AssocLeft |
421 ]-} |
444 ]-} |
422 , [ |
445 , [ |
423 Infix (char '=' >> return (BinOp "=")) AssocNone |
446 Infix (char' '=' >> return (BinOp "=")) AssocNone |
424 ] |
447 ] |
425 ] |
448 ] |
426 strOrChar [a] = CharCode . show . ord $ a |
449 strOrChar [a] = CharCode . show . ord $ a |
427 strOrChar a = StringLiteral a |
450 strOrChar a = StringLiteral a |
428 |
451 |
|
452 phrasesBlock :: Parsec String u Phrase |
429 phrasesBlock = do |
453 phrasesBlock = do |
430 try $ string "begin" |
454 try $ string' "begin" |
431 comments |
455 comments |
432 p <- manyTill phrase (try $ string "end" >> notFollowedBy alphaNum) |
456 p <- manyTill phrase (try $ string' "end" >> notFollowedBy alphaNum) |
433 comments |
457 comments |
434 return $ Phrases p |
458 return $ Phrases p |
435 |
459 |
|
460 phrase :: Parsec String u Phrase |
436 phrase = do |
461 phrase = do |
437 o <- choice [ |
462 o <- choice [ |
438 phrasesBlock |
463 phrasesBlock |
439 , ifBlock |
464 , ifBlock |
440 , whileCycle |
465 , whileCycle |
441 , repeatCycle |
466 , repeatCycle |
442 , switchCase |
467 , switchCase |
443 , withBlock |
468 , withBlock |
444 , forCycle |
469 , forCycle |
445 , (try $ reference >>= \r -> string ":=" >> return r) >>= \r -> comments >> expression >>= return . Assignment r |
470 , (try $ reference >>= \r -> string' ":=" >> return r) >>= \r -> comments >> expression >>= return . Assignment r |
446 , builtInFunction expression >>= \(n, e) -> return $ BuiltInFunctionCall e (SimpleReference (Identifier n BTUnknown)) |
471 , builtInFunction expression >>= \(n, e) -> return $ BuiltInFunctionCall e (SimpleReference (Identifier n BTUnknown)) |
447 , procCall |
472 , procCall |
448 , char ';' >> comments >> return NOP |
473 , char' ';' >> comments >> return NOP |
449 ] |
474 ] |
450 optional $ char ';' |
475 optional $ char' ';' |
451 comments |
476 comments |
452 return o |
477 return o |
453 |
478 |
|
479 ifBlock :: Parsec String u Phrase |
454 ifBlock = do |
480 ifBlock = do |
455 try $ string "if" >> notFollowedBy (alphaNum <|> char '_') |
481 try $ string "if" >> notFollowedBy (alphaNum <|> char '_') |
456 comments |
482 comments |
457 e <- expression |
483 e <- expression |
458 comments |
484 comments |
459 string "then" |
485 string' "then" |
460 comments |
486 comments |
461 o1 <- phrase |
487 o1 <- phrase |
462 comments |
488 comments |
463 o2 <- optionMaybe $ do |
489 o2 <- optionMaybe $ do |
464 try $ string "else" >> space |
490 try $ string' "else" >> void space |
465 comments |
491 comments |
466 o <- option NOP phrase |
492 o <- option NOP phrase |
467 comments |
493 comments |
468 return o |
494 return o |
469 return $ IfThenElse e o1 o2 |
495 return $ IfThenElse e o1 o2 |
470 |
496 |
|
497 whileCycle :: Parsec String u Phrase |
471 whileCycle = do |
498 whileCycle = do |
472 try $ string "while" |
499 try $ string' "while" |
473 comments |
500 comments |
474 e <- expression |
501 e <- expression |
475 comments |
502 comments |
476 string "do" |
503 string' "do" |
477 comments |
504 comments |
478 o <- phrase |
505 o <- phrase |
479 return $ WhileCycle e o |
506 return $ WhileCycle e o |
480 |
507 |
|
508 withBlock :: Parsec String u Phrase |
481 withBlock = do |
509 withBlock = do |
482 try $ string "with" >> space |
510 try $ string' "with" >> void space |
483 comments |
511 comments |
484 rs <- (commaSep1 pas) reference |
512 rs <- (commaSep1 pas) reference |
485 comments |
513 comments |
486 string "do" |
514 string' "do" |
487 comments |
515 comments |
488 o <- phrase |
516 o <- phrase |
489 return $ foldr WithBlock o rs |
517 return $ foldr WithBlock o rs |
490 |
518 |
|
519 repeatCycle :: Parsec String u Phrase |
491 repeatCycle = do |
520 repeatCycle = do |
492 try $ string "repeat" >> space |
521 try $ string' "repeat" >> void space |
493 comments |
522 comments |
494 o <- many phrase |
523 o <- many phrase |
495 string "until" |
524 string' "until" |
496 comments |
525 comments |
497 e <- expression |
526 e <- expression |
498 comments |
527 comments |
499 return $ RepeatCycle e o |
528 return $ RepeatCycle e o |
500 |
529 |
|
530 forCycle :: Parsec String u Phrase |
501 forCycle = do |
531 forCycle = do |
502 try $ string "for" >> space |
532 try $ string' "for" >> void space |
503 comments |
533 comments |
504 i <- iD |
534 i <- iD |
505 comments |
535 comments |
506 string ":=" |
536 string' ":=" |
507 comments |
537 comments |
508 e1 <- expression |
538 e1 <- expression |
509 comments |
539 comments |
510 up <- liftM (== Just "to") $ |
540 up <- liftM (== Just "to") $ |
511 optionMaybe $ choice [ |
541 optionMaybe $ choice [ |
512 try $ string "to" |
542 try $ string "to" |
513 , try $ string "downto" |
543 , try $ string "downto" |
514 ] |
544 ] |
515 --choice [string "to", string "downto"] |
545 --choice [string' "to", string' "downto"] |
516 comments |
546 comments |
517 e2 <- expression |
547 e2 <- expression |
518 comments |
548 comments |
519 string "do" |
549 string' "do" |
520 comments |
550 comments |
521 p <- phrase |
551 p <- phrase |
522 comments |
552 comments |
523 return $ ForCycle i e1 e2 p up |
553 return $ ForCycle i e1 e2 p up |
524 |
554 |
|
555 switchCase :: Parsec String u Phrase |
525 switchCase = do |
556 switchCase = do |
526 try $ string "case" |
557 try $ string' "case" |
527 comments |
558 comments |
528 e <- expression |
559 e <- expression |
529 comments |
560 comments |
530 string "of" |
561 string' "of" |
531 comments |
562 comments |
532 cs <- many1 aCase |
563 cs <- many1 aCase |
533 o2 <- optionMaybe $ do |
564 o2 <- optionMaybe $ do |
534 try $ string "else" >> notFollowedBy alphaNum |
565 try $ string' "else" >> notFollowedBy alphaNum |
535 comments |
566 comments |
536 o <- many phrase |
567 o <- many phrase |
537 comments |
568 comments |
538 return o |
569 return o |
539 string "end" |
570 string' "end" |
540 comments |
571 comments |
541 return $ SwitchCase e cs o2 |
572 return $ SwitchCase e cs o2 |
542 where |
573 where |
543 aCase = do |
574 aCase = do |
544 e <- (commaSep pas) $ (liftM InitRange rangeDecl <|> initExpression) |
575 e <- (commaSep pas) $ (liftM InitRange rangeDecl <|> initExpression) |
545 comments |
576 comments |
546 char ':' |
577 char' ':' |
547 comments |
578 comments |
548 p <- phrase |
579 p <- phrase |
549 comments |
580 comments |
550 return (e, p) |
581 return (e, p) |
551 |
582 |
|
583 procCall :: Parsec String u Phrase |
552 procCall = do |
584 procCall = do |
553 r <- reference |
585 r <- reference |
554 p <- option [] $ (parens pas) parameters |
586 p <- option [] $ (parens pas) parameters |
555 return $ ProcCall r p |
587 return $ ProcCall r p |
556 |
588 |
|
589 parameters :: Parsec String u [Expression] |
557 parameters = (commaSep pas) expression <?> "parameters" |
590 parameters = (commaSep pas) expression <?> "parameters" |
558 |
591 |
|
592 functionBody :: Parsec String u (TypesAndVars, Phrase) |
559 functionBody = do |
593 functionBody = do |
560 tv <- typeVarDeclaration True |
594 tv <- typeVarDeclaration True |
561 comments |
595 comments |
562 p <- phrasesBlock |
596 p <- phrasesBlock |
563 char ';' |
597 char' ';' |
564 comments |
598 comments |
565 return (TypesAndVars tv, p) |
599 return (TypesAndVars tv, p) |
566 |
600 |
|
601 uses :: Parsec String u Uses |
567 uses = liftM Uses (option [] u) |
602 uses = liftM Uses (option [] u) |
568 where |
603 where |
569 u = do |
604 u = do |
570 string "uses" |
605 string' "uses" |
571 comments |
606 comments |
572 u <- (iD >>= \i -> comments >> return i) `sepBy1` (char ',' >> comments) |
607 ulist <- (iD >>= \i -> comments >> return i) `sepBy1` (char' ',' >> comments) |
573 char ';' |
608 char' ';' |
574 comments |
609 comments |
575 return u |
610 return ulist |
576 |
611 |
|
612 initExpression :: Parsec String u InitExpression |
577 initExpression = buildExpressionParser table term <?> "initialization expression" |
613 initExpression = buildExpressionParser table term <?> "initialization expression" |
578 where |
614 where |
579 term = comments >> choice [ |
615 term = comments >> choice [ |
580 liftM (uncurry BuiltInFunction) $ builtInFunction initExpression |
616 liftM (uncurry BuiltInFunction) $ builtInFunction initExpression |
581 , try $ brackets pas (commaSep pas $ initExpression) >>= return . InitSet |
617 , try $ brackets pas (commaSep pas $ initExpression) >>= return . InitSet |
582 , try $ parens pas (commaSep pas $ initExpression) >>= \ia -> when ((notRecord $ head ia) && (null $ tail ia)) mzero >> return (InitArray ia) |
618 , try $ parens pas (commaSep pas $ initExpression) >>= \ia -> when ((notRecord $ head ia) && (null $ tail ia)) mzero >> return (InitArray ia) |
583 , try $ parens pas (sepEndBy recField (char ';' >> comments)) >>= return . InitRecord |
619 , try $ parens pas (sepEndBy recField (char' ';' >> comments)) >>= return . InitRecord |
584 , parens pas initExpression |
620 , parens pas initExpression |
585 , try $ integer pas >>= \i -> notFollowedBy (char '.') >> (return . InitNumber . show) i |
621 , try $ integer pas >>= \i -> notFollowedBy (char' '.') >> (return . InitNumber . show) i |
586 , try $ float pas >>= return . InitFloat . show |
622 , try $ float pas >>= return . InitFloat . show |
587 , try $ integer pas >>= return . InitNumber . show |
623 , try $ integer pas >>= return . InitNumber . show |
588 , stringLiteral pas >>= return . InitString |
624 , stringLiteral pas >>= return . InitString |
589 , char '#' >> many digit >>= \c -> comments >> return (InitChar c) |
625 , char' '#' >> many digit >>= \c -> comments >> return (InitChar c) |
590 , char '$' >> many hexDigit >>= \h -> comments >> return (InitHexNumber h) |
626 , char' '$' >> many hexDigit >>= \h -> comments >> return (InitHexNumber h) |
591 , char '@' >> initExpression >>= \c -> comments >> return (InitAddress c) |
627 , char' '@' >> initExpression >>= \c -> comments >> return (InitAddress c) |
592 , try $ string "nil" >> return InitNull |
628 , try $ string' "nil" >> return InitNull |
593 , itypeCast |
629 , itypeCast |
594 , iD >>= return . InitReference |
630 , iD >>= return . InitReference |
595 ] |
631 ] |
596 |
632 |
597 notRecord (InitRecord _) = False |
633 notRecord (InitRecord _) = False |
598 notRecord _ = True |
634 notRecord _ = True |
599 |
635 |
600 recField = do |
636 recField = do |
601 i <- iD |
637 i <- iD |
602 spaces |
638 spaces |
603 char ':' |
639 char' ':' |
604 spaces |
640 spaces |
605 e <- initExpression |
641 e <- initExpression |
606 spaces |
642 spaces |
607 return (i ,e) |
643 return (i ,e) |
608 |
644 |
609 table = [ |
645 table = [ |
610 [ |
646 [ |
611 Prefix (char '-' >> return (InitPrefixOp "-")) |
647 Prefix (char' '-' >> return (InitPrefixOp "-")) |
612 ,Prefix (try (string "not") >> return (InitPrefixOp "not")) |
648 ,Prefix (try (string' "not") >> return (InitPrefixOp "not")) |
613 ] |
649 ] |
614 , [ Infix (char '*' >> return (InitBinOp "*")) AssocLeft |
650 , [ Infix (char' '*' >> return (InitBinOp "*")) AssocLeft |
615 , Infix (char '/' >> return (InitBinOp "/")) AssocLeft |
651 , Infix (char' '/' >> return (InitBinOp "/")) AssocLeft |
616 , Infix (try (string "div") >> return (InitBinOp "div")) AssocLeft |
652 , Infix (try (string' "div") >> return (InitBinOp "div")) AssocLeft |
617 , Infix (try (string "mod") >> return (InitBinOp "mod")) AssocLeft |
653 , Infix (try (string' "mod") >> return (InitBinOp "mod")) AssocLeft |
618 , Infix (try $ string "and" >> return (InitBinOp "and")) AssocLeft |
654 , Infix (try $ string' "and" >> return (InitBinOp "and")) AssocLeft |
619 , Infix (try $ string "shl" >> return (InitBinOp "shl")) AssocNone |
655 , Infix (try $ string' "shl" >> return (InitBinOp "shl")) AssocNone |
620 , Infix (try $ string "shr" >> return (InitBinOp "shr")) AssocNone |
656 , Infix (try $ string' "shr" >> return (InitBinOp "shr")) AssocNone |
621 ] |
657 ] |
622 , [ Infix (char '+' >> return (InitBinOp "+")) AssocLeft |
658 , [ Infix (char' '+' >> return (InitBinOp "+")) AssocLeft |
623 , Infix (char '-' >> return (InitBinOp "-")) AssocLeft |
659 , Infix (char' '-' >> return (InitBinOp "-")) AssocLeft |
624 , Infix (try $ string "or" >> return (InitBinOp "or")) AssocLeft |
660 , Infix (try $ string' "or" >> return (InitBinOp "or")) AssocLeft |
625 , Infix (try $ string "xor" >> return (InitBinOp "xor")) AssocLeft |
661 , Infix (try $ string' "xor" >> return (InitBinOp "xor")) AssocLeft |
626 ] |
662 ] |
627 , [ Infix (try (string "<>") >> return (InitBinOp "<>")) AssocNone |
663 , [ Infix (try (string' "<>") >> return (InitBinOp "<>")) AssocNone |
628 , Infix (try (string "<=") >> return (InitBinOp "<=")) AssocNone |
664 , Infix (try (string' "<=") >> return (InitBinOp "<=")) AssocNone |
629 , Infix (try (string ">=") >> return (InitBinOp ">=")) AssocNone |
665 , Infix (try (string' ">=") >> return (InitBinOp ">=")) AssocNone |
630 , Infix (char '<' >> return (InitBinOp "<")) AssocNone |
666 , Infix (char' '<' >> return (InitBinOp "<")) AssocNone |
631 , Infix (char '>' >> return (InitBinOp ">")) AssocNone |
667 , Infix (char' '>' >> return (InitBinOp ">")) AssocNone |
632 , Infix (char '=' >> return (InitBinOp "=")) AssocNone |
668 , Infix (char' '=' >> return (InitBinOp "=")) AssocNone |
633 ] |
669 ] |
634 {--, [ Infix (try $ string "and" >> return (InitBinOp "and")) AssocLeft |
670 {--, [ Infix (try $ string' "and" >> return (InitBinOp "and")) AssocLeft |
635 , Infix (try $ string "or" >> return (InitBinOp "or")) AssocLeft |
671 , Infix (try $ string' "or" >> return (InitBinOp "or")) AssocLeft |
636 , Infix (try $ string "xor" >> return (InitBinOp "xor")) AssocLeft |
672 , Infix (try $ string' "xor" >> return (InitBinOp "xor")) AssocLeft |
637 ] |
673 ] |
638 , [ Infix (try $ string "shl" >> return (InitBinOp "shl")) AssocNone |
674 , [ Infix (try $ string' "shl" >> return (InitBinOp "shl")) AssocNone |
639 , Infix (try $ string "shr" >> return (InitBinOp "shr")) AssocNone |
675 , Infix (try $ string' "shr" >> return (InitBinOp "shr")) AssocNone |
640 ]--} |
676 ]--} |
641 --, [Prefix (try (string "not") >> return (InitPrefixOp "not"))] |
677 --, [Prefix (try (string' "not") >> return (InitPrefixOp "not"))] |
642 ] |
678 ] |
643 |
679 |
644 itypeCast = do |
680 itypeCast = do |
645 t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes |
681 t <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) knownTypes |
646 i <- parens pas initExpression |
682 i <- parens pas initExpression |
647 comments |
683 comments |
648 return $ InitTypeCast (Identifier t BTUnknown) i |
684 return $ InitTypeCast (Identifier t BTUnknown) i |
649 |
685 |
|
686 builtInFunction :: Parsec String u a -> Parsec String u (String, [a]) |
650 builtInFunction e = do |
687 builtInFunction e = do |
651 name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin |
688 name <- choice $ map (\s -> try $ caseInsensitiveString s >>= \i -> notFollowedBy alphaNum >> return i) builtin |
652 spaces |
689 spaces |
653 exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e |
690 exprs <- option [] $ parens pas $ option [] $ commaSep1 pas $ e |
654 spaces |
691 spaces |
655 return (name, exprs) |
692 return (name, exprs) |
656 |
693 |
|
694 systemUnit :: Parsec String u PascalUnit |
657 systemUnit = do |
695 systemUnit = do |
658 string "system;" |
696 string' "system;" |
659 comments |
697 comments |
660 string "type" |
698 string' "type" |
661 comments |
699 comments |
662 t <- typesDecl |
700 t <- typesDecl |
663 string "var" |
701 string' "var" |
664 v <- varsDecl True |
702 v <- varsDecl True |
665 return $ System (t ++ v) |
703 return $ System (t ++ v) |
666 |
704 |
|
705 redoUnit :: Parsec String u PascalUnit |
667 redoUnit = do |
706 redoUnit = do |
668 string "redo;" |
707 string' "redo;" |
669 comments |
708 comments |
670 string "type" |
709 string' "type" |
671 comments |
710 comments |
672 t <- typesDecl |
711 t <- typesDecl |
673 string "var" |
712 string' "var" |
674 v <- varsDecl True |
713 v <- varsDecl True |
675 return $ Redo (t ++ v) |
714 return $ Redo (t ++ v) |
676 |
715 |