libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / m2 / mc / mcp5.bnf
blob9d6f0348b55ba807108abe64398134b4963844b6
1 --
2 -- mc-5.bnf grammar and associated actions for mcp5.
3 --
4 -- Copyright (C) 2016-2024 Free Software Foundation, Inc.
5 -- Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 --
7 -- This file is part of GNU Modula-2.
8 --
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)
12 -- any later version.
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/>.
22 % module mcp5 begin
24 (* output from mc-5.bnf, automatically generated do not edit.
26 Copyright (C) 2016-2024 Free Software Foundation, Inc.
27 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
29 This file is part of GNU Modula-2.
31 GNU Modula-2 is free software; you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation; either version 3, or (at your option)
34 any later version.
36 GNU Modula-2 is distributed in the hope that it will be useful, but
37 WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 General Public License for more details.
41 You should have received a copy of the GNU General Public License
42 along with GNU Modula-2; see the file COPYING. If not,
43 see <https://www.gnu.org/licenses/>. *)
45 IMPLEMENTATION MODULE mcp5 ;
47 FROM DynamicStrings IMPORT String, InitString, KillString, Mark,
48 ConCat, ConCatChar ;
50 FROM mcError IMPORT errorStringAt, flushErrors ;
51 FROM nameKey IMPORT NulName, Name, makekey ;
52 FROM mcPrintf IMPORT printf0, printf1 ;
53 FROM mcDebug IMPORT assert ;
54 FROM mcReserved IMPORT toktype ;
55 FROM mcComment IMPORT setProcedureComment ;
56 FROM mcMetaError IMPORT metaError1, metaError2 ;
57 FROM mcStack IMPORT stack ;
59 IMPORT mcStack ;
61 FROM mcLexBuf IMPORT currentstring, currenttoken, getToken, insertToken,
62 insertTokenAndRewind, getTokenNo, lastcomment,
63 getBodyComment, getAfterComment ;
65 FROM decl IMPORT node, lookupDef, lookupImp, lookupModule, getSymName,
66 enterScope, leaveScope,
67 makeEnum, makeEnumField, putType, lookupSym, isDef, makeSubrange,
68 makeSet, makePointer,
69 addParameter,
70 makeVarargs, makeVarParameter, makeNonVarParameter,
71 putSubrangeType, putConst, getType, skipType,
72 makeArray, putUnbounded, getCardinal, makeBinaryTok, makeUnaryTok,
73 makeRecord, isRecord, isRecordField, isVarientField, makeVarient,
74 addFieldsToRecord, isVarient, buildVarientSelector,
75 buildVarientFieldRecord, paramEnter, paramLeave,
76 makeIdentList, putIdent, addVarParameters, addNonVarParameters,
77 lookupInScope, import, lookupExported, isImp, isModule, isConst,
78 makeLiteralInt, makeLiteralReal, makeString, getBuiltinConst,
79 getNextEnum, makeComponentRef, makeArrayRef, makeDeRef,
80 makePointerRef,
81 makeExpList, putExpList, isExpList, isArray, isPointer, isVar,
82 isConst, isParameter,
83 makeStatementSequence, addStatement, putBegin, putFinally,
84 makeReturn, putReturn, makeExit, makeComment,
85 isStatementSequence, isWhile, makeWhile, putWhile,
86 makeAssignment, makeFuncCall, isReturn,
87 makeIf, makeElsif, putElse, isIf,
88 makeFor, putFor, isFor,
89 makeRepeat, putRepeat,
90 resetConstExpPos, getNextConstExp,
91 makeSetValue, putSetValue, includeSetValue,
92 makeCase, putCaseExpression, putCaseElse,
93 putCaseStatement, makeCaseList, putCaseRange,
94 dupExpr, makeLoop, putLoop, isLoop,
95 addCommentBody, addCommentAfter, addIfComments,
96 addElseComments, addIfEndComments,
97 addWhileDoComment, addWhileEndComment,
98 addRepeatComment, addUntilComment,
99 makeCommentS ;
102 CONST
103 Pass1 = FALSE ;
104 Debugging = FALSE ;
107 WasNoError : BOOLEAN ;
108 curstring,
109 curident : Name ;
110 curproc,
111 frommodule,
112 qualid,
113 typeDes,
114 typeExp,
115 curmodule : node ;
116 loopNo : CARDINAL ;
117 loopStk,
118 stmtStk,
119 withStk,
120 stk : stack ;
124 followNode -
127 PROCEDURE followNode (n: node) ;
128 BEGIN
129 IF isVar (n)
130 THEN
131 printf0 ("variable: ")
132 ELSIF isParameter (n)
133 THEN
134 printf0 ("parameter: ")
135 END ;
136 n := skipType (getType (n)) ;
137 IF isArray (n)
138 THEN
139 printf0 ("array\n")
140 ELSIF isPointer (n)
141 THEN
142 printf0 ("pointer\n")
143 ELSIF isRecord (n)
144 THEN
145 printf0 ("record\n")
146 ELSE
147 printf0 ("other\n")
149 END followNode ;
153 push -
156 PROCEDURE push (n: node) : node ;
157 BEGIN
158 RETURN mcStack.push (stk, n)
159 END push ;
163 pop -
166 PROCEDURE pop () : node ;
167 BEGIN
168 RETURN mcStack.pop (stk)
169 END pop ;
173 replace -
176 PROCEDURE replace (n: node) : node ;
177 BEGIN
178 RETURN mcStack.replace (stk, n)
179 END replace ;
183 peep - returns the top node on the stack without removing it.
186 PROCEDURE peep () : node ;
187 BEGIN
188 RETURN push (pop ())
189 END peep ;
193 depth - returns the depth of the stack.
196 PROCEDURE depth () : CARDINAL ;
197 BEGIN
198 RETURN mcStack.depth (stk)
199 END depth ;
203 checkDuplicate -
206 PROCEDURE checkDuplicate (b: BOOLEAN) ;
207 BEGIN
209 END checkDuplicate ;
213 isQualident - returns TRUE if, n, is a qualident.
216 PROCEDURE isQualident (n: node) : BOOLEAN ;
218 type: node ;
219 BEGIN
220 IF isDef (n)
221 THEN
222 RETURN TRUE
223 ELSE
224 type := skipType (getType (n)) ;
225 RETURN (type # NIL) AND isRecord (type)
226 END ;
227 RETURN FALSE
228 END isQualident ;
233 startWith -
236 PROCEDURE startWith (n: node) ;
237 BEGIN
238 n := mcStack.push (withStk, n)
239 END startWith ;
243 endWith -
246 PROCEDURE endWith ;
248 n: node ;
249 BEGIN
250 n := mcStack.pop (withStk)
251 END endWith ;
255 lookupWithSym -
258 PROCEDURE lookupWithSym (i: Name) : node ;
260 d : CARDINAL ;
261 n, m, t: node ;
262 BEGIN
263 d := mcStack.depth (withStk) ;
264 WHILE d # 0 DO
265 n := mcStack.access (withStk, d) ;
266 t := skipType (getType (n)) ;
267 m := lookupInScope (t, i) ;
268 IF m # NIL
269 THEN
270 n := dupExpr (n) ;
271 RETURN makeComponentRef (n, m)
272 END ;
273 DEC (d)
274 END ;
275 RETURN lookupSym (i)
276 END lookupWithSym ;
280 pushStmt - push a node, n, to the statement stack and return node, n.
283 PROCEDURE pushStmt (n: node) : node ;
284 BEGIN
285 RETURN mcStack.push (stmtStk, n)
286 END pushStmt ;
290 popStmt - pop the top node from the statement stack.
293 PROCEDURE popStmt () : node ;
294 BEGIN
295 RETURN mcStack.pop (stmtStk)
296 END popStmt ;
300 peepStmt - return the top node from the statement stack,
301 but leave the stack unchanged.
304 PROCEDURE peepStmt () : node ;
305 BEGIN
306 RETURN pushStmt (popStmt ())
307 END peepStmt ;
311 pushLoop - push a node, n, to the loop stack and return node, n.
314 PROCEDURE pushLoop (n: node) : node ;
315 BEGIN
316 RETURN mcStack.push (loopStk, n)
317 END pushLoop ;
321 popLoop - pop the top node from the loop stack.
324 PROCEDURE popLoop () : node ;
325 BEGIN
326 RETURN mcStack.pop (loopStk)
327 END popLoop ;
331 peepLoop - return the top node from the loop stack,
332 but leave the stack unchanged.
335 PROCEDURE peepLoop () : node ;
336 BEGIN
337 RETURN pushLoop (popLoop ())
338 END peepLoop ;
341 PROCEDURE ErrorString (s: String) ;
342 BEGIN
343 errorStringAt (s, getTokenNo ()) ;
344 WasNoError := FALSE
345 END ErrorString ;
348 PROCEDURE ErrorArray (a: ARRAY OF CHAR) ;
349 BEGIN
350 ErrorString (InitString (a))
351 END ErrorArray ;
355 pushNunbounded -
358 PROCEDURE pushNunbounded (c: CARDINAL) ;
360 type,
361 array,
362 subrange: node ;
363 BEGIN
364 WHILE c#0 DO
365 type := pop () ;
366 subrange := makeSubrange (NIL, NIL) ;
367 putSubrangeType (subrange, getCardinal ()) ;
369 array := makeArray (subrange, type) ;
370 putUnbounded (array) ;
371 type := push (array) ;
372 DEC (c)
374 END pushNunbounded ;
378 makeIndexedArray - builds and returns an array of type, t, with, c, indices.
381 PROCEDURE makeIndexedArray (c: CARDINAL; t: node) : node ;
383 i: node ;
384 BEGIN
385 WHILE c>0 DO
386 t := makeArray (pop (), t) ;
387 DEC (c)
388 END ;
389 RETURN t
390 END makeIndexedArray ;
394 importInto - from, m, import, name, into module, current.
395 It checks to see if curident is an enumeration type
396 and if so automatically includes all enumeration fields
397 as well.
400 PROCEDURE importInto (m: node; name: Name; current: node) ;
402 s, o: node ;
403 BEGIN
404 assert (isDef (m)) ;
405 assert (isDef (current) OR isModule (current) OR isImp (current)) ;
406 s := lookupExported (m, name) ;
407 IF s=NIL
408 THEN
409 metaError2 ('{%1k} was not exported from definition module {%2a}', name, m)
410 ELSE
411 o := import (current, s) ;
412 IF s#o
413 THEN
414 metaError2 ('{%1ad} cannot be imported into the current module as it causes a name clash with {%2ad}',
415 s, o)
418 END importInto ;
422 checkEndName - if module does not have, name, then issue an error containing, desc.
425 PROCEDURE checkEndName (module: node; name: Name; desc: ARRAY OF CHAR) ;
427 s: String ;
428 BEGIN
429 IF getSymName (module)#name
430 THEN
431 s := InitString ('inconsistent module name found with this ') ;
432 s := ConCat (s, Mark (InitString (desc))) ;
433 ErrorString (s)
435 END checkEndName ;
437 % declaration mcp5 begin
441 SyntaxError - after a syntax error we skip all tokens up until we reach
442 a stop symbol.
445 PROCEDURE SyntaxError (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
446 BEGIN
447 DescribeError ;
448 IF Debugging
449 THEN
450 printf0('\nskipping token *** ')
451 END ;
453 yes the ORD(currenttoken) looks ugly, but it is *much* safer than
454 using currenttoken<sometok as a change to the ordering of the
455 token declarations below would cause this to break. Using ORD() we are
456 immune from such changes
458 WHILE NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
459 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
460 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))
462 getToken
463 END ;
464 IF Debugging
465 THEN
466 printf0(' ***\n')
468 END SyntaxError ;
472 SyntaxCheck -
475 PROCEDURE SyntaxCheck (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
476 BEGIN
477 (* and again (see above re: ORD)
479 IF NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
480 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
481 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))
482 THEN
483 SyntaxError (stopset0, stopset1, stopset2)
485 END SyntaxCheck ;
489 WarnMissingToken - generates a warning message about a missing token, t.
492 PROCEDURE WarnMissingToken (t: toktype) ;
494 s0 : SetOfStop0 ;
495 s1 : SetOfStop1 ;
496 s2 : SetOfStop2 ;
497 str: String ;
498 BEGIN
499 s0 := SetOfStop0{} ;
500 s1 := SetOfStop1{} ;
501 s2 := SetOfStop2{} ;
502 IF ORD(t)<32
503 THEN
504 s0 := SetOfStop0{t}
505 ELSIF ORD(t)<64
506 THEN
507 s1 := SetOfStop1{t}
508 ELSE
509 s2 := SetOfStop2{t}
510 END ;
511 str := DescribeStop (s0, s1, s2) ;
513 str := ConCat (InitString ('syntax error,'), Mark (str)) ;
514 errorStringAt (str, getTokenNo ())
515 END WarnMissingToken ;
519 MissingToken - generates a warning message about a missing token, t.
522 PROCEDURE MissingToken (t: toktype) ;
523 BEGIN
524 WarnMissingToken (t) ;
525 IF (t#identtok) AND (t#integertok) AND (t#realtok) AND (t#stringtok)
526 THEN
527 IF Debugging
528 THEN
529 printf0 ('inserting token\n')
530 END ;
531 insertToken (t)
533 END MissingToken ;
537 CheckAndInsert -
540 PROCEDURE CheckAndInsert (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
541 BEGIN
542 IF ((ORD(t)<32) AND (t IN stopset0)) OR
543 ((ORD(t)>=32) AND (ORD(t)<64) AND (t IN stopset1)) OR
544 ((ORD(t)>=64) AND (t IN stopset2))
545 THEN
546 WarnMissingToken (t) ;
547 insertTokenAndRewind (t) ;
548 RETURN( TRUE )
549 ELSE
550 RETURN( FALSE )
552 END CheckAndInsert ;
556 InStopSet
559 PROCEDURE InStopSet (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
560 BEGIN
561 IF ((ORD(t)<32) AND (t IN stopset0)) OR
562 ((ORD(t)>=32) AND (ORD(t)<64) AND (t IN stopset1)) OR
563 ((ORD(t)>=64) AND (t IN stopset2))
564 THEN
565 RETURN( TRUE )
566 ELSE
567 RETURN( FALSE )
569 END InStopSet ;
573 PeepToken - peep token checks to see whether the stopset is satisfied by currenttoken
574 If it is not then it will insert a token providing the token
575 is one of ; ] ) } . OF END ,
577 if the stopset contains <identtok> then we do not insert a token
580 PROCEDURE PeepToken (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
581 BEGIN
582 (* and again (see above re: ORD)
584 IF (NOT (((ORD(currenttoken)<32) AND (currenttoken IN stopset0)) OR
585 ((ORD(currenttoken)>=32) AND (ORD(currenttoken)<64) AND (currenttoken IN stopset1)) OR
586 ((ORD(currenttoken)>=64) AND (currenttoken IN stopset2)))) AND
587 (NOT InStopSet(identtok, stopset0, stopset1, stopset2))
588 THEN
589 (* SyntaxCheck would fail since currentoken is not part of the stopset
590 we check to see whether any of currenttoken might be a commonly omitted token *)
591 IF CheckAndInsert(semicolontok, stopset0, stopset1, stopset2) OR
592 CheckAndInsert(rsbratok, stopset0, stopset1, stopset2) OR
593 CheckAndInsert(rparatok, stopset0, stopset1, stopset2) OR
594 CheckAndInsert(rcbratok, stopset0, stopset1, stopset2) OR
595 CheckAndInsert(periodtok, stopset0, stopset1, stopset2) OR
596 CheckAndInsert(oftok, stopset0, stopset1, stopset2) OR
597 CheckAndInsert(endtok, stopset0, stopset1, stopset2) OR
598 CheckAndInsert(commatok, stopset0, stopset1, stopset2)
599 THEN
602 END PeepToken ;
606 Expect -
609 PROCEDURE Expect (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
610 BEGIN
611 IF currenttoken=t
612 THEN
613 getToken ;
614 IF Pass1
615 THEN
616 PeepToken(stopset0, stopset1, stopset2)
618 ELSE
619 MissingToken(t)
620 END ;
621 SyntaxCheck(stopset0, stopset1, stopset2)
622 END Expect ;
626 CompilationUnit - returns TRUE if the input was correct enough to parse
627 in future passes.
630 PROCEDURE CompilationUnit () : BOOLEAN ;
631 BEGIN
632 stk := mcStack.init () ;
633 withStk := mcStack.init () ;
634 stmtStk := mcStack.init () ;
635 loopStk := mcStack.init () ;
636 loopNo := 0 ;
637 WasNoError := TRUE ;
638 FileUnit(SetOfStop0{eoftok}, SetOfStop1{}, SetOfStop2{}) ;
639 mcStack.kill (stk) ;
640 mcStack.kill (withStk) ;
641 mcStack.kill (stmtStk) ;
642 mcStack.kill (loopStk) ;
643 RETURN WasNoError
644 END CompilationUnit ;
648 Ident - error checking varient of Ident
651 PROCEDURE Ident (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
652 BEGIN
653 curident := makekey (currentstring) ;
654 Expect(identtok, stopset0, stopset1, stopset2)
655 END Ident ;
659 string -
662 PROCEDURE string (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
663 BEGIN
664 curstring := makekey (currentstring) ;
665 Expect(stringtok, stopset0, stopset1, stopset2)
666 END string ;
670 Integer -
673 PROCEDURE Integer (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
675 n: node ;
676 BEGIN
677 n := push (makeLiteralInt (makekey (currentstring))) ;
678 Expect(integertok, stopset0, stopset1, stopset2)
679 END Integer ;
683 Real -
686 PROCEDURE Real (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
688 n: node ;
689 BEGIN
690 n := push (makeLiteralReal (makekey (currentstring))) ;
691 Expect(realtok, stopset0, stopset1, stopset2)
692 END Real ;
694 % module mcp5 end
695 END mcp5.
696 % rules
697 error 'ErrorArray' 'ErrorString'
698 tokenfunc 'currenttoken'
700 token '' eoftok -- internal token
701 token '+' plustok
702 token '-' minustok
703 token '*' timestok
704 token '/' dividetok
705 token ':=' becomestok
706 token '&' ambersandtok
707 token "." periodtok
708 token "," commatok
709 token ";" semicolontok
710 token '(' lparatok
711 token ')' rparatok
712 token '[' lsbratok -- left square brackets
713 token ']' rsbratok -- right square brackets
714 token '{' lcbratok -- left curly brackets
715 token '}' rcbratok -- right curly brackets
716 token '^' uparrowtok
717 token "'" singlequotetok
718 token '=' equaltok
719 token '#' hashtok
720 token '<' lesstok
721 token '>' greatertok
722 token '<>' lessgreatertok
723 token '<=' lessequaltok
724 token '>=' greaterequaltok
725 token '<*' ldirectivetok
726 token '*>' rdirectivetok
727 token '..' periodperiodtok
728 token ':' colontok
729 token '"' doublequotestok
730 token '|' bartok
731 token 'AND' andtok
732 token 'ARRAY' arraytok
733 token 'BEGIN' begintok
734 token 'BY' bytok
735 token 'CASE' casetok
736 token 'CONST' consttok
737 token 'DEFINITION' definitiontok
738 token 'DIV' divtok
739 token 'DO' dotok
740 token 'ELSE' elsetok
741 token 'ELSIF' elsiftok
742 token 'END' endtok
743 token 'EXCEPT' excepttok
744 token 'EXIT' exittok
745 token 'EXPORT' exporttok
746 token 'FINALLY' finallytok
747 token 'FOR' fortok
748 token 'FROM' fromtok
749 token 'IF' iftok
750 token 'IMPLEMENTATION' implementationtok
751 token 'IMPORT' importtok
752 token 'IN' intok
753 token 'LOOP' looptok
754 token 'MOD' modtok
755 token 'MODULE' moduletok
756 token 'NOT' nottok
757 token 'OF' oftok
758 token 'OR' ortok
759 token 'PACKEDSET' packedsettok
760 token 'POINTER' pointertok
761 token 'PROCEDURE' proceduretok
762 token 'QUALIFIED' qualifiedtok
763 token 'UNQUALIFIED' unqualifiedtok
764 token 'RECORD' recordtok
765 token 'REM' remtok
766 token 'REPEAT' repeattok
767 token 'RETRY' retrytok
768 token 'RETURN' returntok
769 token 'SET' settok
770 token 'THEN' thentok
771 token 'TO' totok
772 token 'TYPE' typetok
773 token 'UNTIL' untiltok
774 token 'VAR' vartok
775 token 'WHILE' whiletok
776 token 'WITH' withtok
777 token 'ASM' asmtok
778 token 'VOLATILE' volatiletok
779 token '...' periodperiodperiodtok
780 token '__DATE__' datetok
781 token '__LINE__' linetok
782 token '__FILE__' filetok
783 token '__ATTRIBUTE__' attributetok
784 token '__BUILTIN__' builtintok
785 token '__INLINE__' inlinetok
786 token 'integer number' integertok
787 token 'identifier' identtok
788 token 'real number' realtok
789 token 'string' stringtok
791 special Ident first { < identtok > } follow { }
792 special Integer first { < integertok > } follow { }
793 special Real first { < realtok > } follow { }
794 special string first { < stringtok > } follow { }
798 -- the following are provided by the module m2flex and also handbuild procedures below
799 -- Ident := Letter { ( Letter | Digit ) } =:
800 -- Integer := Digit { Digit } | OctalDigit { OctalDigit } ( " B " | " C " ) |
801 -- Digit { HexDigit } " H " =:
802 -- Real := Digit { Digit } " . " { Digit } [ ScaleFactor ] =:
803 -- ScaleFactor := " E " [ ( " + " | " - " ) ] Digit { Digit } =:
804 -- HexDigit := Digit | " A " | " B " | " C " | " D " | " E " | " F " =:
805 -- Digit := OctalDigit | " 8 " | " 9 " =:
806 -- OctalDigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" =:
807 -- String
809 FileUnit := DefinitionModule | ImplementationOrProgramModule
812 ProgramModule := "MODULE"
813 Ident % curmodule := lookupModule (curident) %
814 % addCommentBody (curmodule) %
815 % enterScope (curmodule) %
816 % resetConstExpPos (curmodule) %
817 [ Priority ] ";"
818 { Import }
819 Block
820 Ident % checkEndName (curmodule, curident, 'program module') %
821 % leaveScope %
826 ImplementationModule := "IMPLEMENTATION" "MODULE"
827 Ident % curmodule := lookupImp (curident) %
828 % addCommentBody (curmodule) %
829 % enterScope (lookupDef (curident)) %
830 % enterScope (curmodule) %
831 % resetConstExpPos (curmodule) %
832 [ Priority ] ";"
833 { Import }
834 Block
835 Ident % checkEndName (curmodule, curident, 'implementation module') %
836 % leaveScope ; leaveScope %
840 ImplementationOrProgramModule := ImplementationModule | ProgramModule =:
842 ConstInteger := Integer % VAR i: node ; %
843 % i := pop () %
846 ConstReal := Real % VAR r: node ; %
847 % r := pop () %
850 ConstNumber := ConstInteger | ConstReal =:
852 Number := Integer | Real =:
854 Qualident := Ident { "." Ident } =:
856 ConstantDeclaration := Ident "=" ConstExpressionNop =:
858 ConstExpressionNop := % VAR c: node ; %
859 % c := getNextConstExp () %
860 SimpleConstExpr [ Relation SimpleConstExpr ] =:
862 ConstExpression := % VAR c: node ; %
863 % c := push (getNextConstExp ()) %
864 SimpleConstExpr [ Relation SimpleConstExpr ] =:
866 Relation := "="
867 | "#"
868 | "<>"
869 | "<"
870 | "<="
871 | ">"
872 | ">="
873 | "IN"
876 SimpleConstExpr := UnaryOrConstTerm { AddOperator ConstTerm } =:
878 UnaryOrConstTerm :=
880 ConstTerm
883 ConstTerm
885 ConstTerm
888 AddOperator := "+"
889 | "-"
890 | "OR"
893 ConstTerm := ConstFactor { MulOperator ConstFactor } =:
895 MulOperator := "*"
896 | "/"
897 | "DIV"
898 | "MOD"
899 | "REM"
900 | "AND"
901 | "&"
904 NotConstFactor := "NOT" ConstFactor % VAR n: node ; %
905 % n := push (makeUnaryTok (nottok, pop ())) %
908 ConstFactor := ConstNumber | ConstString | ConstSetOrQualidentOrFunction |
909 "(" ConstExpressionNop ")" | NotConstFactor
910 | ConstAttribute =:
912 -- to help satisfy LL1
914 ConstString := string =:
916 ConstComponentElement := ConstExpressionNop [ ".." ConstExpressionNop ]
919 ConstComponentValue := ConstComponentElement [ 'BY' ConstExpressionNop ]
922 ConstArraySetRecordValue := ConstComponentValue { ',' ConstComponentValue }
925 ConstConstructor := '{'
926 [ ConstArraySetRecordValue ]
927 '}' =:
929 ConstSetOrQualidentOrFunction := Qualident
930 [ ConstConstructor | ConstActualParameters ]
932 ConstConstructor =:
934 ConstActualParameters := "(" [ ConstExpList ] ")" =:
936 ConstExpList := ConstExpressionNop { "," ConstExpressionNop }
939 ConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "("
940 ConstAttributeExpression
941 ")" ")" =:
943 ConstAttributeExpression := Ident | "<" Qualident ',' Ident ">" =:
945 ByteAlignment := '<*' AttributeExpression '*>'
948 OptAlignmentExpression := [ AlignmentExpression ] =:
950 AlignmentExpression := "(" ConstExpressionNop ")" =:
952 Alignment := [ ByteAlignment ] =:
954 IdentList := Ident { "," Ident }
957 SubrangeType := "[" ConstExpressionNop ".." ConstExpressionNop "]" =:
959 ArrayType := "ARRAY" SimpleType { "," SimpleType } "OF" Type =:
961 RecordType := "RECORD" [ DefaultRecordAttributes ]
962 FieldListSequence
963 "END" =:
965 DefaultRecordAttributes := '<*' AttributeExpression '*>' =:
967 RecordFieldPragma := [ '<*' FieldPragmaExpression
968 { ',' FieldPragmaExpression } '*>' ] =:
970 FieldPragmaExpression := Ident PragmaConstExpression =:
972 PragmaConstExpression := [ '(' ConstExpressionNop ')' ] =:
974 AttributeExpression := Ident '(' ConstExpressionNop ')' =:
976 FieldListSequence := FieldListStatement { ";" FieldListStatement } =:
978 FieldListStatement := [ FieldList ] =:
980 FieldList := IdentList ":" Type RecordFieldPragma
981 | "CASE" CaseTag "OF" Varient { "|" Varient }
982 [ "ELSE"
983 FieldListSequence
984 ] "END"
987 TagIdent := Ident | % curident := NulName %
990 CaseTag := TagIdent [ ":" Qualident ]
993 Varient := [ VarientCaseLabelList ":" FieldListSequence ] =:
995 VarientCaseLabelList := VarientCaseLabels { "," VarientCaseLabels } =:
997 VarientCaseLabels := ConstExpressionNop [ ".." ConstExpressionNop ]
1000 SetType := ( "SET" | "PACKEDSET" ) "OF" SimpleType =:
1002 PointerType := "POINTER" "TO" Type =:
1004 ProcedureType := "PROCEDURE" [ FormalTypeList ] =:
1006 FormalTypeList := "(" ( ")" FormalReturn |
1007 ProcedureParameters ")" FormalReturn ) =:
1009 FormalReturn := [ ":" OptReturnType ] =:
1011 OptReturnType := "[" Qualident "]" | Qualident
1014 ProcedureParameters := ProcedureParameter
1015 { "," ProcedureParameter } =:
1017 ProcedureParameter := "..." | "VAR" FormalType | FormalType =:
1020 VarIdent := Ident [ "[" ConstExpressionNop "]" ]
1023 VarIdentList := VarIdent { "," VarIdent } =:
1025 VariableDeclaration := VarIdentList ":" Type Alignment
1028 Designator := PushQualident { SubDesignator } =:
1030 SubDesignator := % VAR n, field, type: node ; %
1031 % n := peep () %
1032 % IF n = NIL
1033 THEN
1034 ErrorArray ('no expression found') ;
1035 flushErrors ;
1036 RETURN
1037 END %
1038 % type := skipType (getType (n)) %
1039 ( "."
1040 Ident % IF isRecord (type)
1041 THEN
1042 field := lookupInScope (type, curident) ;
1043 IF field = NIL
1044 THEN
1045 metaError2 ('field {%1k} cannot be found in record {%2ad}', curident, type)
1046 ELSE
1047 n := replace (makeComponentRef (n, field))
1049 ELSE
1050 metaError2 ('attempting to access a field {%1k} from {%2ad} which does not have a record type', curident, type)
1051 END %
1053 | "[" ArrayExpList % IF isArray (type)
1054 THEN
1055 n := replace (makeArrayRef (n, pop ()))
1056 ELSE
1057 metaError1 ('attempting to access an array but the expression is not an array but a {%1d}', type)
1058 END %
1060 | SubPointer
1064 SubPointer := % VAR n, field, type: node ; %
1065 % n := peep () %
1066 % type := skipType (getType (n)) %
1067 "^" ( "." Ident % IF isPointer (type)
1068 THEN
1069 type := skipType (getType (type)) ;
1070 IF isRecord (type)
1071 THEN
1072 field := lookupInScope (type, curident) ;
1073 IF field = NIL
1074 THEN
1075 metaError2 ('field {%1k} cannot be found in record {%2ad}', curident, type)
1076 ELSE
1077 n := replace (makePointerRef (n, field))
1079 ELSE
1080 metaError2 ('attempting to access a field {%1k} from {%2ad} which does not have a record type', curident, type)
1082 ELSE
1083 metaError2 ('trying to dereference {%1k} which was not declared as a pointer but a {%2tad}', n, n)
1084 END %
1086 | % IF isPointer (type)
1087 THEN
1088 n := replace (makeDeRef (n))
1089 ELSE
1090 metaError1 ('attempting to dereference a pointer but the expression is not a pointer but a {%1d}', type)
1091 END %
1097 ArrayExpList := % VAR l: node ; %
1098 % l := push (makeExpList ()) %
1099 Expression % putExpList (l, pop ()) %
1100 % assert (isExpList (peep ())) %
1101 { ","
1102 Expression % putExpList (l, pop ()) %
1103 % assert (isExpList (peep ())) %
1107 ExpList := % VAR p, n: node ; %
1108 % p := peep () %
1109 % assert (isExpList (p)) %
1110 Expression % putExpList (p, pop ()) %
1111 % assert (isExpList (peep ())) %
1112 { "," Expression % putExpList (p, pop ()) %
1113 % assert (isExpList (peep ())) %
1118 Expression := % VAR c, l, r: node ; op: toktype ; %
1119 SimpleExpression % op := currenttoken %
1120 [ Relation % l := pop () %
1121 SimpleExpression % r := pop () %
1122 % r := push (makeBinaryTok (op, l, r)) %
1126 SimpleExpression := % VAR op: toktype ; n: node ; %
1127 UnaryOrTerm { % op := currenttoken %
1128 % n := pop () %
1129 AddOperator Term % n := push (makeBinaryTok (op, n, pop ())) %
1133 UnaryOrTerm := % VAR n: node ; %
1134 "+" Term % n := push (makeUnaryTok (plustok, pop ())) %
1135 | "-" Term % n := push (makeUnaryTok (minustok, pop ())) %
1136 | Term
1139 Term := % VAR op: toktype ; n: node ; %
1140 Factor { % op := currenttoken %
1141 MulOperator % n := pop () %
1142 Factor % n := push (makeBinaryTok (op, n, pop ())) %
1143 } =:
1145 PushString := string % VAR n: node ; %
1146 % n := push (makeString (curstring)) %
1149 Factor := Number | PushString | SetOrDesignatorOrFunction |
1150 "(" Expression ")" | "NOT" ( Factor % VAR n: node ; %
1151 % n := push (makeUnaryTok (nottok, pop ())) %
1152 | ConstAttribute
1153 % n := push (makeUnaryTok (nottok, pop ())) %
1154 ) =:
1156 ComponentElement := Expression % VAR l, h, n: node ; %
1157 % l := pop () %
1158 % h := NIL %
1159 [ ".." Expression % h := pop () %
1160 % ErrorArray ('implementation restriction range is not allowed') %
1161 ] % n := push (includeSetValue (pop (), l, h)) %
1164 ComponentValue := ComponentElement [ 'BY' % ErrorArray ('implementation restriction BY not allowed') %
1165 Expression ]
1168 ArraySetRecordValue := ComponentValue { ',' ComponentValue }
1171 Constructor := '{' % VAR n: node ; %
1172 % n := push (makeSetValue ()) %
1173 [ ArraySetRecordValue ]
1174 '}' =:
1176 SetOrDesignatorOrFunction := PushQualident % VAR q, p, n: node ; %
1177 [ Constructor % p := pop () %
1178 % q := pop () %
1179 % n := push (putSetValue (p, q)) %
1181 SimpleDes
1182 [ % q := pop () %
1183 ActualParameters % p := pop () %
1184 % p := push (makeFuncCall (q, p)) %
1187 Constructor =:
1189 -- SimpleDes := { "." Ident | "[" ExpList "]" | "^" } =:
1190 SimpleDes := { SubDesignator } =:
1192 ActualParameters := "(" % VAR n: node ; %
1193 % n := push (makeExpList ()) %
1194 [ ExpList ] ")" % assert (isExpList (peep ())) %
1198 ExitStatement := % VAR n: node ; %
1199 "EXIT"
1200 % IF loopNo = 0
1201 THEN
1202 ErrorArray ('EXIT can only be used inside a LOOP statement')
1203 ELSE
1204 n := pushStmt (makeExit (peepLoop (), loopNo))
1205 END %
1208 ReturnStatement := % VAR n: node ; %
1209 % n := pushStmt (makeReturn ()) %
1210 "RETURN" [ Expression % putReturn (n, pop ()) %
1211 ] % addCommentBody (peepStmt ()) %
1212 % addCommentAfter (peepStmt ()) %
1213 % assert (isReturn (peepStmt ())) %
1216 Statement := ( AssignmentOrProcedureCall | IfStatement | CaseStatement |
1217 WhileStatement | RepeatStatement | LoopStatement |
1218 ForStatement | WithStatement | AsmStatement |
1219 ExitStatement | ReturnStatement | RetryStatement | % VAR s: node ; %
1220 % s := pushStmt (NIL) %
1224 RetryStatement := % VAR s: node ; %
1225 % s := pushStmt (makeComment ("retry")) %
1226 "RETRY"
1229 AssignmentOrProcedureCall := % VAR d, a, p: node ; %
1230 Designator % d := pop () %
1231 ( ":=" Expression % a := pushStmt (makeAssignment (d, pop ())) %
1233 ActualParameters % a := pushStmt (makeFuncCall (d, pop ())) %
1234 | % a := pushStmt (makeFuncCall (d, NIL)) %
1236 % addCommentBody (peepStmt ()) %
1237 % addCommentAfter (peepStmt ()) %
1240 -- these two break LL1 as both start with a Designator
1241 -- ProcedureCall := Designator [ ActualParameters ] =:
1242 -- Assignment := Designator ":=" Expression =:
1244 StatementSequence := % VAR s, t: node ; %
1245 % s := pushStmt (makeStatementSequence ()) %
1246 % assert (isStatementSequence (peepStmt ())) %
1247 Statement % addStatement (s, popStmt ()) %
1248 % assert (isStatementSequence (peepStmt ())) %
1249 { ";" Statement % addStatement (s, popStmt ()) %
1250 % assert (isStatementSequence (peepStmt ())) %
1254 IfStatement := % VAR i, a, b: node ; %
1255 "IF" % b := makeCommentS (getBodyComment ()) %
1256 Expression % a := makeCommentS (getAfterComment ()) %
1257 "THEN" StatementSequence % i := pushStmt (makeIf (pop (), popStmt ())) %
1258 % addIfComments (i, b, a) %
1259 { "ELSIF" % b := makeCommentS (getBodyComment ()) %
1260 Expression % a := makeCommentS (getAfterComment ()) %
1261 "THEN" % addElseComments (peepStmt (), b, a) %
1262 StatementSequence % i := makeElsif (i, pop (), popStmt ()) %
1264 [ "ELSE"
1265 StatementSequence % putElse (i, popStmt ()) %
1266 ] "END" % b := makeCommentS (getBodyComment ()) %
1267 % a := makeCommentS (getAfterComment ()) %
1268 % assert (isIf (peepStmt ())) %
1269 % addIfEndComments (peepStmt (), b, a) %
1272 CaseStatement := % VAR s, e: node ; %
1273 % s := pushStmt (makeCase ()) %
1274 "CASE"
1275 Expression % s := putCaseExpression (s, pop ()) %
1276 "OF" Case { "|" Case }
1277 CaseEndStatement
1280 CaseEndStatement := % VAR c: node ; %
1281 "END"
1282 | "ELSE"
1283 % c := peepStmt () %
1284 StatementSequence % c := putCaseElse (c, popStmt ()) %
1285 "END"
1288 Case := [ CaseLabelList ":" % VAR l, c: node ; %
1289 % l := pop () %
1290 % c := peepStmt () %
1291 StatementSequence % c := putCaseStatement (c, l, popStmt ()) %
1295 CaseLabelList := % VAR l: node ; %
1296 % l := push (makeCaseList ()) %
1297 CaseLabels { "," CaseLabels } =:
1299 CaseLabels := % VAR lo, hi, l: node ; %
1300 % lo := NIL ; hi := NIL %
1301 % l := peep () %
1302 ConstExpression % lo := pop () %
1303 [ ".." ConstExpression % hi := pop () %
1304 ] % l := putCaseRange (l, lo, hi) %
1307 WhileStatement := % VAR s, w, e, a, b: node ; %
1308 % w := pushStmt (makeWhile ()) %
1309 "WHILE" Expression "DO" % b := makeCommentS (getBodyComment ()) %
1310 % a := makeCommentS (getAfterComment ()) %
1311 % addWhileDoComment (w, b, a) %
1312 % e := pop () %
1313 StatementSequence % s := popStmt () %
1314 "END" % (* assert (isStatementSequence (peepStmt ())) *) %
1315 % putWhile (w, e, s) %
1316 % b := makeCommentS (getBodyComment ()) %
1317 % a := makeCommentS (getAfterComment ()) %
1318 % addWhileEndComment (w, b, a) %
1321 RepeatStatement := % VAR r, s, a, b: node ; %
1322 % r := pushStmt (makeRepeat ()) %
1323 "REPEAT"
1324 % b := makeCommentS (getBodyComment ()) %
1325 % a := makeCommentS (getAfterComment ()) %
1326 % addRepeatComment (r, b, a) %
1327 StatementSequence % s := popStmt () %
1328 "UNTIL" Expression % putRepeat (r, s, pop ()) %
1329 % b := makeCommentS (getBodyComment ()) %
1330 % a := makeCommentS (getAfterComment ()) %
1331 % addUntilComment (r, b, a) %
1334 ForStatement := % VAR f, i, s, e, b: node ; %
1335 % b := NIL %
1336 % f := pushStmt (makeFor ()) %
1337 "FOR" Ident % i := lookupWithSym (curident) %
1338 ":=" Expression % s := pop () %
1339 "TO" Expression % e := pop () %
1340 [ "BY" ConstExpression % b := pop () %
1341 ] "DO"
1342 StatementSequence % putFor (f, i, s, e, b, popStmt ()) %
1343 "END"
1346 LoopStatement := % VAR l, s: node ; %
1347 "LOOP" % l := pushStmt (pushLoop (makeLoop ())) %
1348 % INC (loopNo) %
1349 StatementSequence % s := popStmt () %
1350 % putLoop (l, s) %
1351 % DEC (loopNo) %
1352 "END" % l := popLoop () %
1353 % assert (isLoop (peepStmt ())) %
1356 WithStatement := "WITH" Designator "DO" % startWith (pop ()) %
1357 StatementSequence
1358 "END" % endWith %
1361 ProcedureDeclaration := ProcedureHeading ";" ProcedureBlock
1362 Ident % leaveScope %
1365 ProcedureIdent := Ident % curproc := lookupSym (curident) %
1366 % enterScope (curproc) %
1367 % setProcedureComment (lastcomment, curident) %
1371 DefProcedureIdent := Ident % curproc := lookupSym (curident) %
1374 DefineBuiltinProcedure := [ "__ATTRIBUTE__" "__BUILTIN__" "(" "(" Ident ")" ")" | "__INLINE__" ]
1377 ProcedureHeading := "PROCEDURE" DefineBuiltinProcedure ( ProcedureIdent
1378 [ FormalParameters ]
1379 AttributeNoReturn )
1382 Builtin := [ "__BUILTIN__" | "__INLINE__" ] =:
1384 DefProcedureHeading := "PROCEDURE" Builtin ( DefProcedureIdent
1385 [ DefFormalParameters ]
1386 AttributeNoReturn )
1389 -- introduced procedure block so we can produce more informative
1390 -- error messages
1392 ProcedureBlock := { Declaration } [ "BEGIN" ProcedureBlockBody ] "END"
1395 Block := { Declaration } InitialBlock FinalBlock "END"
1398 InitialBlock := [ "BEGIN" InitialBlockBody ] =:
1400 FinalBlock := [ "FINALLY" FinalBlockBody ] =:
1402 InitialBlockBody := NormalPart % putBegin (curmodule, popStmt ()) %
1403 [ "EXCEPT" ExceptionalPart ] =:
1405 FinalBlockBody := NormalPart % putFinally (curmodule, popStmt ()) %
1406 [ "EXCEPT" ExceptionalPart ] =:
1408 ProcedureBlockBody := ProcedureNormalPart
1409 [ "EXCEPT" ExceptionalPart ] =:
1411 ProcedureNormalPart := StatementSequence % putBegin (curproc, popStmt ()) %
1414 NormalPart := StatementSequence
1417 ExceptionalPart := StatementSequence
1420 Declaration := "CONST" { ConstantDeclaration ";" } |
1421 "TYPE" { TypeDeclaration } |
1422 "VAR" { VariableDeclaration ";" } |
1423 ProcedureDeclaration ";" |
1424 ModuleDeclaration ";" =:
1426 DefFormalParameters := "(" % paramEnter (curproc) %
1427 [ DefMultiFPSection ] ")" % paramLeave (curproc) %
1428 FormalReturn =:
1430 AttributeNoReturn := [ "<*" Ident "*>" ] =:
1432 AttributeUnused := [ "<*" Ident "*>" ] =:
1434 DefMultiFPSection := DefExtendedFP | FPSection [ ";" DefMultiFPSection ] =:
1436 FormalParameters := "(" % paramEnter (curproc) %
1437 [ MultiFPSection ] ")" % paramLeave (curproc) %
1438 FormalReturn =:
1440 MultiFPSection := ExtendedFP | FPSection [ ";" MultiFPSection ] =:
1442 FPSection := NonVarFPSection | VarFPSection =:
1444 DefExtendedFP := DefOptArg | "..." =:
1446 ExtendedFP := OptArg | "..." =:
1448 VarFPSection := "VAR" IdentList ":" FormalType [ AttributeUnused ]
1451 NonVarFPSection := IdentList ":" FormalType [ AttributeUnused ]
1454 OptArg := "[" Ident ":" FormalType [ "=" ConstExpressionNop ] "]" =:
1456 DefOptArg := "[" Ident ":" FormalType "=" ConstExpressionNop "]" =:
1458 FormalType := { "ARRAY" "OF" } Qualident =:
1460 ModuleDeclaration := "MODULE" Ident [ Priority ] ";"
1461 { Import } [ Export ]
1462 Block Ident
1465 Priority := "[" ConstExpressionNop "]" =:
1467 Export := "EXPORT" ( "QUALIFIED"
1468 IdentList |
1469 "UNQUALIFIED"
1470 IdentList |
1471 IdentList ) ";" =:
1473 FromIdentList := Ident { "," Ident } =:
1475 FromImport := "FROM" Ident "IMPORT" FromIdentList ";"
1478 ImportModuleList := Ident { "," Ident } =:
1480 WithoutFromImport := "IMPORT" ImportModuleList ";"
1483 Import := FromImport | WithoutFromImport =:
1485 DefinitionModule := "DEFINITION" "MODULE" [ "FOR" string ] Ident ";" % curmodule := lookupDef (curident) %
1486 % enterScope (curmodule) %
1487 { Import } [ Export ]
1488 { Definition }
1489 "END" Ident "." % checkEndName (curmodule, curident, 'definition module') %
1490 % leaveScope %
1493 PushQualident := % VAR type, field: node ; %
1494 Ident % qualid := push (lookupWithSym (curident)) %
1495 % IF qualid = NIL
1496 THEN
1497 metaError1 ('the symbol {%1k} is not visible in this scope (or any other nested scope)', curident)
1498 END %
1499 [ "."
1500 % IF NOT isQualident (qualid)
1501 THEN
1502 ErrorArray ('the first component of this qualident must be a definition module or a parameter/variable/constant which has record type')
1503 END %
1504 Ident % IF isDef (qualid)
1505 THEN
1506 qualid := replace (lookupInScope (qualid, curident))
1507 ELSE
1508 type := skipType (getType (qualid)) ;
1509 field := lookupInScope (type, curident) ;
1510 IF field = NIL
1511 THEN
1512 metaError2 ('field {%1k} cannot be found in {%2ad}', curident, qualid)
1513 ELSE
1514 qualid := replace (makeComponentRef (qualid, field))
1516 END ;
1517 IF qualid = NIL
1518 THEN
1519 metaError1 ('qualified component of the identifier {%1k} cannot be found', curident)
1520 END %
1524 OptSubrange := [ SubrangeType ] =:
1526 TypeEquiv := Qualident OptSubrange =:
1528 EnumIdentList := Ident { "," Ident } =:
1530 Enumeration := "(" EnumIdentList ")" =:
1532 SimpleType := TypeEquiv | Enumeration | SubrangeType =:
1534 Type := SimpleType | ArrayType | RecordType | SetType |
1535 PointerType | ProcedureType
1538 TypeDeclaration := { Ident ( ";" | "=" Type Alignment ";" ) }
1541 Definition := "CONST" { ConstantDeclaration ";" } |
1542 "TYPE" { TypeDeclaration } |
1543 "VAR" { VariableDeclaration ";" } |
1544 DefProcedureHeading ";" =:
1546 AsmStatement := % VAR s: node ; %
1547 % s := pushStmt (makeComment ("asm")) %
1548 'ASM' [ 'VOLATILE' ] '(' AsmOperands ')' =:
1550 AsmOperands := string [ AsmOperandSpec ]
1553 AsmOperandSpec := [ ':' AsmList [ ':' AsmList [ ':' TrashList ] ] ]
1556 AsmList := [ AsmElement ] { ',' AsmElement } =:
1558 NamedOperand := '[' Ident ']' =:
1560 AsmOperandName := [ NamedOperand ]
1563 AsmElement := AsmOperandName string '(' Expression ')'
1566 TrashList := [ string ] { ',' string } =: