2 -- mc-2.bnf grammar and associated actions for mcp2.
4 -- Copyright (C) 2015-2022 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 COPYING3. If not see
21 -- <http://www.gnu.org/licenses/>.
23 (* output from mc-2.bnf, automatically generated do not edit.
25 Copyright (C) 2015-2022 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 mcp2 ;
46 FROM DynamicStrings IMPORT String, InitString, KillString, Mark,
49 FROM mcError IMPORT errorStringAt ;
50 FROM nameKey IMPORT NulName, Name, makekey ;
51 FROM mcPrintf IMPORT printf0, printf1 ;
52 FROM mcDebug IMPORT assert ;
53 FROM mcReserved IMPORT toktype ;
55 FROM mcLexBuf IMPORT currentstring, currenttoken, getToken, insertToken,
56 insertTokenAndRewind, getTokenNo ;
58 FROM decl IMPORT node, lookupDef, lookupImp, lookupModule, getSymName,
59 makeType, makeVar, makeConst,
60 enterScope, leaveScope,
61 addImportedModule, getCurrentModule,
62 makeEnum, makeEnumField, putType, lookupSym, isDef,
63 lookupInScope, setEnumsComplete ;
79 PROCEDURE ErrorString (s: String) ;
81 errorStringAt (s, getTokenNo ()) ;
86 PROCEDURE ErrorArray (a: ARRAY OF CHAR) ;
88 ErrorString (InitString (a))
93 checkEndName - if module does not have, name, then issue an error containing, desc.
96 PROCEDURE checkEndName (module: node; name: Name; desc: ARRAY OF CHAR) ;
100 IF getSymName (module)#name
102 s := InitString ('inconsistent module name found with this ') ;
103 s := ConCat (s, Mark (InitString (desc))) ;
108 % declaration mcp2 begin
112 SyntaxError - after a syntax error we skip all tokens up until we reach
116 PROCEDURE SyntaxError (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
121 printf0('\nskipping token *** ')
124 yes the ORD(currenttoken) looks ugly, but it is *much* safer than
125 using currenttoken<sometok as a change to the ordering of the
126 token declarations below would cause this to break. Using ORD() we are
127 immune from such changes
129 WHILE NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
130 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
131 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))
146 PROCEDURE SyntaxCheck (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
148 (* and again (see above re: ORD)
150 IF NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
151 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
152 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))
154 SyntaxError (stopset0, stopset1, stopset2)
160 WarnMissingToken - generates a warning message about a missing token, t.
163 PROCEDURE WarnMissingToken (t: toktype) ;
182 str := DescribeStop (s0, s1, s2) ;
184 str := ConCat (InitString ('syntax error,'), Mark (str)) ;
185 errorStringAt (str, getTokenNo ())
186 END WarnMissingToken ;
190 MissingToken - generates a warning message about a missing token, t.
193 PROCEDURE MissingToken (t: toktype) ;
195 WarnMissingToken (t) ;
196 IF (t#identtok) AND (t#integertok) AND (t#realtok) AND (t#stringtok)
200 printf0 ('inserting token\n')
211 PROCEDURE CheckAndInsert (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
213 IF ((ORD(t)<32) AND (t IN stopset0)) OR
214 ((ORD(t)>=32) AND (ORD(t)<64) AND (t IN stopset1)) OR
215 ((ORD(t)>=64) AND (t IN stopset2))
217 WarnMissingToken (t) ;
218 insertTokenAndRewind (t) ;
230 PROCEDURE InStopSet (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
232 IF ((ORD(t)<32) AND (t IN stopset0)) OR
233 ((ORD(t)>=32) AND (ORD(t)<64) AND (t IN stopset1)) OR
234 ((ORD(t)>=64) AND (t IN stopset2))
244 PeepToken - peep token checks to see whether the stopset is satisfied by currenttoken
245 If it is not then it will insert a token providing the token
246 is one of ; ] ) } . OF END ,
248 if the stopset contains <identtok> then we do not insert a token
251 PROCEDURE PeepToken (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
253 (* and again (see above re: ORD)
255 IF (NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
256 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
257 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))) AND
258 (NOT InStopSet(identtok, stopset0, stopset1, stopset2))
260 (* SyntaxCheck would fail since currentoken is not part of the stopset
261 we check to see whether any of currenttoken might be a commonly omitted token *)
262 IF CheckAndInsert(semicolontok, stopset0, stopset1, stopset2) OR
263 CheckAndInsert(rsbratok, stopset0, stopset1, stopset2) OR
264 CheckAndInsert(rparatok, stopset0, stopset1, stopset2) OR
265 CheckAndInsert(rcbratok, stopset0, stopset1, stopset2) OR
266 CheckAndInsert(periodtok, stopset0, stopset1, stopset2) OR
267 CheckAndInsert(oftok, stopset0, stopset1, stopset2) OR
268 CheckAndInsert(endtok, stopset0, stopset1, stopset2) OR
269 CheckAndInsert(commatok, stopset0, stopset1, stopset2)
280 PROCEDURE Expect (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
287 PeepToken(stopset0, stopset1, stopset2)
292 SyntaxCheck(stopset0, stopset1, stopset2)
297 CompilationUnit - returns TRUE if the input was correct enough to parse
301 PROCEDURE CompilationUnit () : BOOLEAN ;
304 FileUnit(SetOfStop0{eoftok}, SetOfStop1{}, SetOfStop2{}) ;
306 END CompilationUnit ;
310 Ident - error checking varient of Ident
313 PROCEDURE Ident (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
315 curident := makekey (currentstring) ;
316 Expect(identtok, stopset0, stopset1, stopset2)
324 PROCEDURE string (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
327 PushTF(makekey(currentstring), stringtok) ;
330 Expect(stringtok, stopset0, stopset1, stopset2)
338 PROCEDURE Integer (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
341 PushTF(makekey(currentstring), integertok) ;
344 Expect(integertok, stopset0, stopset1, stopset2)
352 PROCEDURE Real (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
355 PushTF(makekey(currentstring), realtok) ;
358 Expect(realtok, stopset0, stopset1, stopset2)
363 registerImport - looks up module, ident, and adds it to the
364 current module import list.
367 PROCEDURE registerImport (ident: Name; scoped: BOOLEAN) ;
371 n := lookupDef (ident) ;
372 addImportedModule (getCurrentModule (), n, scoped)
379 error 'ErrorArray' 'ErrorString'
380 tokenfunc 'currenttoken'
382 token '' eoftok -- internal token
387 token ':=' becomestok
388 token '&' ambersandtok
391 token ";" semicolontok
394 token '[' lsbratok -- left square brackets
395 token ']' rsbratok -- right square brackets
396 token '{' lcbratok -- left curly brackets
397 token '}' rcbratok -- right curly brackets
399 token "'" singlequotetok
404 token '<>' lessgreatertok
405 token '<=' lessequaltok
406 token '>=' greaterequaltok
407 token '<*' ldirectivetok
408 token '*>' rdirectivetok
409 token '..' periodperiodtok
411 token '"' doublequotestok
414 token 'ARRAY' arraytok
415 token 'BEGIN' begintok
418 token 'CONST' consttok
419 token 'DEFINITION' definitiontok
423 token 'ELSIF' elsiftok
425 token 'EXCEPT' excepttok
427 token 'EXPORT' exporttok
428 token 'FINALLY' finallytok
432 token 'IMPLEMENTATION' implementationtok
433 token 'IMPORT' importtok
437 token 'MODULE' moduletok
441 token 'PACKEDSET' packedsettok
442 token 'POINTER' pointertok
443 token 'PROCEDURE' proceduretok
444 token 'QUALIFIED' qualifiedtok
445 token 'UNQUALIFIED' unqualifiedtok
446 token 'RECORD' recordtok
448 token 'REPEAT' repeattok
449 token 'RETRY' retrytok
450 token 'RETURN' returntok
455 token 'UNTIL' untiltok
457 token 'WHILE' whiletok
460 token 'VOLATILE' volatiletok
461 token '...' periodperiodperiodtok
462 token '__DATE__' datetok
463 token '__LINE__' linetok
464 token '__FILE__' filetok
465 token '__ATTRIBUTE__' attributetok
466 token '__BUILTIN__' builtintok
467 token '__INLINE__' inlinetok
468 token 'integer number' integertok
469 token 'identifier' identtok
470 token 'real number' realtok
471 token 'string' stringtok
473 special Ident first { < identtok > } follow { }
474 special Integer first { < integertok > } follow { }
475 special Real first { < realtok > } follow { }
476 special string first { < stringtok > } follow { }
480 -- the following are provided by the module m2flex and also handbuild procedures below
481 -- Ident := Letter { ( Letter | Digit ) } =:
482 -- Integer := Digit { Digit } | OctalDigit { OctalDigit } ( " B " | " C " ) |
483 -- Digit { HexDigit } " H " =:
484 -- Real := Digit { Digit } " . " { Digit } [ ScaleFactor ] =:
485 -- ScaleFactor := " E " [ ( " + " | " - " ) ] Digit { Digit } =:
486 -- HexDigit := Digit | " A " | " B " | " C " | " D " | " E " | " F " =:
487 -- Digit := OctalDigit | " 8 " | " 9 " =:
488 -- OctalDigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" =:
491 FileUnit := DefinitionModule | ImplementationOrProgramModule
494 ProgramModule := "MODULE"
495 Ident % curmodule := lookupModule (curident) %
496 % enterScope (curmodule) %
502 Ident % checkEndName (curmodule, curident, 'program module') %
504 % setEnumsComplete (curmodule) %
508 ImplementationModule := "IMPLEMENTATION" "MODULE"
509 Ident % curmodule := lookupImp (curident) %
510 % enterScope (lookupDef (curident)) %
511 % enterScope (curmodule) %
516 Ident % checkEndName (curmodule, curident, 'implementation module') %
517 % leaveScope ; leaveScope %
518 % setEnumsComplete (curmodule) %
522 ImplementationOrProgramModule := ImplementationModule | ProgramModule
525 Number := Integer | Real =:
528 -- Qualident needs some care as we must only parse module.module.ident
529 -- and not ident.recordfield. We leave the ident.recordfield to be parsed by
530 -- SubDesignator. Note that Qualident is called by SubDesignator so if
531 -- IsAutoPushOff then we just consume tokens.
538 ConstantDeclaration := Ident "=" ConstExpression
541 ConstExpression := SimpleConstExpr [ Relation SimpleConstExpr ] =:
553 SimpleConstExpr := UnaryOrConstTerm { AddOperator ConstTerm } =:
555 UnaryOrConstTerm := "+"
568 ConstTerm := ConstFactor { MulOperator ConstFactor
580 ConstFactor := Number | ConstString | ConstSetOrQualidentOrFunction |
581 "(" ConstExpression ")" | "NOT" ConstFactor
584 -- to help satisfy LL1
586 ConstString := string =:
588 ComponentElement := ConstExpression [ ".." ConstExpression ]
591 ComponentValue := ComponentElement [ 'BY' ConstExpression ]
594 ArraySetRecordValue := ComponentValue { ',' ComponentValue }
598 [ ArraySetRecordValue ]
601 ConstSetOrQualidentOrFunction := Qualident
602 [ Constructor | ConstActualParameters
607 ConstActualParameters :=
611 ConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "("
612 ConstAttributeExpression
615 ConstAttributeExpression :=
617 | "<" Qualident ',' Ident
621 ByteAlignment := '<*' AttributeExpression '*>'
624 OptAlignmentExpression := [ AlignmentExpression ] =:
626 AlignmentExpression := "(" ConstExpression ")" =:
628 Alignment := [ ByteAlignment ] =:
630 TypeDeclaration := Ident % typeDes := lookupSym (curident) %
634 Type := ( DefSimpleType | ArrayType
641 SimpleType := Qualident [ SubrangeType ] | Enumeration | SubrangeType =:
643 EnumIdentList := % VAR n, f: node ; %
645 Ident % f := makeEnumField (n, curident) %
646 { "," Ident % f := makeEnumField (n, curident) %
650 Enumeration := "(" ( EnumIdentList )
654 IdentList := Ident { "," Ident }
657 SubrangeType := "[" ConstExpression ".." ConstExpression "]"
668 RecordType := "RECORD" [ DefaultRecordAttributes ] FieldListSequence "END" =:
670 DefaultRecordAttributes := '<*'
675 RecordFieldPragma := [ '<*' FieldPragmaExpression
676 { ',' FieldPragmaExpression } '*>' ] =:
678 FieldPragmaExpression := Ident PragmaConstExpression =:
680 PragmaConstExpression := [ '(' ConstExpression ')' ] =:
682 AttributeExpression := Ident '(' ConstExpression ')' =:
684 FieldListSequence := FieldListStatement { ";" FieldListStatement } =:
686 -- at present FieldListStatement is as follows:
687 FieldListStatement := [ FieldList ] =:
688 -- later replace it with FieldList to comply with PIM2
690 -- sadly the PIM rules are not LL1 as Ident and Qualident have the same first
691 -- symbols. We rewrite FieldList to inline qualident
693 -- FieldList := IdentList ":"
695 -- "CASE" [ Ident ":" ] Qualident "OF" Varient { "|" Varient }
696 -- [ "ELSE" FieldListSequence ] "END" =:
698 FieldList := IdentList ":"
699 Type RecordFieldPragma
703 Varient { "|" Varient }
709 TagIdent := [ Ident ] =:
711 CaseTag := TagIdent [":" Qualident ] =:
714 VarientCaseLabelList ":" FieldListSequence
717 VarientCaseLabelList := VarientCaseLabels { "," VarientCaseLabels } =:
719 VarientCaseLabels := ConstExpression [ ".." ConstExpression ]
723 -- the following rules are a copy of the ConstExpression ebnf rules but without
724 -- any actions all prefixed with Silent.
725 -- At present they are only used by CaseLabels, if this continues to be true we
726 -- might consider restricting the SilentConstExpression. Eg it makes no sence to allow
727 -- String in these circumstances!
730 SilentConstExpression :=
731 SilentSimpleConstExpr
732 [ SilentRelation SilentSimpleConstExpr ]
735 SilentRelation := "=" | "#" | "<>" | "<" | "<=" | ">" | ">=" | "IN" =:
737 SilentSimpleConstExpr := SilentUnaryOrConstTerm { SilentAddOperator SilentConstTerm } =:
739 SilentUnaryOrConstTerm := "+" SilentConstTerm | "-" SilentConstTerm | SilentConstTerm =:
741 SilentAddOperator := "+" | "-" | "OR" =:
743 SilentConstTerm := SilentConstFactor { SilentMulOperator SilentConstFactor } =:
745 SilentMulOperator := "*" | "/" | "DIV" | "MOD" | "REM" | "AND" | "&" =:
747 SilentConstFactor := Number | SilentConstString | SilentConstSetOrQualidentOrFunction |
748 "(" SilentConstExpression ")" | "NOT" SilentConstFactor
749 | SilentConstAttribute =:
751 SilentConstString := string =:
753 SilentConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "(" SilentConstAttributeExpression ")" ")" =:
755 SilentConstAttributeExpression := Ident | "<" Ident ',' SilentConstString ">" =:
757 SilentComponentElement := SilentConstExpression [ ".." SilentConstExpression ] =:
759 SilentComponentValue := SilentComponentElement [ 'BY' SilentConstExpression ] =:
761 SilentArraySetRecordValue := SilentComponentValue { ',' SilentComponentValue } =:
763 SilentConstructor := '{'
764 [ SilentArraySetRecordValue ] '}' =:
766 SilentConstSetOrQualidentOrFunction := SilentConstructor | Qualident
767 [ SilentConstructor | SilentActualParameters ] =:
769 SilentElement := SilentConstExpression [ ".." SilentConstExpression ] =:
771 SilentActualParameters := "(" [ SilentExpList ] ")" =:
773 SilentExpList := SilentConstExpression { "," SilentConstExpression } =:
775 -- end of the Silent constant rules
777 SetType := ( "SET" | "PACKEDSET" ) "OF" SimpleType =:
779 PointerType := "POINTER" "TO" Type
782 ProcedureType := "PROCEDURE" [ FormalTypeList ] =:
784 FormalTypeList := "(" ( ")" FormalReturn |
785 ProcedureParameters ")" FormalReturn ) =:
787 FormalReturn := [ ":" OptReturnType ] =:
789 OptReturnType := "[" Qualident "]" | Qualident =:
791 ProcedureParameters := ProcedureParameter
792 { "," ProcedureParameter } =:
794 ProcedureParameter := "..." | "VAR" FormalType | FormalType =:
797 VarIdent := Ident [ "[" ConstExpression "]" ]
800 VarIdentList := VarIdent { "," VarIdent }
803 VariableDeclaration := VarIdentList ":"
808 [ "[" ConstExpression "]" ]
811 DefVarIdentList := DefVarIdent { "," DefVarIdent }
814 DefVariableDeclaration := % typeDes := NIL %
815 DefVarIdentList ":" Type Alignment
818 Designator := Qualident
835 ExpList := Expression { "," Expression }
838 Expression := SimpleExpression [ Relation SimpleExpression ]
841 SimpleExpression := UnaryOrTerm { AddOperator Term } =:
843 UnaryOrTerm := "+" Term
848 Term := Factor { MulOperator Factor
851 Factor := Number | string | SetOrDesignatorOrFunction |
852 "(" Expression ")" | "NOT" ( Factor
856 SetOrDesignatorOrFunction := Qualident
858 SimpleDes [ ActualParameters ]
862 -- SimpleDes := { "." Ident | "[" ExpList "]" | "^" } =:
863 SimpleDes := { SubDesignator } =:
865 ActualParameters := "(" [ ExpList ] ")" =:
867 ExitStatement := "EXIT"
870 ReturnStatement := "RETURN" [ Expression ]
873 Statement := [ AssignmentOrProcedureCall | IfStatement | CaseStatement |
874 WhileStatement | RepeatStatement | LoopStatement |
875 ForStatement | WithStatement | AsmStatement |
876 ExitStatement | ReturnStatement | RetryStatement
880 RetryStatement := "RETRY"
883 AssignmentOrProcedureCall := Designator
886 ActualParameters | % (* epsilon *) %
890 -- these two break LL1 as both start with a Designator
891 -- ProcedureCall := Designator [ ActualParameters ] =:
892 -- Assignment := Designator ":=" Expression =:
894 StatementSequence := Statement { ";" Statement }
906 StatementSequence ] "END"
909 CaseStatement := "CASE"
911 "OF" Case { "|" Case }
915 CaseEndStatement := "END"
917 StatementSequence "END"
920 Case := [ CaseLabelList ":" StatementSequence ]
923 CaseLabelList := CaseLabels { "," CaseLabels } =:
925 CaseLabels := ConstExpression [ ".." ConstExpression ]
928 WhileStatement := "WHILE" Expression "DO"
933 RepeatStatement := "REPEAT"
939 "FOR" Ident ":=" Expression "TO" Expression [ "BY" ConstExpression ] "DO"
944 LoopStatement := "LOOP"
949 WithStatement := "WITH" Designator "DO"
954 ProcedureDeclaration := ProcedureHeading ";" ProcedureBlock
958 ProcedureIdent := Ident % curproc := lookupSym (curident) %
961 DefineBuiltinProcedure := [ "__ATTRIBUTE__" "__BUILTIN__" "(" "(" Ident ")" ")" | "__INLINE__" ]
964 ProcedureHeading := "PROCEDURE" DefineBuiltinProcedure ( ProcedureIdent % enterScope (curproc) %
969 Builtin := [ "__BUILTIN__" | "__INLINE__" ] =:
971 DefProcedureHeading := "PROCEDURE" Builtin ( ProcedureIdent
972 [ DefFormalParameters ]
976 -- introduced procedure block so we can produce more informative
979 ProcedureBlock := { Declaration } [ "BEGIN" ProcedureBlockBody ] "END" % leaveScope %
982 Block := { Declaration } InitialBlock FinalBlock "END"
985 InitialBlock := [ "BEGIN" InitialBlockBody ] =:
987 FinalBlock := [ "FINALLY" FinalBlockBody ] =:
989 InitialBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
991 FinalBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
993 ProcedureBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
995 NormalPart := StatementSequence =:
997 ExceptionalPart := StatementSequence
1000 Declaration := "CONST" { ConstantDeclaration ";" } |
1001 "TYPE" { TypeDeclaration ";" } |
1002 "VAR" { VariableDeclaration ";" } |
1003 ProcedureDeclaration ";" |
1004 ModuleDeclaration ";" =:
1006 DefFormalParameters := "(" [ DefMultiFPSection ] ")" FormalReturn =:
1008 DefMultiFPSection := DefExtendedFP | FPSection [ ";" DefMultiFPSection ] =:
1010 FormalParameters := "(" [ MultiFPSection ] ")" FormalReturn =:
1012 AttributeNoReturn := [ "<*" Ident "*>" ] =:
1014 AttributeUnused := [ "<*" Ident "*>" ] =:
1016 MultiFPSection := ExtendedFP | FPSection [ ";" MultiFPSection ] =:
1018 FPSection := NonVarFPSection | VarFPSection =:
1020 DefExtendedFP := DefOptArg | "..." =:
1022 ExtendedFP := OptArg | "..." =:
1024 VarFPSection := "VAR" IdentList ":" FormalType [ AttributeUnused ] =:
1026 NonVarFPSection := IdentList ":" FormalType [ AttributeUnused ] =:
1028 OptArg := "[" Ident ":" FormalType [ "=" ConstExpression ] "]" =:
1030 DefOptArg := "[" Ident ":" FormalType "=" ConstExpression "]" =:
1032 FormalType := { "ARRAY" "OF" } Qualident =:
1034 ModuleDeclaration := "MODULE" Ident [ Priority ] ";"
1035 { Import } [ Export ]
1039 Priority := "[" ConstExpression "]" =:
1041 Export := "EXPORT" ( "QUALIFIED"
1047 FromImport := "FROM" Ident "IMPORT" IdentList ";"
1050 ImportModuleList := Ident { "," Ident }
1053 WithoutFromImport := "IMPORT" ImportModuleList ";"
1056 Import := FromImport | WithoutFromImport =:
1058 DefinitionModule := "DEFINITION" "MODULE" [ "FOR" string ] Ident ";" % curmodule := lookupDef (curident) %
1059 % enterScope (curmodule) %
1060 { Import } [ Export ]
1062 "END" Ident "." % checkEndName (curmodule, curident, 'definition module') %
1064 % setEnumsComplete (curmodule) %
1068 Ident % typeExp := lookupSym (curident) %
1069 [ "." % IF NOT isDef (typeExp)
1071 ErrorArray ('the first component of this qualident must be a definition module')
1073 Ident % typeExp := lookupInScope (typeExp, curident) ;
1076 ErrorArray ('identifier not found in definition module')
1081 DefOptSubrange := [ SubrangeType | % putType (typeDes, typeExp) %
1085 DefTypeEquiv := DefQualident DefOptSubrange =:
1087 DefEnumIdentList := % VAR n, f: node ; %
1088 % n := makeEnum () %
1089 Ident % f := makeEnumField (n, curident) %
1090 { "," Ident % f := makeEnumField (n, curident) %
1091 } % IF typeDes # NIL THEN putType (typeDes, n) END %
1094 DefEnumeration := "(" DefEnumIdentList ")" =:
1096 DefSimpleType := DefTypeEquiv | DefEnumeration | SubrangeType
1099 DefType := DefSimpleType | ArrayType | RecordType | SetType |
1100 PointerType | ProcedureType
1103 DefTypeDeclaration := { Ident % typeDes := lookupSym (curident) %
1104 ( ";" | "=" DefType Alignment ";" ) }
1107 DefConstantDeclaration := Ident
1111 Definition := "CONST" { DefConstantDeclaration ";" } |
1112 "TYPE" { DefTypeDeclaration } |
1113 "VAR" { DefVariableDeclaration ";" } |
1114 DefProcedureHeading ";" =:
1116 AsmStatement := 'ASM' [ 'VOLATILE' ] '(' AsmOperands ')' =:
1118 AsmOperands := string [ AsmOperandSpec ]
1121 AsmOperandSpec := [ ':' AsmList [ ':' AsmList [ ':' TrashList ] ] ]
1124 AsmList := [ AsmElement ] { ',' AsmElement } =:
1126 NamedOperand := '[' Ident ']' =:
1128 AsmOperandName := [ NamedOperand ]
1131 AsmElement := AsmOperandName string '(' Expression ')'
1134 TrashList := [ string ] { ',' string } =: