2 -- mc-
3.bnf grammar and associated actions for mcp
3.
4 -- Copyright
(C
) 2015-
2024 Free Software Foundation, Inc
.
5 -- Contributed by Gaius Mulley <gaius
.mulley@southwales
.ac
.uk>
.
7 -- This file is part of GNU Modula-
2.
9 -- GNU Modula-
2 is free software; you can redistribute it and/or modify
10 -- it under the terms of the GNU General Public License as published by
11 -- the Free Software Foundation; either version
3, or
(at your option
)
14 -- GNU Modula-
2 is distributed in the hope that it will be useful, but
15 -- WITHOUT ANY WARRANTY; without even the implied warranty of
16 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
. See the GNU
17 -- General Public License for more details
.
19 -- You should have received a copy of the GNU General Public License
20 -- along with GNU Modula-
2; see the file COPYING
3. If not see
21 -- <http
://www.gnu.org/licenses/>.
23 (* output from mc-
3.bnf, automatically generated do not edit
.
25 Copyright
(C
) 2015-
2024 Free Software Foundation, Inc
.
26 Contributed by Gaius Mulley <gaius
.mulley@southwales
.ac
.uk>
.
28 This file is part of GNU Modula-
2.
30 GNU Modula-
2 is free software; you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation; either version
3, or
(at your option
)
35 GNU Modula-
2 is distributed in the hope that it will be useful, but
36 WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
. See the GNU
38 General Public License for more details
.
40 You should have received a copy of the GNU General Public License
41 along with GNU Modula-
2; see the file COPYING
. If not,
42 see <https
://www.gnu.org/licenses/>. *)
44 IMPLEMENTATION MODULE mcp
3 ;
46 FROM DynamicStrings IMPORT String, InitString, KillString, Mark,
49 FROM mcError IMPORT errorStringAt ;
50 FROM nameKey IMPORT NulName, Name, makekey, makeKey ;
51 FROM mcPrintf IMPORT printf
0, printf
1 ;
52 FROM mcDebug IMPORT assert ;
53 FROM mcReserved IMPORT toktype ;
54 FROM mcMetaError IMPORT metaError
1, metaError
2 ;
55 FROM mcStack IMPORT stack ;
59 FROM mcLexBuf IMPORT currentstring, currenttoken, getToken, insertToken,
60 insertTokenAndRewind, getTokenNo ;
62 FROM decl IMPORT node, lookupDef, lookupImp, lookupModule, getSymName,
64 enterScope, leaveScope,
65 putType, lookupSym, isDef, makeSubrange,
66 makeSet, makePointer, makeProcType,
67 putReturnType, putOptReturn,
68 addParameter, paramEnter, paramLeave,
69 makeVarargs, makeVarParameter, makeNonVarParameter,
70 putSubrangeType, putConst,
71 makeArray, putUnbounded, getCardinal,
72 makeRecord, isRecord, isRecordField, isVarientField, makeVarient,
73 addFieldsToRecord, isVarient, buildVarientSelector,
74 buildVarientFieldRecord, makeVarDecl, addOptParameter,
75 makeIdentList, putIdent, addVarParameters, addNonVarParameters,
76 lookupInScope, import, lookupExported, isImp, isModule, isConst,
77 makeLiteralInt, makeLiteralReal, makeString, getBuiltinConst,
78 getNextEnum, resetEnumPos, makeConstExp, setConstExpComplete,
79 makeEnum, makeEnumField, setNoReturn ;
87 WasNoError : BOOLEAN ;
103 PROCEDURE push
(n
: node
) : node ;
105 RETURN mcStack
.push
(stk, n
)
113 PROCEDURE pop
() : node ;
115 RETURN mcStack
.pop
(stk
)
123 PROCEDURE replace
(n
: node
) : node ;
125 RETURN mcStack
.replace
(stk, n
)
130 peep - returns the top node on the stack without removing it
.
133 PROCEDURE peep
() : node ;
140 depth - returns the depth of the stack
.
143 PROCEDURE depth
() : CARDINAL ;
145 RETURN mcStack
.depth
(stk
)
153 PROCEDURE checkDuplicate
(b
: BOOLEAN
) ;
159 PROCEDURE ErrorString
(s
: String
) ;
161 errorStringAt
(s, getTokenNo
()) ;
166 PROCEDURE ErrorArray
(a
: ARRAY OF CHAR
) ;
168 ErrorString
(InitString
(a
))
173 checkParameterAttribute -
176 PROCEDURE checkParameterAttribute ;
178 IF makeKey
("unused") # curident
180 metaError
1 ('attribute
{%
1k
} is not allowed in the formal parameter section, currently only unused is allowed', curident
)
182 END checkParameterAttribute ;
186 checkReturnAttribute -
189 PROCEDURE checkReturnAttribute ;
191 IF makeKey
("noreturn") # curident
193 metaError
1 ('attribute
{%
1k
} is not allowed in the procedure return type, only noreturn is allowed', curident
)
195 END checkReturnAttribute ;
202 PROCEDURE pushNunbounded
(c
: CARDINAL
) ;
210 subrange := makeSubrange
(NIL, NIL
) ;
211 putSubrangeType
(subrange, getCardinal
()) ;
213 array := makeArray
(subrange, type
) ;
214 putUnbounded
(array
) ;
215 type := push
(array
) ;
222 makeIndexedArray - builds and returns an array of type, t, with, c, indices
.
225 PROCEDURE makeIndexedArray
(c
: CARDINAL; t
: node
) : node ;
230 t := makeArray
(pop
(), t
) ;
234 END makeIndexedArray ;
238 importInto - from, m, import, name, into module, current
.
239 It checks to see if curident is an enumeration type
240 and if so automatically includes all enumeration fields
244 PROCEDURE importInto
(m
: node; name
: Name; current
: node
) ;
249 assert
(isDef
(current
) OR isModule
(current
) OR isImp
(current
)) ;
250 s := lookupExported
(m, name
) ;
253 metaError
2 ('
{%
1k
} was not exported from definition module
{%
2a
}', name, m
)
255 o := import
(current, s
) ;
258 metaError
2 ('
{%
1ad
} cannot be imported into the current module as it causes a name clash with
{%
2ad
}',
266 checkEndName - if module does not have, name, then issue an error containing, desc
.
269 PROCEDURE checkEndName
(module
: node; name
: Name; desc
: ARRAY OF CHAR
) ;
273 IF getSymName
(module
)#name
275 s := InitString
('inconsistent module name found with this '
) ;
276 s := ConCat
(s, Mark
(InitString
(desc
))) ;
281 % declaration mcp
3 begin
285 SyntaxError - after a syntax error we skip all tokens up until we reach
289 PROCEDURE SyntaxError
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
294 printf
0('
\nskipping token *** '
)
297 yes the ORD
(currenttoken
) looks ugly, but it is *much* safer than
298 using currenttoken<sometok as a change to the ordering of the
299 token declarations below would cause this to break
. Using ORD
() we are
300 immune from such changes
302 WHILE NOT
(((ORD
(currenttoken
)<
32) AND
(currenttoken IN stopset
0)) OR
303 ((ORD
(currenttoken
)>
=32) AND
(ORD
(currenttoken
)<
64) AND
(currenttoken IN stopset
1)) OR
304 ((ORD
(currenttoken
)>
=64) AND
(currenttoken IN stopset
2)))
319 PROCEDURE SyntaxCheck
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
321 (* and again
(see above re
: ORD
)
323 IF NOT
(((ORD
(currenttoken
)<
32) AND
(currenttoken IN stopset
0)) OR
324 ((ORD
(currenttoken
)>
=32) AND
(ORD
(currenttoken
)<
64) AND
(currenttoken IN stopset
1)) OR
325 ((ORD
(currenttoken
)>
=64) AND
(currenttoken IN stopset
2)))
327 SyntaxError
(stopset
0, stopset
1, stopset
2)
333 WarnMissingToken - generates a warning message about a missing token, t
.
336 PROCEDURE WarnMissingToken
(t
: toktype
) ;
355 str := DescribeStop
(s
0, s
1, s
2) ;
357 str := ConCat
(InitString
('syntax error,'
), Mark
(str
)) ;
358 errorStringAt
(str, getTokenNo
())
359 END WarnMissingToken ;
363 MissingToken - generates a warning message about a missing token, t
.
366 PROCEDURE MissingToken
(t
: toktype
) ;
368 WarnMissingToken
(t
) ;
369 IF
(t#identtok
) AND
(t#integertok
) AND
(t#realtok
) AND
(t#stringtok
)
373 printf
0 ('inserting token
\n'
)
384 PROCEDURE CheckAndInsert
(t
: toktype; stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) : BOOLEAN ;
386 IF
((ORD
(t
)<
32) AND
(t IN stopset
0)) OR
387 ((ORD
(t
)>
=32) AND
(ORD
(t
)<
64) AND
(t IN stopset
1)) OR
388 ((ORD
(t
)>
=64) AND
(t IN stopset
2))
390 WarnMissingToken
(t
) ;
391 insertTokenAndRewind
(t
) ;
403 PROCEDURE InStopSet
(t
: toktype; stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) : BOOLEAN ;
405 IF
((ORD
(t
)<
32) AND
(t IN stopset
0)) OR
406 ((ORD
(t
)>
=32) AND
(ORD
(t
)<
64) AND
(t IN stopset
1)) OR
407 ((ORD
(t
)>
=64) AND
(t IN stopset
2))
417 PeepToken - peep token checks to see whether the stopset is satisfied by currenttoken
418 If it is not then it will insert a token providing the token
419 is one of ;
] ) } . OF END ,
421 if the stopset contains <identtok> then we do not insert a token
424 PROCEDURE PeepToken
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
426 (* and again
(see above re
: ORD
)
428 IF
(NOT
(((ORD
(currenttoken
)<
32) AND
(currenttoken IN stopset
0)) OR
429 ((ORD
(currenttoken
)>
=32) AND
(ORD
(currenttoken
)<
64) AND
(currenttoken IN stopset
1)) OR
430 ((ORD
(currenttoken
)>
=64) AND
(currenttoken IN stopset
2)))) AND
431 (NOT InStopSet
(identtok, stopset
0, stopset
1, stopset
2))
433 (* SyntaxCheck would fail since currentoken is not part of the stopset
434 we check to see whether any of currenttoken might be a commonly omitted token *
)
435 IF CheckAndInsert
(semicolontok, stopset
0, stopset
1, stopset
2) OR
436 CheckAndInsert
(rsbratok, stopset
0, stopset
1, stopset
2) OR
437 CheckAndInsert
(rparatok, stopset
0, stopset
1, stopset
2) OR
438 CheckAndInsert
(rcbratok, stopset
0, stopset
1, stopset
2) OR
439 CheckAndInsert
(periodtok, stopset
0, stopset
1, stopset
2) OR
440 CheckAndInsert
(oftok, stopset
0, stopset
1, stopset
2) OR
441 CheckAndInsert
(endtok, stopset
0, stopset
1, stopset
2) OR
442 CheckAndInsert
(commatok, stopset
0, stopset
1, stopset
2)
453 PROCEDURE Expect
(t
: toktype; stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
460 PeepToken
(stopset
0, stopset
1, stopset
2)
465 SyntaxCheck
(stopset
0, stopset
1, stopset
2)
470 CompilationUnit - returns TRUE if the input was correct enough to parse
474 PROCEDURE CompilationUnit
() : BOOLEAN ;
476 stk := mcStack
.init
() ;
478 FileUnit
(SetOfStop
0{eoftok
}, SetOfStop
1{}, SetOfStop
2{}) ;
481 END CompilationUnit ;
485 Ident - error checking varient of Ident
488 PROCEDURE Ident
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
490 curident := makekey
(currentstring
) ;
491 Expect
(identtok, stopset
0, stopset
1, stopset
2)
499 PROCEDURE string
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
501 curstring := makekey
(currentstring
) ;
502 Expect
(stringtok, stopset
0, stopset
1, stopset
2)
510 PROCEDURE Integer
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
512 Expect
(integertok, stopset
0, stopset
1, stopset
2)
520 PROCEDURE Real
(stopset
0: SetOfStop
0; stopset
1: SetOfStop
1; stopset
2: SetOfStop
2) ;
522 Expect
(realtok, stopset
0, stopset
1, stopset
2)
528 error 'ErrorArray' 'ErrorString'
529 tokenfunc 'currenttoken'
531 token '' eoftok -- internal token
536 token '
:=' becomestok
537 token '&' ambersandtok
540 token
";" semicolontok
543 token '
[' lsbratok -- left square brackets
544 token '
]' rsbratok -- right square brackets
545 token '
{' lcbratok -- left curly brackets
546 token '
}' rcbratok -- right curly brackets
548 token
"'" singlequotetok
553 token '<>' lessgreatertok
554 token '<
=' lessequaltok
555 token '>
=' greaterequaltok
556 token '<*' ldirectivetok
557 token '*>' rdirectivetok
558 token '
..' periodperiodtok
560 token '
"' doublequotestok
563 token 'ARRAY' arraytok
564 token 'BEGIN' begintok
567 token 'CONST' consttok
568 token 'DEFINITION' definitiontok
572 token 'ELSIF' elsiftok
574 token 'EXCEPT' excepttok
576 token 'EXPORT' exporttok
577 token 'FINALLY' finallytok
581 token 'IMPLEMENTATION' implementationtok
582 token 'IMPORT' importtok
586 token 'MODULE' moduletok
590 token 'PACKEDSET' packedsettok
591 token 'POINTER' pointertok
592 token 'PROCEDURE' proceduretok
593 token 'QUALIFIED' qualifiedtok
594 token 'UNQUALIFIED' unqualifiedtok
595 token 'RECORD' recordtok
597 token 'REPEAT' repeattok
598 token 'RETRY' retrytok
599 token 'RETURN' returntok
604 token 'UNTIL' untiltok
606 token 'WHILE' whiletok
609 token 'VOLATILE' volatiletok
610 token '...' periodperiodperiodtok
611 token '__DATE__' datetok
612 token '__LINE__' linetok
613 token '__FILE__' filetok
614 token '__ATTRIBUTE__' attributetok
615 token '__BUILTIN__' builtintok
616 token '__INLINE__' inlinetok
617 token 'integer number' integertok
618 token 'identifier' identtok
619 token 'real number' realtok
620 token 'string' stringtok
622 special Ident first { < identtok > } follow { }
623 special Integer first { < integertok > } follow { }
624 special Real first { < realtok > } follow { }
625 special string first { < stringtok > } follow { }
629 -- the following are provided by the module m2flex and also handbuild procedures below
630 -- Ident := Letter { ( Letter | Digit ) } =:
631 -- Integer := Digit { Digit } | OctalDigit { OctalDigit } ( " B
" | " C
" ) |
632 -- Digit { HexDigit } " H
" =:
633 -- Real := Digit { Digit } " . " { Digit } [ ScaleFactor ] =:
634 -- ScaleFactor := " E
" [ ( " +
" | " -
" ) ] Digit { Digit } =:
635 -- HexDigit := Digit | " A
" | " B
" | " C
" | " D
" | " E
" | " F
" =:
636 -- Digit := OctalDigit | " 8 " | " 9 " =:
637 -- OctalDigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" =:
640 FileUnit := DefinitionModule | ImplementationOrProgramModule
643 ProgramModule := "MODULE
"
644 Ident % curmodule := lookupModule (curident) %
645 % enterScope (curmodule) %
646 % resetEnumPos (curmodule) %
652 Ident % checkEndName (curmodule, curident, 'program module') %
653 % setConstExpComplete (curmodule) %
659 ImplementationModule := "IMPLEMENTATION
" "MODULE
"
660 Ident % curmodule := lookupImp (curident) %
661 % enterScope (lookupDef (curident)) %
662 % enterScope (curmodule) %
663 % resetEnumPos (curmodule) %
668 Ident % checkEndName (curmodule, curident, 'implementation module') %
669 % setConstExpComplete (curmodule) %
670 % leaveScope ; leaveScope %
674 ImplementationOrProgramModule := ImplementationModule | ProgramModule
677 Number := Integer | Real =:
683 ConstantDeclaration := % VAR d, e: node ; %
684 Ident % d := lookupSym (curident) %
685 "=" ConstExpression % e := pop () %
686 % assert (isConst (d)) %
690 ConstExpressionNop := SimpleConstExpr % VAR n: node ; %
691 [ Relation SimpleConstExpr ]
692 % n := makeConstExp () %
695 ConstExpression := % VAR n: node ; %
696 % n := push (makeConstExp ()) %
698 [ Relation SimpleConstExpr ]
711 SimpleConstExpr := UnaryOrConstTerm { AddOperator ConstTerm } =:
713 UnaryOrConstTerm := "+
" ConstTerm | "-
" ConstTerm | ConstTerm =:
715 AddOperator := "+
" | "-
" | "OR
" =:
717 ConstTerm := ConstFactor { MulOperator ConstFactor } =:
728 ConstFactor := Number | ConstString | ConstSetOrQualidentOrFunction |
729 "(" ConstExpressionNop ")" | "NOT
" ConstFactor
732 -- to help satisfy LL1
734 ConstString := string =:
736 ComponentElement := ConstExpressionNop [ ".." ConstExpressionNop ] =:
738 ComponentValue := ComponentElement [ 'BY' ConstExpressionNop ] =:
740 ArraySetRecordValue := ComponentValue { ',' ComponentValue } =:
742 Constructor := '{'[ ArraySetRecordValue ] '}' =:
744 ConstSetOrQualidentOrFunction := Qualident
746 ConstActualParameters
749 ConstActualParameters := "(" [ ConstExpList ] ")" =:
751 ConstExpList := ConstExpressionNop { ",
" ConstExpressionNop } =:
753 ConstAttribute := "__ATTRIBUTE__
" "__BUILTIN__
" "(" "("
754 ConstAttributeExpression
757 ConstAttributeExpression := Ident | "<
" Qualident ',' Ident ">
" =:
759 ByteAlignment := '<*' AttributeExpression '*>' =:
761 OptAlignmentExpression := [ AlignmentExpression ] =:
763 AlignmentExpression := "(" ConstExpressionNop ")" =:
765 Alignment := [ ByteAlignment ] =:
767 IdentList := Ident { ",
" Ident }
770 PushIdentList := % VAR n: node ; %
771 % n := makeIdentList () %
772 Ident % checkDuplicate (putIdent (n, curident)) %
773 { ",
" Ident % checkDuplicate (putIdent (n, curident)) %
777 SubrangeType := % VAR low, high: node ; d: CARDINAL ; %
778 "[" % d := depth () %
779 ConstExpression % low := pop () %
780 % assert (d = depth ()) %
781 ".." ConstExpression % high := pop () %
782 % assert (d = depth ()) %
783 % typeExp := push (makeSubrange (low, high)) %
784 % assert (d = depth () - 1) %
788 ArrayType := "ARRAY
" % VAR c: CARDINAL ; t, n: node ; %
790 SimpleType % INC (c) %
792 SimpleType % INC (c) %
794 Type % n := push (makeIndexedArray (c, pop ())) %
797 RecordType := "RECORD
" % VAR n: node ; %
798 % n := push (makeRecord ()) %
799 % n := push (NIL) (* no varient *) %
800 [ DefaultRecordAttributes ]
801 FieldListSequence % assert (pop ()=NIL) %
804 DefaultRecordAttributes := '<*'
809 RecordFieldPragma := [ '<*' FieldPragmaExpression
810 { ',' FieldPragmaExpression } '*>' ] =:
812 FieldPragmaExpression := Ident PragmaConstExpression =:
814 PragmaConstExpression := [ '(' ConstExpressionNop ')' ] =:
816 AttributeExpression := Ident '(' ConstExpressionNop ')' =:
818 FieldListSequence := FieldListStatement { ";
" FieldListStatement } =:
820 FieldListStatement := [ FieldList ] =:
822 FieldList := % VAR r, i, f, t, n, v, w: node ; d: CARDINAL ; %
824 % v := pop () ; assert ((v=NIL) OR isVarient (v)) %
825 % r := peep () ; assert (isRecord (r) OR isVarientField (r)) %
827 % assert (d=depth ()) %
828 % assert (((v=NIL) AND isRecord (r)) OR ((v#NIL) AND isVarientField (r))) %
829 PushIdentList ":" % assert (d=depth () - 1) %
831 Type % assert (d=depth () - 1) %
833 RecordFieldPragma % assert (d=depth ()) %
834 % r := addFieldsToRecord (r, v, i, t) %
835 % assert (d=depth ()) %
837 "CASE
" % (* addRecordToList *) %
839 % v := pop () ; assert ((v=NIL) OR isVarient (v)) %
840 % r := peep () ; assert (isRecord (r) OR isVarientField (r)) %
842 % assert (((v=NIL) AND isRecord (r)) OR ((v#NIL) AND isRecordField (r))) %
843 % w := push (makeVarient (r)) %
844 % assert (d = depth () - 1) %
845 % (* addVarientToList *) %
847 % assert (d = depth () - 1) %
848 Varient % assert (d = depth () - 1) %
849 { "|
" Varient % assert (d = depth () - 1) %
851 % w := peep () ; assert (isVarient (w)) %
852 % assert (d = depth () - 1) %
855 ] "END
" % w := pop () ; assert (isVarient (w)) %
856 % assert (d=depth ()) %
859 TagIdent := Ident | % curident := NulName %
862 CaseTag := % VAR tagident: Name ; q, v, w, r: node ; %
863 % w := pop () ; v := pop () ; r := peep () ; v := push (v) ; w := push (w) %
864 % assert (isVarient (w)) %
865 % assert ((v=NIL) OR isVarient (v)) %
866 % assert (isRecord (r) OR isVarientField (r)) %
867 % assert (isVarient (push (pop ()))) %
868 TagIdent % tagident := curident %
869 ( ":" PushQualident % q := pop () %
870 % assert (isVarient (push (pop ()))) %
872 ) % buildVarientSelector (r, w, tagident, q) %
875 Varient := % VAR p, r, v, f: node ; d: CARDINAL ; %
877 % assert (isVarient (peep ())) %
878 [ % v := pop () ; assert (isVarient (v)) %
882 % f := push (buildVarientFieldRecord (v, p)) %
884 VarientCaseLabelList ":" FieldListSequence % v := pop () %
886 % assert (isVarientField (f)) %
887 % assert (isVarient (v)) %
889 ] % assert (isVarient (peep ())) %
890 % assert (d=depth ()) %
893 VarientCaseLabelList := VarientCaseLabels { ",
" VarientCaseLabels } =:
895 VarientCaseLabels := % VAR l, h: node ; %
897 ConstExpression % l := pop () %
898 [ ".." ConstExpression % h := pop () %
899 ] % (* l, h could be saved if necessary. *) %
902 SetType := ( "SET
" | "PACKEDSET
" ) "OF
" SimpleType % VAR n: node ; %
903 % n := push (makeSet (pop ())) %
906 PointerType := "POINTER
" "TO
" Type % VAR n: node ; %
907 % n := push (makePointer (pop ())) %
910 ProcedureType := "PROCEDURE
" % curproc := push (makeProcType ()) %
911 [ FormalTypeList ] =:
913 FormalTypeList := "(" ( ")" FormalReturn |
914 ProcedureParameters ")" FormalReturn ) =:
916 FormalReturn := [ ":" OptReturnType ] =:
918 OptReturnType := "[" PushQualident % putReturnType (curproc, pop ()) %
919 % putOptReturn (curproc) %
920 "]" | PushQualident % putReturnType (curproc, pop ()) %
923 ProcedureParameters := ProcedureParameter % addParameter (curproc, pop ()) %
924 { ",
" ProcedureParameter % addParameter (curproc, pop ()) %
927 ProcedureParameter := "..." % VAR n: node ; %
928 % n := push (makeVarargs ()) %
929 | "VAR
" FormalType % n := push (makeVarParameter (NIL, pop (), curproc, TRUE)) %
930 | FormalType % n := push (makeNonVarParameter (NIL, pop (), curproc, TRUE)) %
934 VarIdent := % VAR n, a: node ; %
936 Ident % checkDuplicate (putIdent (n, curident)) %
938 [ "[" ConstExpression % a := pop () (* could store, a, into, n. *) %
942 VarIdentList := % VAR n: node ; %
943 % n := makeIdentList () %
945 VarIdent { ",
" VarIdent }
948 VariableDeclaration := % VAR v, d: node ; %
949 VarIdentList % v := pop () %
950 ":" Type % d := makeVarDecl (v, pop ()) %
954 Designator := Qualident
971 ExpList := Expression { ",
" Expression }
974 Expression := SimpleExpression [ Relation SimpleExpression ]
977 SimpleExpression := UnaryOrTerm { AddOperator Term } =:
979 UnaryOrTerm := "+
" Term
984 Term := Factor { MulOperator Factor
987 Factor := Number | string | SetOrDesignatorOrFunction |
988 "(" Expression ")" | "NOT
" ( Factor
992 SetOrDesignatorOrFunction := Qualident
994 SimpleDes [ ActualParameters ]
998 -- SimpleDes := { "." Ident | "[" ExpList "]" | "^
" } =:
999 SimpleDes := { SubDesignator } =:
1001 ActualParameters := "(" [ ExpList ] ")" =:
1003 ExitStatement := "EXIT
"
1006 ReturnStatement := "RETURN
" [ Expression ]
1009 Statement := [ AssignmentOrProcedureCall | IfStatement | CaseStatement |
1010 WhileStatement | RepeatStatement | LoopStatement |
1011 ForStatement | WithStatement | AsmStatement |
1012 ExitStatement | ReturnStatement | RetryStatement
1016 RetryStatement := "RETRY
"
1019 AssignmentOrProcedureCall := Designator
1022 ActualParameters | % (* epsilon *) %
1026 StatementSequence := Statement { ";
" Statement }
1038 StatementSequence ] "END
"
1041 CaseStatement := "CASE
"
1043 "OF
" Case { "|
" Case }
1047 CaseEndStatement := "END
"
1049 StatementSequence "END
"
1052 Case := [ CaseLabelList ":" StatementSequence ]
1055 CaseLabelList := CaseLabels { ",
" CaseLabels } =:
1057 CaseLabels := ConstExpressionNop [ ".." ConstExpressionNop ]
1060 WhileStatement := "WHILE
" Expression "DO
"
1065 RepeatStatement := "REPEAT
"
1070 ForStatement := "FOR
" Ident ":=" Expression "TO
" Expression
1071 [ "BY
" ConstExpressionNop ] "DO
"
1076 LoopStatement := "LOOP
"
1081 WithStatement := "WITH
" Designator "DO
"
1086 ProcedureDeclaration := ProcedureHeading ";
" ProcedureBlock
1087 Ident % leaveScope %
1090 ProcedureIdent := Ident % curproc := lookupSym (curident) %
1091 % enterScope (curproc) %
1094 DefProcedureIdent := Ident % curproc := lookupSym (curident) %
1097 DefineBuiltinProcedure := [ "__ATTRIBUTE__
" "__BUILTIN__
" "(" "(" Ident ")" ")" | "__INLINE__
" ]
1100 ProcedureHeading := "PROCEDURE
" DefineBuiltinProcedure ( ProcedureIdent [ FormalParameters ] AttributeNoReturn )
1103 Builtin := [ "__BUILTIN__
" | "__INLINE__
" ] =:
1105 DefProcedureHeading := "PROCEDURE
" Builtin ( DefProcedureIdent [ DefFormalParameters ] AttributeNoReturn )
1108 -- introduced procedure block so we can produce more informative
1111 ProcedureBlock := { Declaration } [ "BEGIN
" ProcedureBlockBody ] "END
"
1114 Block := { Declaration } InitialBlock FinalBlock "END
"
1117 InitialBlock := [ "BEGIN
" InitialBlockBody ] =:
1119 FinalBlock := [ "FINALLY
" FinalBlockBody ] =:
1121 InitialBlockBody := NormalPart [ "EXCEPT
" ExceptionalPart ] =:
1123 FinalBlockBody := NormalPart [ "EXCEPT
" ExceptionalPart ] =:
1125 ProcedureBlockBody := NormalPart [ "EXCEPT
" ExceptionalPart ] =:
1127 NormalPart := StatementSequence =:
1129 ExceptionalPart := StatementSequence
1132 Declaration := "CONST
" { ConstantDeclaration ";
" } |
1133 "TYPE
" { TypeDeclaration } |
1134 "VAR
" { VariableDeclaration ";
" } |
1135 ProcedureDeclaration ";
" |
1136 ModuleDeclaration ";
" =:
1138 DefFormalParameters := "(" % paramEnter (curproc) %
1139 [ DefMultiFPSection ] ")" % paramLeave (curproc) %
1142 DefMultiFPSection := DefExtendedFP | FPSection [ ";
" DefMultiFPSection ] =:
1144 FormalParameters := "(" % paramEnter (curproc) %
1145 [ MultiFPSection ] ")" % paramLeave (curproc) %
1148 AttributeNoReturn := [ NoReturn | % setNoReturn (curproc, FALSE) %
1151 NoReturn := "<*
" Ident % setNoReturn (curproc, TRUE) %
1152 % checkReturnAttribute %
1155 AttributeUnused := [ Unused ] =:
1157 Unused := "<*
" Ident % curisused := FALSE %
1158 % checkParameterAttribute %
1161 MultiFPSection := ExtendedFP | FPSection [ ";
" MultiFPSection ] =:
1163 FPSection := NonVarFPSection | VarFPSection =:
1165 DefExtendedFP := DefOptArg | "..." % addParameter (curproc, makeVarargs ()) %
1168 ExtendedFP := OptArg | "..."
1171 VarFPSection := "VAR
" PushIdentList % VAR l, t: node ; %
1172 ":" FormalType % t := pop () %
1174 % curisused := TRUE %
1176 % addVarParameters (curproc, l, t, curisused) %
1179 NonVarFPSection := PushIdentList % VAR l, t: node ; %
1180 ":" FormalType % t := pop () %
1182 % curisused := TRUE %
1184 % addNonVarParameters (curproc, l, t, curisused) %
1187 OptArg := % VAR p, init, type: node ; id: Name ; %
1188 "[" Ident % id := curident %
1189 ":" FormalType % type := pop () %
1191 [ "=" ConstExpression % init := pop () %
1192 ] "]" % p := addOptParameter (curproc, id, type, init) %
1196 DefOptArg := % VAR p, init, type: node ; id: Name ; %
1197 "[" Ident % id := curident %
1198 ":" FormalType % type := pop () %
1199 "=" ConstExpression % init := pop () %
1200 "]" % p := addOptParameter (curproc, id, type, init) %
1204 FormalType := % VAR c: CARDINAL ; %
1205 % VAR n, a, s: node ; %
1207 { "ARRAY
" "OF
" % INC (c) %
1208 } PushQualident % pushNunbounded (c) %
1211 ModuleDeclaration := "MODULE
" Ident [ Priority ] ";
"
1212 { Import } [ Export ]
1216 Priority := "[" ConstExpressionNop "]" =:
1218 Export := "EXPORT
" ( "QUALIFIED
"
1224 FromIdentList := Ident % importInto (frommodule, curident, curmodule) %
1225 { ",
" Ident % importInto (frommodule, curident, curmodule) %
1229 FromImport := "FROM
" Ident % frommodule := lookupDef (curident) %
1230 "IMPORT
" FromIdentList ";
"
1233 ImportModuleList := Ident { ",
" Ident } =:
1235 WithoutFromImport := "IMPORT
" ImportModuleList ";
"
1238 Import := FromImport | WithoutFromImport =:
1240 DefinitionModule := "DEFINITION
" "MODULE
" [ "FOR
" string ] Ident ";
" % curmodule := lookupDef (curident) %
1241 % enterScope (curmodule) %
1242 % resetEnumPos (curmodule) %
1243 { Import } [ Export ]
1245 "END
" Ident "." % checkEndName (curmodule, curident, 'definition module') %
1246 % setConstExpComplete (curmodule) %
1251 Ident % typeExp := push (lookupSym (curident)) %
1254 metaError1 ('the symbol {%1k} is not visible in this scope (or any other nested scope)', curident)
1257 % IF NOT isDef (typeExp)
1259 ErrorArray ('the first component of this qualident must be a definition module')
1261 Ident % typeExp := replace (lookupInScope (typeExp, curident)) ;
1264 ErrorArray ('identifier not found in definition module')
1269 OptSubrange := [ SubrangeType
1270 % VAR q, s: node ; %
1273 % putSubrangeType (s, q) %
1274 % typeExp := push (s) %
1278 TypeEquiv := PushQualident OptSubrange =:
1280 EnumIdentList := % VAR f: node ; %
1281 % typeExp := push (makeEnum ()) %
1282 Ident % f := makeEnumField (typeExp, curident) %
1283 { ",
" Ident % f := makeEnumField (typeExp, curident) %
1287 Enumeration := "(" EnumIdentList ")" =:
1289 SimpleType := % VAR d: CARDINAL ; %
1291 ( TypeEquiv | Enumeration | SubrangeType ) % assert (d = depth () - 1) %
1294 Type := SimpleType | ArrayType | RecordType | SetType |
1295 PointerType | ProcedureType
1298 TypeDeclaration := { Ident % typeDes := lookupSym (curident) %
1299 ( ";
" | "=" Type % putType (typeDes, pop ()) %
1303 Definition := "CONST
" { ConstantDeclaration ";
" } |
1304 "TYPE
" { TypeDeclaration } |
1305 "VAR
" { VariableDeclaration ";
" } |
1306 DefProcedureHeading ";
" =:
1308 AsmStatement := 'ASM' [ 'VOLATILE' ] '(' AsmOperands ')' =:
1310 AsmOperands := string [ AsmOperandSpec ]
1313 AsmOperandSpec := [ ':' AsmList [ ':' AsmList [ ':' TrashList ] ] ]
1316 AsmList := [ AsmElement ] { ',' AsmElement } =:
1318 NamedOperand := '[' Ident ']' =:
1320 AsmOperandName := [ NamedOperand ]
1323 AsmElement := AsmOperandName string '(' Expression ')'
1326 TrashList := [ string ] { ',' string } =: