]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/m2/mc/mcp2.bnf
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / mc / mcp2.bnf
CommitLineData
1eee94d3
GM
1--
2-- mc-2.bnf grammar and associated actions for mcp2.
3--
a945c346 4-- Copyright (C) 2015-2024 Free Software Foundation, Inc.
1eee94d3
GM
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.
13--
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.
18--
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 mcp2 begin
23(* output from mc-2.bnf, automatically generated do not edit.
24
a945c346 25Copyright (C) 2015-2024 Free Software Foundation, Inc.
1eee94d3
GM
26Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
27
28This file is part of GNU Modula-2.
29
30GNU Modula-2 is free software; you can redistribute it and/or modify
31it under the terms of the GNU General Public License as published by
32the Free Software Foundation; either version 3, or (at your option)
33any later version.
34
35GNU Modula-2 is distributed in the hope that it will be useful, but
36WITHOUT ANY WARRANTY; without even the implied warranty of
37MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38General Public License for more details.
39
40You should have received a copy of the GNU General Public License
41along with GNU Modula-2; see the file COPYING. If not,
42see <https://www.gnu.org/licenses/>. *)
43
44IMPLEMENTATION MODULE mcp2 ;
45
46FROM DynamicStrings IMPORT String, InitString, KillString, Mark,
47 ConCat, ConCatChar ;
48
49FROM mcError IMPORT errorStringAt ;
50FROM nameKey IMPORT NulName, Name, makekey ;
51FROM mcPrintf IMPORT printf0, printf1 ;
52FROM mcDebug IMPORT assert ;
53FROM mcReserved IMPORT toktype ;
54
55FROM mcLexBuf IMPORT currentstring, currenttoken, getToken, insertToken,
56 insertTokenAndRewind, getTokenNo ;
57
58FROM 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 ;
64
65
66CONST
67 Pass1 = FALSE ;
68 Debugging = FALSE ;
69
70VAR
71 WasNoError: BOOLEAN ;
72 curident : Name ;
73 typeDes,
74 typeExp,
75 curproc,
76 curmodule : node ;
77
78
79PROCEDURE ErrorString (s: String) ;
80BEGIN
81 errorStringAt (s, getTokenNo ()) ;
82 WasNoError := FALSE
83END ErrorString ;
84
85
86PROCEDURE ErrorArray (a: ARRAY OF CHAR) ;
87BEGIN
88 ErrorString (InitString (a))
89END ErrorArray ;
90
91
92(*
93 checkEndName - if module does not have, name, then issue an error containing, desc.
94*)
95
96PROCEDURE checkEndName (module: node; name: Name; desc: ARRAY OF CHAR) ;
97VAR
98 s: String ;
99BEGIN
100 IF getSymName (module)#name
101 THEN
102 s := InitString ('inconsistent module name found with this ') ;
103 s := ConCat (s, Mark (InitString (desc))) ;
104 ErrorString (s)
105 END
106END checkEndName ;
107
108% declaration mcp2 begin
109
110
111(*
112 SyntaxError - after a syntax error we skip all tokens up until we reach
113 a stop symbol.
114*)
115
116PROCEDURE SyntaxError (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
117BEGIN
118 DescribeError ;
119 IF Debugging
120 THEN
121 printf0('\nskipping token *** ')
122 END ;
123 (*
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
128 *)
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)))
132 DO
133 getToken
134 END ;
135 IF Debugging
136 THEN
137 printf0(' ***\n')
138 END
139END SyntaxError ;
140
141
142(*
143 SyntaxCheck -
144*)
145
146PROCEDURE SyntaxCheck (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
147BEGIN
148 (* and again (see above re: ORD)
149 *)
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)))
153 THEN
154 SyntaxError (stopset0, stopset1, stopset2)
155 END
156END SyntaxCheck ;
157
158
159(*
160 WarnMissingToken - generates a warning message about a missing token, t.
161*)
162
163PROCEDURE WarnMissingToken (t: toktype) ;
164VAR
165 s0 : SetOfStop0 ;
166 s1 : SetOfStop1 ;
167 s2 : SetOfStop2 ;
168 str: String ;
169BEGIN
170 s0 := SetOfStop0{} ;
171 s1 := SetOfStop1{} ;
172 s2 := SetOfStop2{} ;
173 IF ORD(t)<32
174 THEN
175 s0 := SetOfStop0{t}
176 ELSIF ORD(t)<64
177 THEN
178 s1 := SetOfStop1{t}
179 ELSE
180 s2 := SetOfStop2{t}
181 END ;
182 str := DescribeStop (s0, s1, s2) ;
183
184 str := ConCat (InitString ('syntax error,'), Mark (str)) ;
185 errorStringAt (str, getTokenNo ())
186END WarnMissingToken ;
187
188
189(*
190 MissingToken - generates a warning message about a missing token, t.
191*)
192
193PROCEDURE MissingToken (t: toktype) ;
194BEGIN
195 WarnMissingToken (t) ;
196 IF (t#identtok) AND (t#integertok) AND (t#realtok) AND (t#stringtok)
197 THEN
198 IF Debugging
199 THEN
200 printf0 ('inserting token\n')
201 END ;
202 insertToken (t)
203 END
204END MissingToken ;
205
206
207(*
208 CheckAndInsert -
209*)
210
211PROCEDURE CheckAndInsert (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
212BEGIN
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))
216 THEN
217 WarnMissingToken (t) ;
218 insertTokenAndRewind (t) ;
219 RETURN( TRUE )
220 ELSE
221 RETURN( FALSE )
222 END
223END CheckAndInsert ;
224
225
226(*
227 InStopSet
228*)
229
230PROCEDURE InStopSet (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) : BOOLEAN ;
231BEGIN
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))
235 THEN
236 RETURN( TRUE )
237 ELSE
238 RETURN( FALSE )
239 END
240END InStopSet ;
241
242
243(*
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 ,
247
248 if the stopset contains <identtok> then we do not insert a token
249*)
250
251PROCEDURE PeepToken (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
252BEGIN
253 (* and again (see above re: ORD)
254 *)
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))
259 THEN
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)
270 THEN
271 END
272 END
273END PeepToken ;
274
275
276(*
277 Expect -
278*)
279
280PROCEDURE Expect (t: toktype; stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
281BEGIN
282 IF currenttoken=t
283 THEN
284 getToken ;
285 IF Pass1
286 THEN
287 PeepToken(stopset0, stopset1, stopset2)
288 END
289 ELSE
290 MissingToken(t)
291 END ;
292 SyntaxCheck(stopset0, stopset1, stopset2)
293END Expect ;
294
295
296(*
297 CompilationUnit - returns TRUE if the input was correct enough to parse
298 in future passes.
299*)
300
301PROCEDURE CompilationUnit () : BOOLEAN ;
302BEGIN
303 WasNoError := TRUE ;
304 FileUnit(SetOfStop0{eoftok}, SetOfStop1{}, SetOfStop2{}) ;
305 RETURN( WasNoError )
306END CompilationUnit ;
307
308
309(*
310 Ident - error checking varient of Ident
311*)
312
313PROCEDURE Ident (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
314BEGIN
315 curident := makekey (currentstring) ;
316 Expect(identtok, stopset0, stopset1, stopset2)
317END Ident ;
318
319
320(*
321 string -
322*)
323
324PROCEDURE string (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
325BEGIN
326(*
327 PushTF(makekey(currentstring), stringtok) ;
328 BuildString
329*)
330 Expect(stringtok, stopset0, stopset1, stopset2)
331END string ;
332
333
334(*
335 Integer -
336*)
337
338PROCEDURE Integer (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
339BEGIN
340(*
341 PushTF(makekey(currentstring), integertok) ;
342 BuildNumber
343*)
344 Expect(integertok, stopset0, stopset1, stopset2)
345END Integer ;
346
347
348(*
349 Real -
350*)
351
352PROCEDURE Real (stopset0: SetOfStop0; stopset1: SetOfStop1; stopset2: SetOfStop2) ;
353BEGIN
354(*
355 PushTF(makekey(currentstring), realtok) ;
356 BuildNumber
357*)
358 Expect(realtok, stopset0, stopset1, stopset2)
359END Real ;
360
361
362(*
363 registerImport - looks up module, ident, and adds it to the
364 current module import list.
365*)
366
367PROCEDURE registerImport (ident: Name; scoped: BOOLEAN) ;
368VAR
369 n: node ;
370BEGIN
371 n := lookupDef (ident) ;
372 addImportedModule (getCurrentModule (), n, scoped)
373END registerImport ;
374
375
376% module mcp2 end
377END mcp2.
378% rules
379error 'ErrorArray' 'ErrorString'
380tokenfunc 'currenttoken'
381
382token '' eoftok -- internal token
383token '+' plustok
384token '-' minustok
385token '*' timestok
386token '/' dividetok
387token ':=' becomestok
388token '&' ambersandtok
389token "." periodtok
390token "," commatok
391token ";" semicolontok
392token '(' lparatok
393token ')' rparatok
394token '[' lsbratok -- left square brackets
395token ']' rsbratok -- right square brackets
396token '{' lcbratok -- left curly brackets
397token '}' rcbratok -- right curly brackets
398token '^' uparrowtok
399token "'" singlequotetok
400token '=' equaltok
401token '#' hashtok
402token '<' lesstok
403token '>' greatertok
404token '<>' lessgreatertok
405token '<=' lessequaltok
406token '>=' greaterequaltok
407token '<*' ldirectivetok
408token '*>' rdirectivetok
409token '..' periodperiodtok
410token ':' colontok
411token '"' doublequotestok
412token '|' bartok
413token 'AND' andtok
414token 'ARRAY' arraytok
415token 'BEGIN' begintok
416token 'BY' bytok
417token 'CASE' casetok
418token 'CONST' consttok
419token 'DEFINITION' definitiontok
420token 'DIV' divtok
421token 'DO' dotok
422token 'ELSE' elsetok
423token 'ELSIF' elsiftok
424token 'END' endtok
425token 'EXCEPT' excepttok
426token 'EXIT' exittok
427token 'EXPORT' exporttok
428token 'FINALLY' finallytok
429token 'FOR' fortok
430token 'FROM' fromtok
431token 'IF' iftok
432token 'IMPLEMENTATION' implementationtok
433token 'IMPORT' importtok
434token 'IN' intok
435token 'LOOP' looptok
436token 'MOD' modtok
437token 'MODULE' moduletok
438token 'NOT' nottok
439token 'OF' oftok
440token 'OR' ortok
441token 'PACKEDSET' packedsettok
442token 'POINTER' pointertok
443token 'PROCEDURE' proceduretok
444token 'QUALIFIED' qualifiedtok
445token 'UNQUALIFIED' unqualifiedtok
446token 'RECORD' recordtok
447token 'REM' remtok
448token 'REPEAT' repeattok
449token 'RETRY' retrytok
450token 'RETURN' returntok
451token 'SET' settok
452token 'THEN' thentok
453token 'TO' totok
454token 'TYPE' typetok
455token 'UNTIL' untiltok
456token 'VAR' vartok
457token 'WHILE' whiletok
458token 'WITH' withtok
459token 'ASM' asmtok
460token 'VOLATILE' volatiletok
461token '...' periodperiodperiodtok
462token '__DATE__' datetok
463token '__LINE__' linetok
464token '__FILE__' filetok
465token '__ATTRIBUTE__' attributetok
466token '__BUILTIN__' builtintok
467token '__INLINE__' inlinetok
468token 'integer number' integertok
469token 'identifier' identtok
470token 'real number' realtok
471token 'string' stringtok
472
473special Ident first { < identtok > } follow { }
474special Integer first { < integertok > } follow { }
475special Real first { < realtok > } follow { }
476special string first { < stringtok > } follow { }
477
478BNF
479
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" =:
489-- String
490
491FileUnit := DefinitionModule | ImplementationOrProgramModule
492 =:
493
494ProgramModule := "MODULE"
495 Ident % curmodule := lookupModule (curident) %
496 % enterScope (curmodule) %
497 [ Priority
498 ]
499 ";"
500 { Import }
501 Block
502 Ident % checkEndName (curmodule, curident, 'program module') %
503 % leaveScope %
504 % setEnumsComplete (curmodule) %
505 "."
506 =:
507
508ImplementationModule := "IMPLEMENTATION" "MODULE"
509 Ident % curmodule := lookupImp (curident) %
510 % enterScope (lookupDef (curident)) %
511 % enterScope (curmodule) %
512 [ Priority
513 ] ";"
514 { Import }
515 Block
516 Ident % checkEndName (curmodule, curident, 'implementation module') %
517 % leaveScope ; leaveScope %
518 % setEnumsComplete (curmodule) %
519 "."
520 =:
521
522ImplementationOrProgramModule := ImplementationModule | ProgramModule
523 =:
524
525Number := Integer | Real =:
526
527--
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.
532--
533
534Qualident :=
535 Ident { "." Ident }
536 =:
537
538ConstantDeclaration := Ident "=" ConstExpression
539 =:
540
541ConstExpression := SimpleConstExpr [ Relation SimpleConstExpr ] =:
542
543Relation := "="
544 | "#"
545 | "<>"
546 | "<"
547 | "<="
548 | ">"
549 | ">="
550 | "IN"
551 =:
552
553SimpleConstExpr := UnaryOrConstTerm { AddOperator ConstTerm } =:
554
555UnaryOrConstTerm := "+"
556 ConstTerm
557 |
558 "-"
559 ConstTerm
560 |
561 ConstTerm =:
562
563AddOperator := "+"
564 | "-"
565 | "OR"
566 =:
567
568ConstTerm := ConstFactor { MulOperator ConstFactor
569 } =:
570
571MulOperator := "*"
572 | "/"
573 | "DIV"
574 | "MOD"
575 | "REM"
576 | "AND"
577 | "&"
578 =:
579
580ConstFactor := Number | ConstString | ConstSetOrQualidentOrFunction |
581 "(" ConstExpression ")" | "NOT" ConstFactor
582 | ConstAttribute =:
583
584-- to help satisfy LL1
585
586ConstString := string =:
587
588ComponentElement := ConstExpression [ ".." ConstExpression ]
589 =:
590
591ComponentValue := ComponentElement [ 'BY' ConstExpression ]
592 =:
593
594ArraySetRecordValue := ComponentValue { ',' ComponentValue }
595 =:
596
597Constructor := '{'
598 [ ArraySetRecordValue ]
599 '}' =:
600
601ConstSetOrQualidentOrFunction := Qualident
602 [ Constructor | ConstActualParameters
603 ]
604 |
605 Constructor =:
606
607ConstActualParameters :=
608 ActualParameters
609 =:
610
611ConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "("
612 ConstAttributeExpression
613 ")" ")" =:
614
615ConstAttributeExpression :=
616 Ident
617 | "<" Qualident ',' Ident
618 ">"
619 =:
620
621ByteAlignment := '<*' AttributeExpression '*>'
622 =:
623
624OptAlignmentExpression := [ AlignmentExpression ] =:
625
626AlignmentExpression := "(" ConstExpression ")" =:
627
628Alignment := [ ByteAlignment ] =:
629
630TypeDeclaration := Ident % typeDes := lookupSym (curident) %
631 "=" Type Alignment
632 =:
633
634Type := ( DefSimpleType | ArrayType
635 | RecordType
636 | SetType
637 | PointerType
638 | ProcedureType )
639 =:
640
641SimpleType := Qualident [ SubrangeType ] | Enumeration | SubrangeType =:
642
643EnumIdentList := % VAR n, f: node ; %
644 % n := makeEnum () %
645 Ident % f := makeEnumField (n, curident) %
646 { "," Ident % f := makeEnumField (n, curident) %
647 }
648 =:
649
650Enumeration := "(" ( EnumIdentList )
651 ")"
652 =:
653
654IdentList := Ident { "," Ident }
655 =:
656
657SubrangeType := "[" ConstExpression ".." ConstExpression "]"
658 =:
659
660ArrayType := "ARRAY"
661 SimpleType
662 { ","
663 SimpleType
664 } "OF"
665 Type
666 =:
667
668RecordType := "RECORD" [ DefaultRecordAttributes ] FieldListSequence "END" =:
669
670DefaultRecordAttributes := '<*'
671 AttributeExpression
672
673 '*>' =:
674
675RecordFieldPragma := [ '<*' FieldPragmaExpression
676 { ',' FieldPragmaExpression } '*>' ] =:
677
678FieldPragmaExpression := Ident PragmaConstExpression =:
679
680PragmaConstExpression := [ '(' ConstExpression ')' ] =:
681
682AttributeExpression := Ident '(' ConstExpression ')' =:
683
684FieldListSequence := FieldListStatement { ";" FieldListStatement } =:
685
686-- at present FieldListStatement is as follows:
687FieldListStatement := [ FieldList ] =:
688-- later replace it with FieldList to comply with PIM2
689
690-- sadly the PIM rules are not LL1 as Ident and Qualident have the same first
691-- symbols. We rewrite FieldList to inline qualident
692-- was
693-- FieldList := IdentList ":"
694-- Type |
695-- "CASE" [ Ident ":" ] Qualident "OF" Varient { "|" Varient }
696-- [ "ELSE" FieldListSequence ] "END" =:
697
698FieldList := IdentList ":"
699 Type RecordFieldPragma
700 |
701 "CASE"
702 CaseTag "OF"
703 Varient { "|" Varient }
704 [ "ELSE"
705 FieldListSequence
706 ] "END"
707 =:
708
709TagIdent := [ Ident ] =:
710
711CaseTag := TagIdent [":" Qualident ] =:
712
713Varient := [
714 VarientCaseLabelList ":" FieldListSequence
715 ] =:
716
717VarientCaseLabelList := VarientCaseLabels { "," VarientCaseLabels } =:
718
719VarientCaseLabels := ConstExpression [ ".." ConstExpression ]
720 =:
721
722--
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!
728--
729
730SilentConstExpression :=
731 SilentSimpleConstExpr
732 [ SilentRelation SilentSimpleConstExpr ]
733 =:
734
735SilentRelation := "=" | "#" | "<>" | "<" | "<=" | ">" | ">=" | "IN" =:
736
737SilentSimpleConstExpr := SilentUnaryOrConstTerm { SilentAddOperator SilentConstTerm } =:
738
739SilentUnaryOrConstTerm := "+" SilentConstTerm | "-" SilentConstTerm | SilentConstTerm =:
740
741SilentAddOperator := "+" | "-" | "OR" =:
742
743SilentConstTerm := SilentConstFactor { SilentMulOperator SilentConstFactor } =:
744
745SilentMulOperator := "*" | "/" | "DIV" | "MOD" | "REM" | "AND" | "&" =:
746
747SilentConstFactor := Number | SilentConstString | SilentConstSetOrQualidentOrFunction |
748 "(" SilentConstExpression ")" | "NOT" SilentConstFactor
749 | SilentConstAttribute =:
750
751SilentConstString := string =:
752
753SilentConstAttribute := "__ATTRIBUTE__" "__BUILTIN__" "(" "(" SilentConstAttributeExpression ")" ")" =:
754
755SilentConstAttributeExpression := Ident | "<" Ident ',' SilentConstString ">" =:
756
757SilentComponentElement := SilentConstExpression [ ".." SilentConstExpression ] =:
758
759SilentComponentValue := SilentComponentElement [ 'BY' SilentConstExpression ] =:
760
761SilentArraySetRecordValue := SilentComponentValue { ',' SilentComponentValue } =:
762
763SilentConstructor := '{'
764 [ SilentArraySetRecordValue ] '}' =:
765
766SilentConstSetOrQualidentOrFunction := SilentConstructor | Qualident
767 [ SilentConstructor | SilentActualParameters ] =:
768
769SilentElement := SilentConstExpression [ ".." SilentConstExpression ] =:
770
771SilentActualParameters := "(" [ SilentExpList ] ")" =:
772
773SilentExpList := SilentConstExpression { "," SilentConstExpression } =:
774
775-- end of the Silent constant rules
776
777SetType := ( "SET" | "PACKEDSET" ) "OF" SimpleType =:
778
779PointerType := "POINTER" "TO" Type
780 =:
781
782ProcedureType := "PROCEDURE" [ FormalTypeList ] =:
783
784FormalTypeList := "(" ( ")" FormalReturn |
785 ProcedureParameters ")" FormalReturn ) =:
786
787FormalReturn := [ ":" OptReturnType ] =:
788
789OptReturnType := "[" Qualident "]" | Qualident =:
790
791ProcedureParameters := ProcedureParameter
792 { "," ProcedureParameter } =:
793
794ProcedureParameter := "..." | "VAR" FormalType | FormalType =:
795
796
797VarIdent := Ident [ "[" ConstExpression "]" ]
798 =:
799
800VarIdentList := VarIdent { "," VarIdent }
801 =:
802
803VariableDeclaration := VarIdentList ":"
804 Type Alignment
805 =:
806
807DefVarIdent := Ident
808 [ "[" ConstExpression "]" ]
809 =:
810
811DefVarIdentList := DefVarIdent { "," DefVarIdent }
812 =:
813
814DefVariableDeclaration := % typeDes := NIL %
815 DefVarIdentList ":" Type Alignment
816 =:
817
818Designator := Qualident
819 { SubDesignator } =:
820
821SubDesignator := "."
822 Ident
823 | "[" ArrayExpList
824 "]"
825 | "^"
826 =:
827
828ArrayExpList :=
829 Expression
830 { ","
831 Expression
832 }
833 =:
834
835ExpList := Expression { "," Expression }
836 =:
837
838Expression := SimpleExpression [ Relation SimpleExpression ]
839 =:
840
841SimpleExpression := UnaryOrTerm { AddOperator Term } =:
842
843UnaryOrTerm := "+" Term
844 | "-" Term
845 | Term
846 =:
847
848Term := Factor { MulOperator Factor
849 } =:
850
851Factor := Number | string | SetOrDesignatorOrFunction |
852 "(" Expression ")" | "NOT" ( Factor
853 | ConstAttribute
854 ) =:
855
856SetOrDesignatorOrFunction := Qualident
857 [ Constructor |
858 SimpleDes [ ActualParameters ]
859 ] |
860 Constructor =:
861
862-- SimpleDes := { "." Ident | "[" ExpList "]" | "^" } =:
863SimpleDes := { SubDesignator } =:
864
865ActualParameters := "(" [ ExpList ] ")" =:
866
867ExitStatement := "EXIT"
868 =:
869
870ReturnStatement := "RETURN" [ Expression ]
871 =:
872
873Statement := [ AssignmentOrProcedureCall | IfStatement | CaseStatement |
874 WhileStatement | RepeatStatement | LoopStatement |
875 ForStatement | WithStatement | AsmStatement |
876 ExitStatement | ReturnStatement | RetryStatement
877 ]
878 =:
879
880RetryStatement := "RETRY"
881 =:
882
883AssignmentOrProcedureCall := Designator
884 ( ":=" Expression
885 |
886 ActualParameters | % (* epsilon *) %
887 )
888 =:
889
890-- these two break LL1 as both start with a Designator
891-- ProcedureCall := Designator [ ActualParameters ] =:
892-- Assignment := Designator ":=" Expression =:
893
894StatementSequence := Statement { ";" Statement }
895 =:
896
897IfStatement := "IF"
898 Expression "THEN"
899 StatementSequence
900 { "ELSIF"
901
902 Expression "THEN"
903 StatementSequence
904 }
905 [ "ELSE"
906 StatementSequence ] "END"
907 =:
908
909CaseStatement := "CASE"
910 Expression
911 "OF" Case { "|" Case }
912 CaseEndStatement
913 =:
914
915CaseEndStatement := "END"
916 | "ELSE"
917 StatementSequence "END"
918 =:
919
920Case := [ CaseLabelList ":" StatementSequence ]
921 =:
922
923CaseLabelList := CaseLabels { "," CaseLabels } =:
924
925CaseLabels := ConstExpression [ ".." ConstExpression ]
926 =:
927
928WhileStatement := "WHILE" Expression "DO"
929 StatementSequence
930 "END"
931 =:
932
933RepeatStatement := "REPEAT"
934 StatementSequence
935 "UNTIL" Expression
936 =:
937
938ForStatement :=
939 "FOR" Ident ":=" Expression "TO" Expression [ "BY" ConstExpression ] "DO"
940 StatementSequence
941 "END"
942 =:
943
944LoopStatement := "LOOP"
945 StatementSequence
946 "END"
947 =:
948
949WithStatement := "WITH" Designator "DO"
950 StatementSequence
951 "END"
952 =:
953
954ProcedureDeclaration := ProcedureHeading ";" ProcedureBlock
955 Ident
956 =:
957
958ProcedureIdent := Ident % curproc := lookupSym (curident) %
959 =:
960
961DefineBuiltinProcedure := [ "__ATTRIBUTE__" "__BUILTIN__" "(" "(" Ident ")" ")" | "__INLINE__" ]
962 =:
963
964ProcedureHeading := "PROCEDURE" DefineBuiltinProcedure ( ProcedureIdent % enterScope (curproc) %
965 [ FormalParameters ]
966 AttributeNoReturn )
967 =:
968
969Builtin := [ "__BUILTIN__" | "__INLINE__" ] =:
970
971DefProcedureHeading := "PROCEDURE" Builtin ( ProcedureIdent
972 [ DefFormalParameters ]
973 AttributeNoReturn )
974 =:
975
976-- introduced procedure block so we can produce more informative
977-- error messages
978
979ProcedureBlock := { Declaration } [ "BEGIN" ProcedureBlockBody ] "END" % leaveScope %
980 =:
981
982Block := { Declaration } InitialBlock FinalBlock "END"
983 =:
984
985InitialBlock := [ "BEGIN" InitialBlockBody ] =:
986
987FinalBlock := [ "FINALLY" FinalBlockBody ] =:
988
989InitialBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
990
991FinalBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
992
993ProcedureBlockBody := NormalPart [ "EXCEPT" ExceptionalPart ] =:
994
995NormalPart := StatementSequence =:
996
997ExceptionalPart := StatementSequence
998 =:
999
1000Declaration := "CONST" { ConstantDeclaration ";" } |
1001 "TYPE" { TypeDeclaration ";" } |
1002 "VAR" { VariableDeclaration ";" } |
1003 ProcedureDeclaration ";" |
1004 ModuleDeclaration ";" =:
1005
1006DefFormalParameters := "(" [ DefMultiFPSection ] ")" FormalReturn =:
1007
1008DefMultiFPSection := DefExtendedFP | FPSection [ ";" DefMultiFPSection ] =:
1009
1010FormalParameters := "(" [ MultiFPSection ] ")" FormalReturn =:
1011
1012AttributeNoReturn := [ "<*" Ident "*>" ] =:
1013
1014AttributeUnused := [ "<*" Ident "*>" ] =:
1015
1016MultiFPSection := ExtendedFP | FPSection [ ";" MultiFPSection ] =:
1017
1018FPSection := NonVarFPSection | VarFPSection =:
1019
1020DefExtendedFP := DefOptArg | "..." =:
1021
1022ExtendedFP := OptArg | "..." =:
1023
1024VarFPSection := "VAR" IdentList ":" FormalType [ AttributeUnused ] =:
1025
1026NonVarFPSection := IdentList ":" FormalType [ AttributeUnused ] =:
1027
1028OptArg := "[" Ident ":" FormalType [ "=" ConstExpression ] "]" =:
1029
1030DefOptArg := "[" Ident ":" FormalType "=" ConstExpression "]" =:
1031
1032FormalType := { "ARRAY" "OF" } Qualident =:
1033
1034ModuleDeclaration := "MODULE" Ident [ Priority ] ";"
1035 { Import } [ Export ]
1036 Block Ident
1037 =:
1038
1039Priority := "[" ConstExpression "]" =:
1040
1041Export := "EXPORT" ( "QUALIFIED"
1042 IdentList |
1043 "UNQUALIFIED"
1044 IdentList |
1045 IdentList ) ";" =:
1046
1047FromImport := "FROM" Ident "IMPORT" IdentList ";"
1048 =:
1049
1050ImportModuleList := Ident { "," Ident }
1051 =:
1052
1053WithoutFromImport := "IMPORT" ImportModuleList ";"
1054 =:
1055
1056Import := FromImport | WithoutFromImport =:
1057
1058DefinitionModule := "DEFINITION" "MODULE" [ "FOR" string ] Ident ";" % curmodule := lookupDef (curident) %
1059 % enterScope (curmodule) %
1060 { Import } [ Export ]
1061 { Definition }
1062 "END" Ident "." % checkEndName (curmodule, curident, 'definition module') %
1063 % leaveScope %
1064 % setEnumsComplete (curmodule) %
1065 =:
1066
1067DefQualident :=
1068 Ident % typeExp := lookupSym (curident) %
1069 [ "." % IF NOT isDef (typeExp)
1070 THEN
1071 ErrorArray ('the first component of this qualident must be a definition module')
1072 END %
1073 Ident % typeExp := lookupInScope (typeExp, curident) ;
1074 IF typeExp=NIL
1075 THEN
1076 ErrorArray ('identifier not found in definition module')
1077 END %
1078 ]
1079 =:
1080
1081DefOptSubrange := [ SubrangeType | % putType (typeDes, typeExp) %
1082 ]
1083 =:
1084
1085DefTypeEquiv := DefQualident DefOptSubrange =:
1086
1087DefEnumIdentList := % 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 %
1092 =:
1093
1094DefEnumeration := "(" DefEnumIdentList ")" =:
1095
1096DefSimpleType := DefTypeEquiv | DefEnumeration | SubrangeType
1097 =:
1098
1099DefType := DefSimpleType | ArrayType | RecordType | SetType |
1100 PointerType | ProcedureType
1101 =:
1102
1103DefTypeDeclaration := { Ident % typeDes := lookupSym (curident) %
1104 ( ";" | "=" DefType Alignment ";" ) }
1105 =:
1106
1107DefConstantDeclaration := Ident
1108 "=" ConstExpression
1109 =:
1110
1111Definition := "CONST" { DefConstantDeclaration ";" } |
1112 "TYPE" { DefTypeDeclaration } |
1113 "VAR" { DefVariableDeclaration ";" } |
1114 DefProcedureHeading ";" =:
1115
1116AsmStatement := 'ASM' [ 'VOLATILE' ] '(' AsmOperands ')' =:
1117
1118AsmOperands := string [ AsmOperandSpec ]
1119 =:
1120
1121AsmOperandSpec := [ ':' AsmList [ ':' AsmList [ ':' TrashList ] ] ]
1122 =:
1123
1124AsmList := [ AsmElement ] { ',' AsmElement } =:
1125
1126NamedOperand := '[' Ident ']' =:
1127
1128AsmOperandName := [ NamedOperand ]
1129 =:
1130
1131AsmElement := AsmOperandName string '(' Expression ')'
1132 =:
1133
1134TrashList := [ string ] { ',' string } =:
1135
1136FNB