1 (* ==================================================================== *)
3 (* Parser Module for the Gardens Point Component Pascal Compiler. *)
4 (* Copyright (c) John Gough 1999, 2000. *)
5 (* This module was extensively modified from the parser *)
6 (* automatically produced by the M2 version of COCO/R, using *)
7 (* the CPascal.atg grammar used for the JVM version of GPCP. *)
9 (* ==================================================================== *)
34 (* ==================================================================== *)
38 minErrDist
= 2; (* minimal distance (good tokens) between two errors *)
43 SymbolSet
= ARRAY (maxT
DIV setsize
+ 1) OF SET; (* 0 .. 2 *)
46 symSet
: ARRAY 13 OF SymbolSet
; (*symSet[0] = allSyncSyms*)
47 errDist
: INTEGER; (* number of symbols recognized since last error *)
48 token
: S
.Token
; (* current input symbol *)
49 nextT
: S
.Token
; (* lookahead input symbol *)
50 comma
: LitValue
.CharOpen
;
52 (* ==================================================================== *)
54 (* ==================================================================== *)
56 PROCEDURE Error (errNo
: INTEGER);
58 IF errDist
>= minErrDist
THEN
59 S
.ParseErr
.Report(errNo
, nextT
.lin
, nextT
.col
);
61 IF errNo
< 300 THEN errDist
:= 0 END;
64 (* ==================================================================== *)
66 PROCEDURE SemError(errNo
: INTEGER);
68 IF errDist
>= minErrDist
THEN
69 S
.SemError
.Report(errNo
, token
.lin
, token
.col
);
71 IF errNo
< 300 THEN errDist
:= 0 END;
74 (* ==================================================================== *)
76 PROCEDURE SemErrorS1(errNo
: INTEGER; IN str
: ARRAY OF CHAR);
78 IF errDist
>= minErrDist
THEN
79 S
.SemError
.RepSt1(errNo
, str
, token
.lin
, token
.col
);
81 IF errNo
< 300 THEN errDist
:= 0 END;
84 (* ==================================================================== *)
86 PROCEDURE SemErrorT(errNo
: INTEGER; tok
: S
.Token
);
88 IF errDist
>= minErrDist
THEN
89 S
.SemError
.Report(errNo
, tok
.lin
, tok
.col
);
91 IF errNo
< 300 THEN errDist
:= 0 END;
94 (* ==================================================================== *)
96 PROCEDURE TypeResolve(scp
: Sy
.Scope
);
99 * This visitor marks all reachable types with depth=REACHED;
101 scp
.symTb
.Apply(Visitor
.newResolver());
104 (* ==================================================================== *)
106 PROCEDURE bindToken(scp
: Sy
.Scope
) : Sy
.Idnt
;
109 hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
110 RETURN Sy
.bind(hash
, scp
);
113 (* ==================================================================== *)
115 PROCEDURE bindFieldToken(typ
: Sy
.Type
; tok
: S
.Token
) : Sy
.Idnt
;
121 * We must do a full bind here, rather than just a bind-local
122 * since we must look for inherited methods from the supertypes
124 hash
:= NameHash
.enterSubStr(tok
.pos
, tok
.len
);
125 WITH typ
: Ty
.Record
DO
126 RETURN typ
.bindField(hash
);
128 RETURN typ
.symTb
.lookup(hash
);
132 (* ==================================================================== *)
134 PROCEDURE bindTokenLocal(scp
: Sy
.Scope
) : Sy
.Idnt
;
137 hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
138 RETURN Sy
.bindLocal(hash
, scp
);
141 (* ==================================================================== *)
148 IF nextT
.sym
<= maxT
THEN INC(errDist
) ELSE Error(91) END;
149 UNTIL nextT
.sym
<= maxT
;
153 (* ==================================================================== *)
155 PROCEDURE in (VAR s
: SymbolSet
; x
: INTEGER): BOOLEAN;
157 RETURN x
MOD setsize
IN s
[x
DIV setsize
];
160 (* ==================================================================== *)
162 PROCEDURE Expect (n
: INTEGER);
164 IF nextT
.sym
= n
THEN Get
ELSE Error(n
) END;
167 (* ==================================================================== *)
169 PROCEDURE weakSeparator (n
, syFol
, repFol
: INTEGER): BOOLEAN;
174 IF nextT
.sym
= n
THEN Get
; RETURN TRUE
175 ELSIF in(symSet
[repFol
], nextT
.sym
) THEN RETURN FALSE
177 FOR i
:= 0 TO maxT
DIV setsize
DO
178 s
[i
] := symSet
[0, i
] + symSet
[syFol
, i
] + symSet
[repFol
, i
];
180 Error(n
); WHILE ~
in(s
, nextT
.sym
) DO Get
END;
181 RETURN in(symSet
[syFol
], nextT
.sym
)
185 (* ==================================================================== *)
186 (* Forward Procedure Declarations *)
187 (* ==================================================================== *)
189 PROCEDURE^
ActualParameters(VAR rslt
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
190 PROCEDURE^
ImportList (modScope
: Id
.BlkId
);
191 PROCEDURE^
DeclarationSequence (defScp
: Sy
.Scope
);
192 PROCEDURE^
ConstantDeclaration (defScp
: Sy
.Scope
);
193 PROCEDURE^
TypeDeclaration(defScp
: Sy
.Scope
);
194 PROCEDURE^
VariableDeclaration(defScp
: Sy
.Scope
);
195 PROCEDURE^
IdentDefList(OUT iSeq
: Sy
.IdSeq
; scp
: Sy
.Scope
; kind
: INTEGER);
196 PROCEDURE^
typeQualid(defScp
: Sy
.Scope
) : Id
.TypId
;
197 PROCEDURE^
qualident(defScp
: Sy
.Scope
) : Sy
.Idnt
;
198 PROCEDURE^
FPSection(VAR pars
: Id
.ParSeq
; thisP
, defScp
: Sy
.Scope
);
199 PROCEDURE^
type(defScp
: Sy
.Scope
; vMod
: INTEGER) : Sy
.Type
;
200 PROCEDURE^
identDef(inhScp
: Sy
.Scope
; tag
: INTEGER) : Sy
.Idnt
;
201 PROCEDURE^
constExpression(defScp
: Sy
.Scope
) : Xp
.LeafX
;
202 PROCEDURE^
expression(scope
: Sy
.Scope
) : Sy
.Expr
;
203 PROCEDURE^
designator(inhScp
: Sy
.Scope
) : Sy
.Expr
;
204 PROCEDURE^
OptExprList(VAR xList
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
205 PROCEDURE^
ExprList(VAR xList
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
206 PROCEDURE^
statementSequence(inhLp
: Sy
.Stmt
; inhSc
: Sy
.Scope
) : Sy
.Stmt
;
207 PROCEDURE^
ProcedureStuff(scope
: Sy
.Scope
);
208 PROCEDURE^
CheckVisibility(seq
: Sy
.IdSeq
; in
: INTEGER; OUT out
: INTEGER);
209 PROCEDURE^
FormalParameters(thsP
: Ty
.Procedure
;
213 (* ==================================================================== *)
215 PROCEDURE CPmodule();
216 VAR name
: LitValue
.CharOpen
;
220 Cs
.thisMod
.hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
221 Cs
.thisMod
.token
:= token
;
222 Sy
.getName
.Of(Cs
.thisMod
, Cs
.modNam
);
223 (* Manual addition 15-June-2000. *)
224 IF nextT
.sym
= T
.lbrackSym
THEN
226 IF Cs
.strict
THEN SemError(221); END;
228 name
:= LitValue
.subStrToCharOpen(token
.pos
+1, token
.len
-2);
229 Cs
.thisMod
.scopeNm
:= name
;
231 IF Cs
.verbose
THEN Cs
.Message('external modName
"' + name^ + '"'
) END;
233 (* End addition 15-June-2000 kjg *)
234 Expect(T
.semicolonSym
);
235 IF (nextT
.sym
= T
.IMPORTSym
) THEN
236 ImportList(Cs
.thisMod
);
238 Sy
.ResetScpSeq(Cs
.impSeq
);
240 DeclarationSequence(Cs
.thisMod
);
241 IF (nextT
.sym
= T
.BEGINSym
) THEN
242 Cs
.thisMod
.begTok
:= nextT
;
245 * "BEGIN" [ '[' "UNCHECKED_ARITHMETIC" ']' ] ...
247 IF nextT
.sym
= T
.lbrackSym
THEN
249 IF Cs
.strict
THEN SemError(221); END;
251 IF NameHash
.enterSubStr(token
.pos
, token
.len
) = Bi
.noChkB
THEN
252 Cs
.thisMod
.ovfChk
:= FALSE
;
258 Cs
.thisMod
.modBody
:= statementSequence(NIL, Cs
.thisMod
);
259 IF (nextT
.sym
= T
.CLOSESym
) THEN
261 Cs
.thisMod
.modClose
:= statementSequence(NIL, Cs
.thisMod
);
266 (* ==================================================================== *)
268 PROCEDURE ForeignMod();
269 VAR name
: LitValue
.CharOpen
;
273 Cs
.thisMod
.hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
274 Cs
.thisMod
.token
:= token
;
275 Sy
.getName
.Of(Cs
.thisMod
, Cs
.modNam
);
276 IF nextT
.sym
= T
.lbrackSym
THEN
279 name
:= LitValue
.subStrToCharOpen(token
.pos
+1, token
.len
-2);
280 Cs
.thisMod
.scopeNm
:= name
;
282 IF Cs
.verbose
THEN Cs
.Message('external modName
"' + name^ + '"'
) END;
284 Expect(T
.semicolonSym
);
285 IF (nextT
.sym
= T
.IMPORTSym
) THEN
286 ImportList(Cs
.thisMod
);
288 Sy
.ResetScpSeq(Cs
.impSeq
);
290 DeclarationSequence(Cs
.thisMod
);
293 (* ==================================================================== *)
295 PROCEDURE Import (modScope
: Id
.BlkId
; VAR impSeq
: Sy
.ScpSeq
);
296 VAR ident
: Id
.BlkId
; (* The imported module name descriptor *)
297 alias
: Id
.BlkId
; (* The declared alias name (optional) *)
301 strng
: LitValue
.CharOpen
;
302 impNm
: LitValue
.CharOpen
;
305 ident
:= Id
.newImpId();
307 IF (nextT
.sym
= T
.colonequalSym
) THEN
308 alias
:= Id
.newAlias();
309 alias
.hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
310 IF Sy
.refused(alias
, modScope
) THEN SemError(4) END;
311 Get
; (* Read past colonequals symbol *)
314 * Here is ^ the experimental processing for the option
315 * of using a literal string at this position. If there
316 * is a literal string, it should be mapped to the default
319 IF nextT
.sym
= T
.stringSym
THEN
321 strng
:= LitValue
.subStrToCharOpen(token
.pos
+1, token
.len
-2);
322 ForeignName
.ParseModuleString(strng
, impNm
);
323 alias
.token
:= token
; (* fake the name for err-msg use *)
324 idHsh
:= NameHash
.enterStr(impNm
);
325 IF Cs
.strict
THEN Error(221) END;
328 alias
.token
:= token
; (* fake the name for err-msg use *)
329 ident
.aliasMod
:= alias
;
330 IF Cs
.verbose
THEN alias
.SetNameFromHash(alias
.hash
) END;
331 idHsh
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
334 idHsh
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
336 ident
.token
:= token
;
337 ident
.dfScp
:= ident
;
340 IF Cs
.verbose
THEN ident
.SetNameFromHash(idHsh
) END;
342 IF ident
.hash
= Bi
.sysBkt
THEN
343 dummy
:= Cs
.thisMod
.symTb
.enter(Bi
.sysBkt
, Cs
.sysMod
);
344 IF Cs
.verbose
THEN Cs
.Message("imports unsafe SYSTEM module") END;
345 IF ~Cs
.unsafe
THEN SemError(227);
346 ELSIF ~Cs
.targetIsNET() THEN SemError(228);
349 INCL(ident
.xAttr
, Sy
.weak
);
352 clash
:= Sy
.bind(ident
.hash
, modScope
);
354 dummy
:= Sy
.refused(ident
, modScope
);
355 ELSIF clash
.kind
= Id
.impId
THEN
357 * This import might already be known as a result of an
358 * indirect import. If that is the case, then we must
359 * substitute the old descriptor for "ident" in case there
360 * there are already references to it in the structure.
362 clash
.token
:= ident
.token
; (* to help error reports *)
363 IF Cs
.verbose
THEN clash
.SetNameFromHash(clash
.hash
) END;
364 ident
:= clash(Id
.BlkId
);
366 * If this is the explicit import of a module that
367 * has an alias, then all is ok, make import usable.
369 IF ident
.aliasMod
# NIL THEN
370 EXCL(ident
.xAttr
, Sy
.anon
);
371 IF alias
# NIL THEN (* multiple aliases for same module *)
372 SemErrorS1(240, Sy
.getName
.ChPtr(ident
.aliasMod
));
375 * If ident is the target of an alias then the
376 * target is also made visible in the module.
378 ELSIF alias
# NIL THEN
379 ident
.aliasMod
:= alias
;
381 * Else this really is an error.
383 ELSIF ~ident
.isWeak() &
384 (ident
.hash
# Bi
.sysBkt
) THEN SemError(170); (* imported twice *)
390 IF ident
.hash
= NameHash
.mainBkt
THEN
391 modScope
.main
:= TRUE
; (* the import is "CPmain" *)
392 IF Cs
.verbose
THEN Cs
.Message("contains CPmain entry point") END;
393 INCL(modScope
.xAttr
, Sy
.cMain
); (* Console Main *)
394 ELSIF ident
.hash
= NameHash
.winMain
THEN
395 modScope
.main
:= TRUE
; (* the import is "WinMain" *)
396 INCL(modScope
.xAttr
, Sy
.wMain
); (* Windows Main *)
397 IF Cs
.verbose
THEN Cs
.Message("contains WinMain entry point") END;
398 ELSIF ident
.hash
= NameHash
.staBkt
THEN
399 INCL(modScope
.xAttr
, Sy
.sta
);
400 IF Cs
.verbose
THEN Cs
.Message("sets Single Thread Apartment") END;
403 IF Sy
.weak
IN ident
.xAttr
THEN
405 * Module ident is a newly declared import.
406 * List the file, for importation later ...
408 Sy
.AppendScope(impSeq
, ident
);
409 IF alias
# NIL THEN INCL(ident
.xAttr
, Sy
.anon
) END;
410 EXCL(ident
.xAttr
, Sy
.weak
); (* ==> directly imported *)
411 INCL(ident
.xAttr
, Sy
.need
); (* ==> needed in symfile *)
414 * Alias (if any) must appear after ImpId
417 alias
.dfScp
:= ident
;
418 Sy
.AppendScope(impSeq
, alias
);
422 PROCEDURE ImportThreading(modScope
: Id
.BlkId
; VAR impSeq
: Sy
.ScpSeq
);
426 hash
:= NameHash
.enterStr("mscorlib_System_Threading");
427 idnt
:= Id
.newImpId();
430 IF ~Sy
.refused(idnt
, modScope
) THEN
431 EXCL(idnt
.xAttr
, Sy
.weak
);
432 INCL(idnt
.xAttr
, Sy
.need
);
433 Sy
.AppendScope(impSeq
, idnt
);
437 (* ==================================================================== *)
439 PROCEDURE ImportList (modScope
: Id
.BlkId
);
443 Sy
.ResetScpSeq(Cs
.impSeq
);
444 Import(modScope
, Cs
.impSeq
);
445 WHILE (nextT
.sym
= T
.commaSym
) DO
447 Import(modScope
, Cs
.impSeq
);
449 Expect(T
.semicolonSym
);
451 * Now some STA-specific tests.
453 IF Sy
.sta
IN modScope
.xAttr
THEN
455 ImportThreading(modScope
, Cs
.impSeq
);
459 IF ~modScope
.main
THEN
461 EXCL(modScope
.xAttr
, Sy
.sta
);
465 Cs
.import1
:= RTS
.GetMillis();
467 OldSymFileRW
.WalkImports(Cs
.impSeq
, modScope
);
469 NewSymFileRW
.WalkImports(Cs
.impSeq
, modScope
);
471 Cs
.import2
:= RTS
.GetMillis();
474 (* ==================================================================== *)
476 PROCEDURE FPSection(VAR pars
: Id
.ParSeq
; thisP
, defScp
: Sy
.Scope
);
477 (* sequence is passed in from the caller *)
483 pTst
: BOOLEAN; (* test if formal type is private *)
484 (* --------------------------- *)
485 PROCEDURE isPrivate(t
: Sy
.Type
) : BOOLEAN;
487 RETURN ~
(t
IS Ty
.Base
) & (t
.idnt
.vMod
= Sy
.prvMode
);
489 (* --------------------------- *)
490 PROCEDURE CheckFormalType(tst
: BOOLEAN; tok
: S
.Token
; typ
: Sy
.Type
);
492 * There are two separate kinds of tests here:
493 * * formals must not be less visible than the procedure
494 * * anonymous formals are only useful in two cases:
495 * - open arrays, provided the element type is visible enough;
496 * - pointer types, provided the bound type is visible enough.
498 IF typ
= NIL THEN RETURN;
499 ELSIF typ
.idnt
# NIL THEN
500 IF tst
& isPrivate(typ
) THEN SemErrorT(150, tok
) END;
502 WITH typ
: Ty
.Record
DO
504 | typ
: Ty
.Pointer
DO
505 CheckFormalType(tst
, tok
, typ
.boundTp
);
507 CheckFormalType(tst
, tok
, typ
.elemTp
);
508 (* Open arrays and vectors have length = 0 *)
509 IF typ
.length
# 0 THEN SemErrorT(315, tok
) END;
510 ELSE (* skip procs? *)
514 (* --------------------------- *)
516 Id
.ResetParSeq(pars
); (* make sequence empty *)
517 IF nextT
.sym
= T
.INSym
THEN
520 ELSIF nextT
.sym
= T
.OUTSym
THEN
523 ELSIF nextT
.sym
= T
.VARSym
THEN
529 parD
:= identDef(defScp
, Id
.parId
)(Id
.ParId
);
530 Id
.AppendParam(pars
, parD
);
531 WHILE weakSeparator(12, 1, 2) DO
532 parD
:= identDef(defScp
, Id
.parId
)(Id
.ParId
);
533 Id
.AppendParam(pars
, parD
);
537 tpDx
:= type(defScp
, Sy
.prvMode
);
539 pTst
:= ~Cs
.special
& (thisP
# NIL) & (thisP
.vMod
= Sy
.pubMode
);
541 CheckFormalType(pTst
, tokn
, tpDx
);
543 FOR indx
:= 0 TO pars
.tide
-1 DO
544 pars
.a
[indx
].parMod
:= mode
;
545 pars
.a
[indx
].type
:= tpDx
;
550 (* ==================================================================== *)
552 PROCEDURE DeclarationSequence (defScp
: Sy
.Scope
);
554 WHILE (nextT
.sym
= T
.CONSTSym
) OR
555 (nextT
.sym
= T
.TYPESym
) OR
556 (nextT
.sym
= T
.VARSym
) DO
557 IF (nextT
.sym
= T
.CONSTSym
) THEN
559 WHILE (nextT
.sym
= T
.identSym
) DO
560 ConstantDeclaration(defScp
);
561 Expect(T
.semicolonSym
);
563 ELSIF (nextT
.sym
= T
.TYPESym
) THEN
565 WHILE (nextT
.sym
= T
.identSym
) DO
566 TypeDeclaration(defScp
);
567 Expect(T
.semicolonSym
);
571 WHILE (nextT
.sym
= T
.identSym
) DO
572 VariableDeclaration(defScp
);
573 Expect(T
.semicolonSym
);
577 (* Last chance to resolve forward types in this block *)
578 defScp
.endDecl
:= TRUE
;
580 (* Now the local procedures *)
581 WHILE (nextT
.sym
= T
.PROCEDURESym
) DO
582 ProcedureStuff(defScp
);
583 Expect(T
.semicolonSym
);
585 END DeclarationSequence
;
587 (* ==================================================================== *)
589 PROCEDURE otherAtts(in
: SET) : SET;
591 IF nextT
.sym
= T
.ABSTRACTSym
THEN
593 RETURN in
+ Id
.isAbs
;
594 ELSIF nextT
.sym
= T
.EMPTYSym
THEN
596 RETURN in
+ Id
.empty
;
597 ELSIF nextT
.sym
= T
.EXTENSIBLESym
THEN
599 RETURN in
+ Id
.extns
;
606 (* ==================================================================== *)
608 PROCEDURE^
MethAttributes(pDesc
: Id
.Procs
);
610 (* ==================================================================== *)
612 PROCEDURE receiver(scope
: Sy
.Scope
) : Id
.ParId
;
617 Get
; (* read past lparenSym *)
618 IF nextT
.sym
= T
.INSym
THEN
621 ELSIF nextT
.sym
= T
.VARSym
THEN
627 parD
:= identDef(scope
, Id
.parId
)(Id
.ParId
);
632 rcvD
:= bindToken(scope
);
635 ELSIF ~
(rcvD
IS Id
.TypId
) THEN
638 parD
.type
:= rcvD
.type
;
644 (* ==================================================================== *)
646 PROCEDURE ExceptBody(pInhr
: Id
.Procs
);
650 * This procedure has an exception handler. We must...
651 * (i) define a local to hold the exception value
652 * (ii) parse the rescue statement sequence
655 excp
:= identDef(pInhr
, Id
.varId
)(Id
.LocId
);
656 excp
.SetKind(Id
.conId
); (* mark immutable *)
657 excp
.type
:= Cs
.ntvExc
;
658 excp
.varOrd
:= pInhr
.locals
.tide
;
659 IF Sy
.refused(excp
, pInhr
) THEN
662 Sy
.AppendIdnt(pInhr
.locals
, excp
);
663 pInhr
.except
:= excp
;
666 pInhr
.rescue
:= statementSequence(NIL, pInhr
); (* inhLp is NIL *)
669 (* ==================================================================== *)
671 PROCEDURE ProcedureBody(pInhr
: Id
.Procs
);(* Inherited descriptor *)
673 DeclarationSequence(pInhr
);
674 IF nextT
.sym
= T
.BEGINSym
THEN
677 * "BEGIN" [ '[' "UNCHECKED_ARITHMETIC" ']' ] ...
679 IF nextT
.sym
= T
.lbrackSym
THEN
682 IF NameHash
.enterSubStr(token
.pos
, token
.len
) = Bi
.noChkB
THEN
683 pInhr
.ovfChk
:= FALSE
;
689 pInhr
.body
:= statementSequence(NIL, pInhr
); (* inhLp is NIL *)
691 IF nextT
.sym
= T
.RESCUESym
THEN
693 IF Cs
.strict
THEN SemError(221); END;
699 (* ==================================================================== *)
701 PROCEDURE procedureHeading(scope
: Sy
.Scope
) : Id
.Procs
;
706 name
: LitValue
.CharOpen
;
708 IF nextT
.sym
# T
.lparenSym
THEN
710 prcD
:= identDef(scope
, Id
.conPrc
)(Id
.Procs
);
711 prcD
.SetKind(Id
.conPrc
);
713 rcvD
:= receiver(scope
);
714 mthD
:= identDef(scope
, Id
.conMth
)(Id
.MthId
);
715 mthD
.SetKind(Id
.conMth
);
716 IF (rcvD
.type
# NIL) &
717 (rcvD
.type
.idnt
# NIL) THEN
718 IF rcvD
.type
.isInterfaceType() &
719 (mthD
.vMod
= Sy
.prvMode
) THEN SemError(216);
724 IF Sy
.refused(rcvD
, mthD
) THEN (* insert receiver in scope *)
725 rcvD
.IdError(4); (* refusal impossible maybe? *)
727 rcvD
.dfScp
:= mthD
; (* Correct the defScp *)
728 rcvD
.varOrd
:= mthD
.locals
.tide
;
729 Sy
.AppendIdnt(mthD
.locals
, rcvD
);
732 IF nextT
.sym
= T
.lbrackSym
THEN
733 IF ~Cs
.special
THEN SemError(144) END;
736 name
:= LitValue
.subStrToCharOpen(token
.pos
+1, token
.len
-2);
739 IF Cs
.verbose
THEN Cs
.Message('external procName
"' + name^ + '"'
) END;
741 prcT
:= Ty
.newPrcTp();
744 IF prcD
.vMod
# Sy
.prvMode
THEN INCL(prcD
.pAttr
, Id
.public
) END;
745 IF nextT
.sym
= T
.lparenSym
THEN
746 FormalParameters(prcT
, prcD
, scope
);
748 IF nextT
.sym
= T
.commaSym
THEN
750 MethAttributes(prcD
);
752 IF rcvD
# NIL THEN prcT
.receiver
:= rcvD
.type
END;
753 prcD
.EnterProc(rcvD
, scope
);
755 END procedureHeading
;
757 (* ==================================================================== *)
759 PROCEDURE ProcDeclStuff(scope
: Sy
.Scope
);
761 name
: FileNames
.NameString
;
762 pNam
: FileNames
.NameString
;
765 desc
:= procedureHeading(scope
);
766 WITH scope
: Id
.Procs
DO (* a nested proc *)
767 Id
.AppendProc(scope
.nestPs
, desc
);
768 desc
.lxDepth
:= scope
.lxDepth
+ 1;
772 Id
.AppendProc(Cs
.thisMod
.procs
, desc
);
773 IF ~desc
.isEmpty() & ~Cs
.isForeign() THEN
774 Expect(T
.semicolonSym
);
776 desc
.endSpan
:= S
.mkSpanTT(token
, nextT
);
778 (* check closing name *)
779 S
.GetString(token
.pos
, token
.len
, name
);
780 Sy
.getName
.Of(desc
, pNam
);
782 IF token
.sym
= T
.identSym
THEN errN
:= 1 ELSE errN
:= 0 END;
783 SemErrorS1(errN
, pNam$
);
788 (* ==================================================================== *)
790 PROCEDURE ForwardStuff(scope
: Sy
.Scope
);
793 Get
; (* read past uparrowSym *)
794 desc
:= procedureHeading(scope
);
795 (* Set lexical depth for forward procs as well. kjg Sep-2001 *)
796 WITH scope
: Id
.Procs
DO (* a nested proc *)
797 desc
.lxDepth
:= scope
.lxDepth
+ 1;
801 IF desc
.kind
= Id
.conMth
THEN
802 desc
.setPrcKind(Id
.fwdMth
);
803 ELSIF desc
.kind
= Id
.conPrc
THEN
804 desc
.setPrcKind(Id
.fwdPrc
);
806 Id
.AppendProc(Cs
.thisMod
.procs
, desc
);
809 (* ==================================================================== *)
811 PROCEDURE ProcedureStuff(scope
: Sy
.Scope
);
812 (* parse procedure and add to list in scope *)
814 Get
; (* read past PROCEDURESym *)
815 IF nextT
.sym
= T
.uparrowSym
THEN
817 ELSIF (nextT
.sym
= T
.identSym
) OR
818 (nextT
.sym
= T
.lparenSym
) THEN
819 ProcDeclStuff(scope
);
824 (* ==================================================================== *)
826 PROCEDURE guard(scope
: Sy
.Scope
) : Sy
.Expr
;
827 VAR expr
: Xp
.BinaryX
;
829 dstX
: Sy
.Expr
; (* should be typeQualid *)
831 qual
:= Xp
.mkIdLeaf(qualident(scope
));
833 expr
:= Xp
.newBinaryX(Xp
.isOp
, qual
, NIL);
834 dstX
:= Xp
.mkIdLeaf(typeQualid(scope
));
835 (* Check #1 : that the expression has a type that is dynamic *)
836 IF ~qual
.hasDynamicType() THEN qual
.ExprError(17) END;
837 (* Check #2 : that manifest type is a base of the asserted type *)
838 IF (qual
.type
# NIL) &
839 ~qual
.type
.isBaseOf(dstX
.type
) &
840 ~qual
.type
.isInterfaceType() &
841 ~dstX
.type
.isInterfaceType() THEN SemError(15) END;
846 (* ==================================================================== *)
848 PROCEDURE caseLabel(chTp
: BOOLEAN;
850 scope
: Sy
.Scope
) : StatDesc
.Triple
;
851 VAR lExp
, rExp
: Sy
.Expr
;
857 lExp
:= constExpression(scope
);
860 IF lExp
.isCharLit() THEN
861 lo
:= ORD(lExp(Xp
.LeafX
).charValue());
863 lExp
.ExprError(43); xpOk
:= FALSE
;
866 IF lExp
.isNumLit() THEN
867 lo
:= lExp(Xp
.LeafX
).value
.int();
869 lExp
.ExprError(37); xpOk
:= FALSE
;
874 IF nextT
.sym
= T
.pointpointSym
THEN
876 rExp
:= constExpression(scope
);
879 IF rExp
.isCharLit() THEN
880 hi
:= ORD(rExp(Xp
.LeafX
).charValue());
882 rExp
.ExprError(43); xpOk
:= FALSE
;
885 IF rExp
.isNumLit() THEN
886 hi
:= rExp(Xp
.LeafX
).value
.int();
888 rExp
.ExprError(37); xpOk
:= FALSE
;
893 IF xpOk
& (lo
> hi
) THEN lExp
.ExprError(30) END;
897 RETURN StatDesc
.newTriple(lo
, hi
, tide
);
900 (* ==================================================================== *)
902 PROCEDURE CaseLabelList(VAR labels
: StatDesc
.TripleSeq
;
906 VAR next
: StatDesc
.Triple
;
908 next
:= caseLabel(isChar
, stTide
, scope
);
909 StatDesc
.AppendTriple(labels
, next
);
910 WHILE nextT
.sym
= T
.commaSym
DO
912 next
:= caseLabel(isChar
, stTide
, scope
);
913 StatDesc
.AppendTriple(labels
, next
);
917 (* ==================================================================== *)
919 PROCEDURE Case(desc
: StatDesc
.CaseSt
; inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
);
921 IF in(symSet
[3], nextT
.sym
) THEN
922 CaseLabelList(desc
.labels
, desc
.chrSel
, desc
.blocks
.tide
, scope
);
924 Sy
.AppendStmt(desc
.blocks
, statementSequence(inhLp
, scope
));
928 (* ==================================================================== *)
930 PROCEDURE ActualParameters(VAR rslt
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
933 OptExprList(rslt
, inhScp
);
935 END ActualParameters
;
937 (* ==================================================================== *)
939 PROCEDURE withStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
940 VAR synthS
: StatDesc
.Choice
;
947 synthS
:= StatDesc
.newWithS();
948 IF nextT
.sym
= T
.ENDSym
THEN
952 ELSIF nextT
.sym
= T
.barSym
THEN
954 IF Cs
.strict
THEN SemError(221); END;
956 IF nextT
.sym
# T
.ELSESym
THEN
957 predXp
:= guard(scope
);
960 tmpId
:= Id
.newLocId();
961 tmpId
.dfScp
:= scope
;
963 savedI
:= predXp
.enterGuard(tmpId
);
964 block
:= statementSequence(inhLp
, scope
);
965 predXp
.ExitGuard(savedI
, tmpId
);
966 Sy
.AppendIdnt(synthS
.temps
, tmpId
);
967 Sy
.AppendExpr(synthS
.preds
, predXp
);
968 Sy
.AppendStmt(synthS
.blocks
, block
);
969 WHILE nextT
.sym
= T
.barSym
DO
971 predXp
:= guard(scope
);
974 tmpId
:= Id
.newLocId();
975 tmpId
.dfScp
:= scope
;
977 savedI
:= predXp
.enterGuard(tmpId
);
978 block
:= statementSequence(inhLp
, scope
);
979 predXp
.ExitGuard(savedI
, tmpId
);
980 Sy
.AppendIdnt(synthS
.temps
, tmpId
);
981 Sy
.AppendExpr(synthS
.preds
, predXp
);
982 Sy
.AppendStmt(synthS
.blocks
, block
);
985 IF nextT
.sym
= T
.ELSESym
THEN
987 block
:= statementSequence(inhLp
, scope
);
988 Sy
.AppendIdnt(synthS
.temps
, NIL);
989 Sy
.AppendExpr(synthS
.preds
, NIL);
990 Sy
.AppendStmt(synthS
.blocks
, block
);
996 (* ==================================================================== *)
998 PROCEDURE loopStatement(scope
: Sy
.Scope
) : Sy
.Stmt
;
999 (* This procedure ignores the inherited attribute which for *
1000 * other cases designates the enclosing loop. This becomes *
1001 * the source of the enclosing loop for all nested statements *)
1002 VAR newLoop
: StatDesc
.TestLoop
;
1005 newLoop
:= StatDesc
.newLoopS();
1006 newLoop
.body
:= statementSequence(newLoop
, scope
);
1011 (* ==================================================================== *)
1013 PROCEDURE forStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1014 VAR rslt
: StatDesc
.ForLoop
;
1017 (* ------------------------- *)
1018 PROCEDURE Check(id
: Sy
.Idnt
);
1020 IF id
= NIL THEN SemError(2);
1021 ELSIF ~
(id
IS Id
.AbVar
) THEN SemError(85);
1022 ELSIF ~id
.mutable() THEN SemError(103);
1023 ELSIF (id
.type
# NIL) & ~id
.type
.isIntType() THEN SemError(84);
1026 (* ------------------------- *)
1030 rslt
:= StatDesc
.newForStat();
1032 cIdn
:= bindToken(scope
);
1034 Expect(T
.colonequalSym
);
1036 rslt
.loXp
:= expression(scope
);
1038 rslt
.hiXp
:= expression(scope
);
1039 IF (nextT
.sym
= T
.BYSym
) THEN
1041 rslt
.byXp
:= constExpression(scope
);
1042 IF rslt
.byXp
# NIL THEN
1043 IF rslt
.byXp
.kind
# Xp
.numLt
THEN
1044 rslt
.byXp
.ExprError(59);
1045 ELSIF rslt
.byXp(Xp
.LeafX
).value
.long() = 0 THEN
1046 rslt
.byXp
.ExprError(81);
1050 rslt
.byXp
:= Xp
.mkNumLt(1);
1053 rslt
.body
:= statementSequence(inhLp
, scope
);
1058 (* ==================================================================== *)
1060 PROCEDURE repeatStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1061 VAR rslt
: StatDesc
.TestLoop
;
1064 rslt
:= StatDesc
.newRepeatS();
1065 rslt
.body
:= statementSequence(inhLp
, scope
);
1067 rslt
.test
:= expression(scope
);
1069 END repeatStatement
;
1071 (* ==================================================================== *)
1073 PROCEDURE whileStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1074 VAR rslt
: StatDesc
.TestLoop
;
1077 rslt
:= StatDesc
.newWhileS();
1078 rslt
.test
:= expression(scope
);
1080 rslt
.body
:= statementSequence(inhLp
, scope
);
1085 (* ==================================================================== *)
1087 PROCEDURE caseStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1088 VAR rslt
: StatDesc
.CaseSt
;
1093 rslt
:= StatDesc
.newCaseS();
1094 slct
:= expression(scope
);
1096 IF slct
# NIL THEN slct
:= slct
.exprAttr() END;
1097 IF (slct
# NIL) & (slct
.type
# NIL) THEN
1098 rslt
.chrSel
:= FALSE
;
1099 rslt
.select
:= slct
;
1100 IF slct
.isCharExpr() THEN
1101 rslt
.chrSel
:= TRUE
;
1102 ELSIF slct
.isIntExpr() THEN
1103 IF slct
.type
.isLongType() THEN slct
.ExprError(141) END;
1108 IF nextT
.sym
= T
.ENDSym
THEN
1111 Case(rslt
, inhLp
, scope
);
1112 WHILE nextT
.sym
= T
.barSym
DO
1114 Case(rslt
, inhLp
, scope
);
1116 IF nextT
.sym
= T
.ELSESym
THEN
1118 rslt
.elsBlk
:= statementSequence(inhLp
, scope
);
1125 (* ==================================================================== *)
1127 PROCEDURE ifStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1128 VAR synthStat
: StatDesc
.Choice
;
1131 synthStat
:= StatDesc
.newIfStat();
1132 Sy
.AppendExpr(synthStat
.preds
, expression(scope
));
1134 Sy
.AppendStmt(synthStat
.blocks
, statementSequence(inhLp
, scope
));
1135 WHILE nextT
.sym
= T
.ELSIFSym
DO
1137 Sy
.AppendExpr(synthStat
.preds
, expression(scope
));
1139 Sy
.AppendStmt(synthStat
.blocks
, statementSequence(inhLp
, scope
));
1141 IF (nextT
.sym
= T
.ELSESym
) THEN
1143 Sy
.AppendExpr(synthStat
.preds
, NIL);
1144 Sy
.AppendStmt(synthStat
.blocks
, statementSequence(inhLp
, scope
));
1150 (* ==================================================================== *)
1152 PROCEDURE^
ConvertOverloaded(VAR e
: Sy
.Expr
);
1154 PROCEDURE^
makeCall(xCr
: Sy
.Expr
; IN actuals
: Sy
.ExprSeq
;
1155 inhScp
: Sy
.Scope
) : Sy
.Expr
;
1157 (* ==================================================================== *)
1159 PROCEDURE identStatement(inhLp
: Sy
.Stmt
; scope
: Sy
.Scope
) : Sy
.Stmt
;
1160 VAR assign
: StatDesc
.Assign
;
1161 prCall
: StatDesc
.ProcCall
;
1162 argLst
: Sy
.ExprSeq
;
1168 desig
:= designator(scope
);
1169 IF nextT
.sym
= T
.colonequalSym
THEN
1170 ConvertOverloaded(desig
);
1171 IF desig
# NIL THEN desig
.tSpan
:= S
.mkSpanTT(saveT
, S
.prevTok
) END;
1173 assign
:= StatDesc
.newAssignS();
1174 value
:= expression(scope
);
1175 assign
.lhsX
:= desig
;
1176 assign
.rhsX
:= value
;
1177 Xp
.CheckIsVariable(desig
);
1179 ELSIF in(symSet
[8], nextT
.sym
) THEN
1180 IF (desig
# NIL) & ~
(desig
IS Xp
.CallX
) THEN
1181 desig
:= makeCall(desig
,argLst
,scope
);
1183 prCall
:= StatDesc
.newProcCall();
1184 prCall
.expr
:= desig
;
1185 IF desig
# NIL THEN desig
.tSpan
:= S
.mkSpanTT(saveT
, S
.prevTok
) END;
1187 (desig
.type
# NIL) & ~desig
.type
.isProperProcType() THEN
1188 desig
.ExprError(182);
1191 ELSE Error(82); RETURN StatDesc
.newEmptyS();
1195 (* ==================================================================== *)
1197 PROCEDURE statement(inhLp
: Sy
.Stmt
; inhSc
: Sy
.Scope
) : Sy
.Stmt
;
1198 VAR synthStat
: Sy
.Stmt
;
1199 synthExpr
: Sy
.Expr
;
1200 keywordTk
: S
.Token
;
1202 (* ------------------------- *)
1204 PROCEDURE newStatement(inhSc
: Sy
.Scope
) : Sy
.Stmt
;
1205 (* This case is pulled out of line, so that the cost of *
1206 * initialisation of the sequence is only paid when needed *)
1207 VAR argList
: Sy
.ExprSeq
;
1210 callNew
: StatDesc
.ProcCall
;
1213 callNew
:= StatDesc
.newProcCall();
1214 ActualParameters(argList
, inhSc
);
1215 qualId
:= Xp
.mkIdLeaf(Bi
.newPd
);
1216 callExp
:= Xp
.newCallX(Xp
.prCall
, argList
, qualId
);
1217 callExp
.tSpan
:= S
.mkSpanTT(callNew
.token
, S
.prevTok
);
1218 callNew
.expr
:= callExp
;
1222 (* ------------------------- *)
1226 IF in(symSet
[9], nextT
.sym
) THEN
1229 synthStat
:= identStatement(inhLp
, inhSc
);
1231 synthStat
:= loopStatement(inhSc
);
1233 synthStat
:= ifStatement(inhLp
, inhSc
);
1235 synthStat
:= caseStatement(inhLp
, inhSc
);
1237 synthStat
:= whileStatement(inhLp
, inhSc
);
1239 synthStat
:= repeatStatement(inhLp
, inhSc
);
1241 synthStat
:= forStatement(inhLp
, inhSc
);
1243 synthStat
:= withStatement(inhLp
, inhSc
);
1245 synthStat
:= newStatement(inhSc
);
1247 (* Semantic action is inline *)
1249 synthStat
:= StatDesc
.newExitS(inhLp
);
1250 IF inhLp
= NIL THEN SemError(58) END;
1252 (* Semantic action is inline *)
1254 IF in(symSet
[3], nextT
.sym
) THEN
1255 synthExpr
:= expression(inhSc
);
1259 synthStat
:= StatDesc
.newReturnS(synthExpr
);
1260 synthStat
.token
:= keywordTk
;
1261 ELSE synthStat
:= StatDesc
.newEmptyS();
1265 synthStat
:= StatDesc
.newEmptyS();
1270 (* ==================================================================== *)
1272 PROCEDURE statementSequence(inhLp
: Sy
.Stmt
; inhSc
: Sy
.Scope
) : Sy
.Stmt
;
1273 VAR block
: StatDesc
.Block
;
1276 WHILE ~
(in(symSet
[4], nextT
.sym
)) DO Error(80); Get
END;
1277 first
:= statement(inhLp
, inhSc
);
1279 WHILE weakSeparator(22, 5, 6) DO
1280 WHILE ~
(in(symSet
[4], nextT
.sym
)) DO Error(81); Get
END;
1282 block
:= StatDesc
.newBlockS(first
.token
);
1283 IF first
.kind
# StatDesc
.emptyS
THEN Sy
.AppendStmt(block
.sequ
,first
) END
1285 first
:= statement(inhLp
, inhSc
);
1286 IF first
.kind
# StatDesc
.emptyS
THEN Sy
.AppendStmt(block
.sequ
,first
) END;
1288 IF block
= NIL THEN RETURN first
ELSE RETURN block
END;
1289 END statementSequence
;
1291 (* ==================================================================== *)
1293 PROCEDURE element(defScp
: Sy
.Scope
) : Sy
.Expr
;
1298 rslt
:= expression(defScp
);
1299 IF nextT
.sym
= T
.pointpointSym
THEN (* a range *)
1301 xTop
:= expression(defScp
);
1302 rslt
:= Xp
.newBinaryT(Xp
.range
, rslt
, xTop
, dTok
);;
1307 (* ==================================================================== *)
1309 PROCEDURE set(defScp
: Sy
.Scope
) : Sy
.Expr
;
1310 VAR rslt
: Xp
.SetExp
;
1312 Expect(T
.lbraceSym
);
1313 rslt
:= Xp
.mkEmptySet();
1314 IF in(symSet
[3], nextT
.sym
) THEN
1315 Sy
.AppendExpr(rslt
.varSeq
, element(defScp
));
1316 WHILE nextT
.sym
= T
.commaSym
DO
1318 Sy
.AppendExpr(rslt
.varSeq
, element(defScp
));
1321 Expect(T
.rbraceSym
);
1325 (* ==================================================================== *)
1327 PROCEDURE mulOperator() : INTEGER;
1330 IF (nextT
.sym
= T
.starSym
) THEN
1333 ELSIF (nextT
.sym
= T
.slashSym
) THEN
1336 ELSIF (nextT
.sym
= T
.DIVSym
) THEN
1339 ELSIF (nextT
.sym
= T
.MODSym
) THEN
1342 ELSIF (nextT
.sym
= T
.andSym
) THEN
1345 ELSIF (nextT
.sym
= T
.DIV0Sym
) THEN
1348 ELSIF (nextT
.sym
= T
.REM0Sym
) THEN
1352 Error(83); oSyn
:= T
.starSym
;
1357 (* ==================================================================== *)
1359 PROCEDURE factor(scope
: Sy
.Scope
) : Sy
.Expr
;
1370 xSyn
:= expression(scope
);
1371 Expect(T
.rparenSym
);
1374 xSyn
:= Xp
.mkNumLt(S
.tokToLong(token
));
1377 xSyn
:= Xp
.mkRealLt(S
.tokToReal(token
));
1378 | T
.CharConstantSym
:
1380 xSyn
:= Xp
.mkCharLt(S
.tokToChar(token
));
1383 xSyn
:= Xp
.tokToStrLt(token
.pos
, token
.len
);
1386 xSyn
:= Xp
.translateStrLt(token
.pos
, token
.len
);
1389 xSyn
:= Xp
.mkNilX();
1391 xSyn
:= designator(scope
);
1392 ConvertOverloaded(xSyn
);
1393 IF (xSyn
# NIL) & (xSyn
.kind
= Xp
.prCall
) THEN
1394 SemError(24); (* use of proper proc as function *)
1398 xSyn
:= factor(scope
);
1399 xSyn
:= Xp
.newUnaryX(Xp
.blNot
, xSyn
);
1401 Error(84); xSyn
:= NIL;
1406 (* ==================================================================== *)
1408 PROCEDURE addOperator() : INTEGER;
1411 IF (nextT
.sym
= T
.plusSym
) THEN
1414 ELSIF (nextT
.sym
= T
.minusSym
) THEN
1417 ELSIF (nextT
.sym
= T
.ORSym
) THEN
1421 Error(85); oSyn
:= T
.plusSym
;
1426 (* ==================================================================== *)
1428 PROCEDURE term(scope
: Sy
.Scope
) : Sy
.Expr
;
1429 VAR xSyn1
: Sy
.Expr
;
1434 xSyn1
:= factor(scope
);
1435 WHILE (nextT
.sym
= T
.starSym
) OR
1436 (nextT
.sym
= T
.slashSym
) OR
1437 (nextT
.sym
= T
.DIVSym
) OR
1438 (nextT
.sym
= T
.MODSym
) OR
1439 (nextT
.sym
= T
.DIV0Sym
) OR
1440 (nextT
.sym
= T
.REM0Sym
) OR
1441 (nextT
.sym
= T
.andSym
) DO
1442 mulOp
:= mulOperator(); saveT
:= token
;
1443 xSyn2
:= factor(scope
);
1444 xSyn1
:= Xp
.newBinaryT(mulOp
, xSyn1
, xSyn2
, saveT
);
1449 (* ==================================================================== *)
1451 PROCEDURE relation() : INTEGER;
1456 Get
; oSyn
:= Xp
.equal
;
1458 Get
; oSyn
:= Xp
.notEq
;
1460 Get
; oSyn
:= Xp
.lessT
;
1462 Get
; oSyn
:= Xp
.lessEq
;
1464 Get
; oSyn
:= Xp
.greT
;
1465 | T
.greaterequalSym
:
1466 Get
; oSyn
:= Xp
.greEq
;
1468 Get
; oSyn
:= Xp
.inOp
;
1470 Get
; oSyn
:= Xp
.isOp
;
1472 Error(86); oSyn
:= Xp
.equal
;
1477 (* ==================================================================== *)
1479 PROCEDURE simpleExpression(scope
: Sy
.Scope
) : Sy
.Expr
;
1480 VAR opNeg
: BOOLEAN;
1487 IF nextT
.sym
= T
.minusSym
THEN
1489 ELSIF nextT
.sym
= T
.plusSym
THEN
1492 term1
:= term(scope
);
1493 IF opNeg
THEN term1
:= Xp
.newUnaryX(Xp
.neg
, term1
) END;
1494 WHILE (nextT
.sym
= T
.minusSym
) OR
1495 (nextT
.sym
= T
.plusSym
) OR
1496 (nextT
.sym
= T
.ORSym
) DO
1497 addOp
:= addOperator(); saveT
:= token
;
1498 term2
:= term(scope
);
1499 term1
:= Xp
.newBinaryT(addOp
, term1
, term2
, saveT
);
1502 END simpleExpression
;
1504 (* ==================================================================== *)
1506 PROCEDURE OptExprList(VAR xList
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
1508 IF in(symSet
[3], nextT
.sym
) THEN
1509 ExprList(xList
, inhScp
);
1510 ELSE (* empty list *)
1515 (* ==================================================================== *)
1517 PROCEDURE ExprList(VAR xList
: Sy
.ExprSeq
; inhScp
: Sy
.Scope
);
1520 * To avoid aliassing, ALWAYS Discard old sequence.
1522 Sy
.InitExprSeq(xList
, 4);
1523 Sy
.AppendExpr(xList
, expression(inhScp
));
1524 WHILE (nextT
.sym
= T
.commaSym
) DO
1526 Sy
.AppendExpr(xList
, expression(inhScp
));
1530 (* ==================================================================== *)
1532 PROCEDURE findMatchingProcs(oId
: Id
.OvlId
;
1533 actuals
: Sy
.ExprSeq
;
1534 VAR rslt
: Id
.PrcSeq
);
1537 visited
: Id
.PrcSeq
;
1540 prcTy
: Ty
.Procedure
;
1543 PROCEDURE seen(newP
: Ty
.Procedure
; visited
: Id
.PrcSeq
) : BOOLEAN;
1547 FOR index
:= 0 TO visited
.tide
-1 DO
1548 IF newP
.sigsMatch(visited
.a
[index
].type
) THEN RETURN TRUE
; END;
1554 Id
.InitPrcSeq(rslt
,1);
1555 Id
.InitPrcSeq(visited
,5);
1556 rec
:= oId
.rec(Ty
.Record
);
1558 finished
:= id
= NIL;
1559 WHILE ~finished
& (id
# NIL) DO
1560 WITH id
: Id
.OvlId
DO
1561 FOR index
:= 0 TO id
.list
.tide
-1 DO
1562 prcTy
:= id
.list
.a
[index
].type(Ty
.Procedure
);
1563 IF Xp
.MatchPars(prcTy
.formals
,actuals
) & ~
seen(prcTy
,rslt
) THEN
1564 Id
.AppendProc(rslt
,id
.list
.a
[index
]);
1568 prcTy
:= id
.type(Ty
.Procedure
);
1569 IF Xp
.MatchPars(prcTy
.formals
,actuals
) & ~
seen(prcTy
,rslt
) THEN
1570 Id
.AppendProc(rslt
,id
);
1576 IF (rec
.baseTp
= NIL) OR (rec
.baseTp
= Ty
.anyRecTp
) THEN
1579 rec
:= rec
.baseTp
.boundRecTp()(Ty
.Record
);
1580 id
:= rec
.symTb
.lookup(oId
.hash
);
1583 END findMatchingProcs
;
1585 PROCEDURE FindBestMatch(IN actuals
: Sy
.ExprSeq
; IN procs
: Id
.PrcSeq
;
1586 OUT match
: BOOLEAN; OUT ix
: INTEGER);
1590 PROCEDURE IsSameAs(lhs
: Sy
.Type
; rhs
: Sy
.Type
) : BOOLEAN;
1592 IF lhs
= rhs
THEN RETURN TRUE
;
1593 ELSE RETURN lhs
.equalType(rhs
);
1597 PROCEDURE IsSameWithNativeCoercions(lhs
: Sy
.Type
; rhs
: Sy
.Type
) : BOOLEAN;
1599 IF lhs
= rhs
THEN RETURN TRUE
;
1600 ELSIF lhs
.isStringType() & rhs
.isStringType() THEN RETURN TRUE
;
1601 ELSIF lhs
.isNativeObj() & rhs
.isNativeObj() THEN RETURN TRUE
;
1602 ELSE RETURN lhs
.equalType(rhs
);
1604 END IsSameWithNativeCoercions
;
1611 WHILE ~match
& (ix
< procs
.tide
) DO
1612 pIx
:= 0; match
:= TRUE
;
1613 WHILE match
& (pIx
< actuals
.tide
) DO
1614 pTy
:= procs
.a
[ix
].type(Ty
.Procedure
);
1615 match
:= IsSameAs(actuals
.a
[pIx
].type
, pTy
.formals
.a
[pIx
].type
);
1618 IF ~match
THEN INC(ix
) ELSE RETURN END;
1621 WHILE ~match
& (ix
< procs
.tide
) DO
1622 pIx
:= 0; match
:= TRUE
;
1623 WHILE match
& (pIx
< actuals
.tide
) DO
1624 pTy
:= procs
.a
[ix
].type(Ty
.Procedure
);
1625 match
:= IsSameWithNativeCoercions(actuals
.a
[pIx
].type
, pTy
.formals
.a
[pIx
].type
);
1628 IF ~match
THEN INC(ix
) END;
1630 IF ~match
THEN ix
:= 0 END;
1633 (* ==================================================================== *)
1635 PROCEDURE makeCall(xCr
: Sy
.Expr
;
1636 IN actuals
: Sy
.ExprSeq
;
1637 inhScp
: Sy
.Scope
) : Sy
.Expr
;
1640 moreThanOne
, found
: BOOLEAN;
1642 prcTy
: Ty
.Procedure
;
1643 index
, pIx
, err
: INTEGER;
1644 nam
: LitValue
.CharOpen
;
1646 (* ------------------------- *)
1648 PROCEDURE RepMulErr(eNo
: INTEGER;
1649 pNam
: LitValue
.CharOpen
;
1650 frmSeq
: Id
.ParSeq
);
1655 cSeq
: LitValue
.CharOpenSeq
;
1658 LitValue
.InitCharOpenSeq(cSeq
,3);
1659 LitValue
.AppendCharOpen(cSeq
,pNam
);
1660 LitValue
.AppendCharOpen(cSeq
,LitValue
.strToCharOpen("("));
1661 len
:= frmSeq
.tide
- 1;
1662 FOR ix
:= 0 TO len
DO
1663 par
:= frmSeq
.a
[ix
];
1664 LitValue
.AppendCharOpen(cSeq
,par
.type
.name());
1665 IF ix
< len
THEN LitValue
.AppendCharOpen(cSeq
,comma
) END;
1667 LitValue
.AppendCharOpen(cSeq
,LitValue
.strToCharOpen(")"));
1668 S
.SemError
.RepSt1(eNo
, LitValue
.arrayCat(cSeq
)^
, token
.lin
, 0);
1671 (* ------------------------- *)
1673 PROCEDURE CheckSuper(xIn
: Xp
.IdentX
);
1674 VAR fld
: Sy
.Idnt
; (* Selector identifier *)
1675 sId
: Sy
.Idnt
; (* Super method ident *)
1676 mth
: Id
.MthId
; (* Method identifier *)
1677 rcT
: Ty
.Record
; (* Method bound recType *)
1685 IF (fld
.kind
# Id
.conMth
) & (fld
.kind
# Id
.fwdMth
) THEN
1686 SemError(119); (* super call invalid *)
1687 ELSE (* OK, fld is a method *)
1688 (* Find the receiver type, and check in scope of base type. *)
1689 mth
:= fld(Id
.MthId
);
1690 rcT
:= mth
.bndType(Ty
.Record
);
1692 (rcT
.baseTp
# NIL) &
1693 (rcT
.baseTp
.kind
= Ty
.recTp
) THEN
1695 * Bind to the overridden method, not necessarily
1696 * defined in the immediate supertype.
1698 sId
:= rcT
.baseTp(Ty
.Record
).bindField(fld
.hash
);
1700 * Inherited method could be overloaded
1701 * Find single sId that matches mth
1703 IF (sId
# NIL) & (sId
IS Id
.OvlId
) THEN
1704 sId
:= sId(Id
.OvlId
).findProc(mth
);
1714 * Now check various semantic constraints
1716 IF (sId
# NIL) & (sId
IS Id
.MthId
) THEN
1717 IF sId(Id
.MthId
).mthAtt
* Id
.mask
# Id
.extns
THEN
1718 SemError(118); (* call empty or abstract *)
1721 xIn
.type
:= sId
.type
;
1724 SemError(120); (* unknown super method *)
1727 SemError(120); (* unknown super method *)
1732 (* ------------------------- *)
1734 moreThanOne
:= FALSE
;
1735 IF (xCr
= NIL) OR (xCr
.type
= NIL) OR (xCr
IS Xp
.CallX
) THEN
1739 IF xCr
.type
.kind
= Ty
.ovlTp
THEN
1740 oId
:= xCr
.type
.idnt(Id
.OvlId
);
1741 nam
:= Sy
.getName
.ChPtr(oId
);
1742 Xp
.AttributePars(actuals
);
1743 findMatchingProcs(oId
,actuals
,procs
);
1744 IF procs
.tide
= 0 THEN
1747 ELSIF procs
.tide
> 1 THEN
1748 FindBestMatch(actuals
,procs
,found
,pIx
);
1749 IF ~found
THEN err
:= 220 ELSE err
:= 312 END;
1750 FOR index
:= 0 TO procs
.tide
-1 DO
1751 IF ~
(found
& (index
= pIx
)) THEN (* just for info *)
1752 RepMulErr(err
,nam
,procs
.a
[index
].type(Ty
.Procedure
).formals
);
1756 RepMulErr(313,nam
,procs
.a
[pIx
].type(Ty
.Procedure
).formals
);
1763 WITH xCr
: Xp
.IdLeaf
DO
1764 xCr
.ident
:= procs
.a
[pIx
];
1765 xCr
.type
:= xCr
.ident
.type
;
1766 | xCr
: Xp
.IdentX
DO
1767 xCr
.ident
:= procs
.a
[pIx
];
1768 xCr
.type
:= xCr
.ident
.type
;
1772 * Overloading (if any) is by now resolved.
1773 * Now check for super calls. See if
1774 * we can find a match for xCr.ident
1775 * in the supertype of
1776 * - xCr.kid.ident(Id.MthId).bndType
1778 IF xCr
.kind
= Xp
.sprMrk
THEN
1779 CheckSuper(xCr(Xp
.IdentX
));
1782 * Now create CallX node in tree.
1784 IF (xCr
.type
.kind
# Ty
.prcTp
) &
1785 (xCr
.type
.kind
# Ty
.evtTp
) THEN
1786 xCr
.ExprError(224); RETURN NIL;
1787 ELSIF xCr
.type
.isProperProcType() THEN
1788 xCr
:= Xp
.newCallX(Xp
.prCall
, actuals
, xCr
);
1789 xCr
.NoteCall(inhScp
); (* note "inhScp" calls "eSyn.kid" *)
1791 xCr
:= Xp
.newCallX(Xp
.fnCall
, actuals
, xCr
);
1792 xCr
:= Xp
.checkCall(xCr(Xp
.CallX
));
1794 xCr
.NoteCall(inhScp
); (* note "inhScp" calls "eSyn.kid" *)
1795 IF (xCr
IS Xp
.CallX
) & (xCr(Xp
.CallX
).kid
.kind
= Xp
.sprMrk
) THEN
1796 Xp
.CheckSuper(xCr(Xp
.CallX
), inhScp
);
1803 (* ------------------------- *)
1805 PROCEDURE findFieldId(id
: Id
.OvlId
) : Sy
.Idnt
;
1811 IF id
= NIL THEN RETURN NIL END;
1813 rec
:= id
.rec(Ty
.Record
);
1814 WHILE (fId
= NIL) & (rec
.baseTp
# NIL) & (rec
.baseTp
IS Ty
.Record
) DO
1815 rec
:= rec
.baseTp(Ty
.Record
);
1816 ident
:= rec
.symTb
.lookup(id
.hash
);
1817 IF ident
IS Id
.OvlId
THEN
1818 fId
:= ident(Id
.OvlId
).fld
;
1819 ELSIF (ident
.kind
= Id
.fldId
) OR (ident
.kind
= Id
.varId
) OR
1820 (ident
.kind
= Id
.conId
) THEN
1827 (* ------------------------- *)
1829 PROCEDURE FindOvlField(e
: Sy
.Expr
);
1831 ASSERT(e
.type
.kind
= Ty
.ovlTp
);
1832 WITH e
: Xp
.IdentX
DO
1833 e
.ident
:= findFieldId(e
.ident(Id
.OvlId
));
1834 IF e
.ident
= NIL THEN
1837 e
.type
:= e
.ident
.type
;
1840 e
.ident
:= findFieldId(e
.ident(Id
.OvlId
));
1841 IF e
.ident
= NIL THEN
1844 e
.type
:= e
.ident
.type
;
1849 (* ------------------------- *)
1851 PROCEDURE ConvertOverloaded(VAR e
: Sy
.Expr
);
1853 IF (e
# NIL) & (e
.type
IS Ty
.Overloaded
) THEN
1855 * WITH e : Xp.IdentX DO
1856 * e.ident := e.ident(Id.OvlId).fld;
1857 * IF (e.ident = NIL) THEN
1858 * SemErrorT(9, e.token);
1860 * e.type := e.ident.type;
1864 WITH e
: Xp
.IdentX
DO
1865 e
.ident
:= e
.ident(Id
.OvlId
).fld
;
1866 IF (e
.ident
= NIL) THEN
1867 SemErrorT(9, e
.token
);
1869 e
.type
:= e
.ident
.type
;
1872 e
.ident
:= e
.ident(Id
.OvlId
).fld
;
1873 IF (e
.ident
= NIL) THEN
1874 SemErrorT(9, e
.token
);
1876 e
.type
:= e
.ident
.type
;
1880 END ConvertOverloaded
;
1882 (* ==================================================================== *)
1884 PROCEDURE MethAttributes(pDesc
: Id
.Procs
);
1887 (* ------------------------- *)
1888 PROCEDURE CheckBasecall(proc
: Id
.Procs
);
1900 rec
:= proc
.type
.returnType();
1901 IF rec
# NIL THEN rec
:= rec
.boundRecTp(); bRc
:= rec(Ty
.Record
) END;
1902 IF rec
# NIL THEN rec
:= rec(Ty
.Record
).baseTp
END;
1903 IF rec
# NIL THEN rec
:= rec
.boundRecTp() END;
1905 * Compute the apparent type of each actual.
1907 FOR idx
:= 0 TO bas
.actuals
.tide
- 1 DO
1908 bas
.actuals
.a
[idx
] := bas
.actuals
.a
[idx
].exprAttr();
1911 * Now try to find matching super-ctor.
1912 * IF there are not actuals, then assume the existence of
1913 * a noarg constructor. TypeDesc.okToList will check this!
1915 IF bas
.actuals
.tide
# 0 THEN
1916 WITH rec
: Ty
.Record
DO
1917 FOR idx
:= 0 TO rec
.statics
.tide
- 1 DO
1918 sId
:= rec
.statics
.a
[idx
];
1920 * If this is a .ctor, then try to match arguments ...
1922 IF sId
.kind
= Id
.ctorP
THEN
1923 sTp
:= sId
.type(Ty
.Procedure
);
1924 IF Xp
.MatchPars(sTp
.formals
, bas
.actuals
) THEN
1925 Id
.AppendProc(seq
, sId(Id
.Procs
));
1931 Id
.AppendProc(seq
, NIL);
1933 IF seq
.tide
= 0 THEN SemError(202);
1934 ELSIF seq
.tide
= 1 THEN bas
.sprCtor
:= seq
.a
[0];
1936 FindBestMatch(bas
.actuals
, seq
, mOk
, idx
);
1937 IF mOk
THEN bas
.sprCtor
:= seq
.a
[idx
] ELSE SemError(147) END;
1940 Sy
.AppendIdnt(bRc
.statics
, proc
);
1942 * And, while we are at it, if this is a no-arg
1943 * constructor, suppress emission of the default.
1945 IF proc
.locals
.tide
= 1 THEN INCL(bRc
.xAttr
, Sy
.xCtor
) END;
1948 (* ------------------------- *)
1949 PROCEDURE DummyParameters(VAR seq
: Sy
.ExprSeq
; prT
: Ty
.Procedure
);
1953 FOR idx
:= 0 TO prT
.formals
.tide
- 1 DO
1954 idl
:= Xp
.mkIdLeaf(prT
.formals
.a
[idx
]);
1955 idl
.type
:= idl
.ident
.type
;
1956 Sy
.AppendExpr(seq
, idl
);
1958 END DummyParameters
;
1959 (* ------------------------- *)
1960 PROCEDURE InsertSelf(prc
: Id
.Procs
);
1965 par
:= Id
.newParId();
1966 par
.hash
:= Bi
.selfBk
;
1968 par
.parMod
:= Sy
.in
; (* so it is read only *)
1969 par
.varOrd
:= 0; (* both .NET and JVM *)
1970 par
.type
:= prc
.type
.returnType();
1971 ASSERT(prc
.symTb
.enter(par
.hash
, par
));
1973 * Now adjust the locals sequence.
1975 Sy
.AppendIdnt(tmp
, par
);
1976 FOR idx
:= 0 TO prc
.locals
.tide
-1 DO
1977 Sy
.AppendIdnt(tmp
, prc
.locals
.a
[idx
]);
1978 prc
.locals
.a
[idx
](Id
.AbVar
).varOrd
:= idx
+1;
1982 (* ------------------------- *)
1985 IF nextT
.sym
= T
.NEWSym
THEN
1988 IF nextT
.sym
= T
.commaSym
THEN Get
; mAtt
:= otherAtts(mAtt
) END;
1989 ELSIF nextT
.sym
= T
.identSym
THEN
1990 hash
:= NameHash
.enterSubStr(nextT
.pos
, nextT
.len
);
1991 IF (hash
= Bi
.constB
) OR (hash
= Bi
.basBkt
) THEN
1993 IF Cs
.strict
THEN SemError(221); END;
1995 IF hash
= Bi
.basBkt
THEN
1996 pDesc
.basCll
.empty
:= FALSE
;
1997 ActualParameters(pDesc
.basCll
.actuals
, pDesc
);
1999 * Insert the arg0 identifier "SELF"
2003 pDesc
.basCll
.empty
:= TRUE
;
2004 DummyParameters(pDesc
.basCll
.actuals
, pDesc
.type(Ty
.Procedure
));
2006 CheckBasecall(pDesc
);
2007 pDesc
.SetKind(Id
.ctorP
);
2009 ELSIF (nextT
.sym
= T
.ABSTRACTSym
) OR
2010 (nextT
.sym
= T
.EXTENSIBLESym
) OR
2011 (nextT
.sym
= T
.EMPTYSym
) THEN
2012 mAtt
:= otherAtts({});
2016 IF pDesc
IS Id
.MthId
THEN
2017 pDesc(Id
.MthId
).mthAtt
:= mAtt
;
2018 IF pDesc
.kind
= Id
.ctorP
THEN SemError(146) END;
2019 ELSIF pDesc
.kind
# Id
.ctorP
THEN
2024 (* ==================================================================== *)
2026 PROCEDURE getTypeAssertId(lst
: Sy
.ExprSeq
) : Sy
.Idnt
;
2030 IF (lst
.tide
= 1) & (lst
.a
[0] IS Xp
.IdLeaf
) THEN
2031 lf
:= lst
.a
[0](Xp
.IdLeaf
);
2032 IF lf
.ident
IS Id
.TypId
THEN RETURN lf
.ident
; END;
2035 END getTypeAssertId
;
2037 (* ==================================================================== *)
2039 PROCEDURE designator(inhScp
: Sy
.Scope
) : Sy
.Expr
;
2040 VAR eSyn
: Sy
.Expr
; (* the synthesized expression attribute *)
2041 qual
: Sy
.Idnt
; (* the base qualident of the designator *)
2042 iLst
: Sy
.ExprSeq
; (* a list of array index expressions *)
2046 (* ------------------------- *)
2048 PROCEDURE implicitDerefOf(wrkX
: Sy
.Expr
) : Sy
.Expr
;
2049 (* Make derefs explicit, returning NIL if invalid pointer type. *)
2055 (wrkX
.type
# NIL) THEN
2057 WITH wrkT
: Ty
.Pointer
DO
2058 bndT
:= wrkT
.boundTp
;
2059 IF bndT
= NIL THEN RETURN NIL END;
2061 wrkX
:= Xp
.newUnaryX(Xp
.deref
, wrkX
);
2062 wrkX
.token
:= save
; (* point to the same token *)
2063 wrkX
.type
:= bndT
; (* type is bound type of ptr. *)
2065 IF wrkT
= Ty
.anyPtrTp
THEN
2067 wrkX
:= Xp
.newUnaryX(Xp
.deref
, wrkX
);
2069 wrkX
.type
:= Ty
.anyRecTp
;
2071 | wrkT
: Ty
.Event
DO
2072 wrkX
.type
:= wrkT
.bndRec
;
2077 END implicitDerefOf
;
2079 (* ------------------------- *)
2081 PROCEDURE checkRecord(xIn
: Sy
.Expr
; (* referencing expression *)
2082 tok
: S
.Token
; (* field/procedure ident *)
2083 scp
: Sy
.Scope
; (* current scope of ref. *)
2084 tId
: BOOLEAN) : Sy
.Expr
; (* left context is tp *)
2085 VAR fId
: Sy
.Idnt
; (* the field identifier desc. *)
2087 (* ------------------------- *)
2088 PROCEDURE Rep162(f
: Sy
.Idnt
);
2089 BEGIN SemErrorS1(162, Sy
.getName
.ChPtr(f
)) END Rep162
;
2090 (* ------------------------- *)
2091 BEGIN (* quit at first trouble sign *)
2092 ConvertOverloaded(xIn
);
2093 xNw
:= implicitDerefOf(xIn
);
2094 IF (xNw
= NIL) OR (xNw
.type
= NIL) THEN RETURN NIL END;
2095 IF (xNw
.type
.kind
# Ty
.recTp
) &
2096 (xNw
.type
.kind
# Ty
.enuTp
) THEN SemError(8); RETURN NIL END;
2097 fId
:= bindFieldToken(xNw
.type
, tok
);
2099 SemErrorS1(9, xIn
.type
.name()); RETURN NIL;
2101 IF tId
THEN (* fId must be a foreign, static feature! *)
2102 IF fId
IS Id
.FldId
THEN SemError(196) END;
2103 IF fId
IS Id
.MthId
THEN SemError(197) END;
2104 xNw
:= Xp
.mkIdLeaf(fId
);
2106 WITH fId
: Id
.VarId
DO SemError(198);
2107 | fId
: Id
.PrcId
DO SemError(199);
2109 IF fId
.callForbidden() THEN SemErrorT(127, tok
) END;
2111 * IF (fId.vMod = Sy.rdoMode) &
2112 * xNw.type.isImportedType() THEN SemErrorT(127, tok) END;
2117 xNw
:= Xp
.newIdentX(Xp
.selct
, fId
, xNw
);
2119 IF fId
.vMod
= Sy
.protect
THEN
2121 * If fId is a protected feature (and hence
2122 * foreign) then the context must be a method
2123 * body. Furthermore, the method scope must
2124 * be derived from the field's defining scope.
2126 WITH scp
: Id
.MthId
DO
2127 IF ~xIn
.type
.isBaseOf(scp
.rcvFrm
.type
) THEN Rep162(fId
) END;
2132 IF (fId
.type
# NIL) &
2133 (fId
.type
IS Ty
.Opaque
) THEN
2134 (* ------------------------------------------- *
2135 * Permanently fix the field type attribute.
2136 * ------------------------------------------- *)
2137 fId
.type
:= fId
.type
.elaboration();
2139 xNw
.type
:= fId
.type
;
2144 (* ------------------------- *)
2146 PROCEDURE checkArray(xCr
: Sy
.Expr
; IN seq
: Sy
.ExprSeq
) : Sy
.Expr
;
2147 VAR xTp
: Sy
.Type
; (* type of current expr xCr *)
2148 aTp
: Ty
.Array
; (* current array type of expr *)
2149 iCr
: Sy
.Expr
; (* the current index expression *)
2150 idx
: INTEGER; (* index into expr. sequence *)
2152 BEGIN (* quit at first trouble sign *)
2153 ConvertOverloaded(xCr
);
2155 FOR idx
:= 0 TO seq
.tide
-1 DO
2156 xCr
:= implicitDerefOf(xCr
);
2157 IF xCr
# NIL THEN xTp
:= xCr
.type
ELSE RETURN NIL END;
2159 * IF xTp.kind # Ty.arrTp THEN
2160 * IF idx = 0 THEN xCr.ExprError(10) ELSE xCr.ExprError(11) END;
2163 * aTp := xTp(Ty.Array);
2166 WITH xTp
: Ty
.Array
DO
2167 aTp
:= xTp(Ty
.Array
);
2169 IF idx
= 0 THEN xCr
.ExprError(10) ELSE xCr
.ExprError(11) END;
2175 IF iCr
# NIL THEN iCr
:= iCr
.exprAttr() END;
2176 IF iCr
# NIL THEN (* check is integertype , literal in range *)
2177 IF ~iCr
.isIntExpr() THEN iCr
.ExprError(31) END;
2178 IF iCr
.type
= Bi
.lIntTp
THEN
2179 iCr
:= Xp
.newIdentX(Xp
.cvrtDn
, Bi
.intTp
.idnt
, iCr
);
2181 IF iCr
.isNumLit() & ~iCr
.inRangeOf(aTp
) THEN iCr
.ExprError(32) END;
2184 xCr
:= Xp
.newBinaryT(Xp
.index
, xCr
, iCr
, tok
);
2185 IF xTp
# NIL THEN xCr
.type
:= xTp
ELSE RETURN NIL END;
2190 (* ------------------------- *)
2192 PROCEDURE checkTypeAssert(xpIn
: Sy
.Expr
; tpId
: Sy
.Idnt
) : Sy
.Expr
;
2196 IF xpIn
.type
.kind
= Ty
.ovlTp
THEN FindOvlField(xpIn
); END;
2197 IF (xpIn
= NIL) OR (tpId
= NIL) OR (tpId
.type
= NIL) THEN RETURN NIL END;
2199 recT
:= dstT
.boundRecTp()(Ty
.Record
);
2200 (* Check #1 : qualident must be a [possibly ptr to] record type *)
2201 IF recT
= NIL THEN SemError(18); RETURN NIL END;
2202 (* Check #2 : Check that the expression has some dynamic type *)
2203 IF ~xpIn
.hasDynamicType() THEN xpIn
.ExprError(17); RETURN NIL END;
2204 IF dstT
.kind
= Ty
.recTp
THEN xpIn
:= implicitDerefOf(xpIn
) END;
2205 (* Check #3 : Check that manifest type is a base of asserted type *)
2207 IF ~xpIn
.type
.isBaseOf(dstT
) &
2208 ~xpIn
.type
.isInterfaceType() &
2209 ~dstT
.isInterfaceType() &
2210 ~
(dstT
.isCompoundType() & recT
.compoundCompat(xpIn
.type
) ) &
2211 ~dstT
.isEventType() THEN SemError(15); RETURN NIL END;
2214 IF ~xpIn
.type
.isBaseOf(dstT
) &
2215 ~xpIn
.type
.isInterfaceType() &
2216 ~dstT
.isInterfaceType() &
2217 ~dstT
.isEventType() &
2218 ~Ty
.isBoxedStruct(xpIn
.type
, dstT
) THEN SemError(15); RETURN NIL END;
2219 END; (* IF Cs.extras *)
2220 (* Geez, it seems to be ok! *)
2221 xpIn
:= Xp
.newUnaryX(Xp
.tCheck
, xpIn
);
2224 END checkTypeAssert
;
2226 (* ------------------------- *)
2228 PROCEDURE mkSuperCall(xIn
: Sy
.Expr
) : Sy
.Expr
;
2232 WITH xIn
: Xp
.IdentX
DO
2233 new
:= Xp
.newIdentX(Xp
.sprMrk
, xIn
.ident
, xIn
.kid
);
2234 new
.type
:= xIn
.ident
.type
;
2236 SemError(119); (* super call invalid *)
2241 (* ------------------------- *)
2243 PROCEDURE stringifier(xIn
: Sy
.Expr
) : Sy
.Expr
;
2245 xIn
:= implicitDerefOf(xIn
);
2246 IF xIn
.isCharArray() THEN
2247 xIn
:= Xp
.newUnaryX(Xp
.mkStr
, xIn
);
2248 xIn
.type
:= Bi
.strTp
;
2250 SemError(41); RETURN NIL;
2255 (* ------------------------- *)
2257 PROCEDURE explicitDerefOf(wrkX
: Sy
.Expr
) : Sy
.Expr
;
2258 (* Make derefs explicit, returning NIL if invalid pointer type. *)
2259 VAR expT
, bndT
: Sy
.Type
;
2262 WITH expT
: Ty
.Pointer
DO
2263 bndT
:= expT
.boundTp
;
2264 IF bndT
= NIL THEN RETURN NIL END;
2265 wrkX
:= Xp
.newUnaryX(Xp
.deref
, wrkX
);
2266 wrkX
.type
:= bndT
; (* type is bound type of ptr. *)
2268 IF expT
= Ty
.anyPtrTp
THEN
2269 wrkX
:= Xp
.newUnaryX(Xp
.deref
, wrkX
);
2270 wrkX
.type
:= Ty
.anyRecTp
; (* type is bound type of ptr. *)
2272 SemError(12); RETURN NIL; (* expr. not a pointer type *)
2274 | expT
: Ty
.Overloaded
DO RETURN mkSuperCall(wrkX
);
2275 | expT
: Ty
.Procedure
DO RETURN mkSuperCall(wrkX
);
2277 * | expT : Ty.Procedure DO
2278 * RETURN checkSuperCall(wrkX);
2281 SemError(12); RETURN NIL; (* expr. not a pointer type *)
2284 END explicitDerefOf
;
2286 (* ------------------------- *)
2288 PROCEDURE ReportIfOpaque(exp
: Sy
.Expr
);
2292 (exp
.type
.kind
= Ty
.namTp
) &
2293 (exp
.type
.idnt
# NIL) &
2294 (exp
.type
.idnt
.dfScp
# NIL) &
2295 exp
.type
.idnt
.dfScp
.isWeak() THEN
2296 SemErrorS1(176, Sy
.getName
.ChPtr(exp
.type
.idnt
.dfScp
));
2300 (* ------------------------- *)
2302 BEGIN (* body of designator *)
2303 (* --------------------------------------------------------- *
2304 * First deal with the qualified identifier part. *
2305 * --------------------------------------------------------- *)
2306 qual
:= qualident(inhScp
);
2307 IF (qual
# NIL) & (qual
.type
# NIL) THEN
2308 eSyn
:= Xp
.mkIdLeaf(qual
);
2309 eSyn
.type
:= qual
.type
;
2310 isTp
:= qual
IS Id
.TypId
;
2315 (* --------------------------------------------------------- *
2316 * Now deal with each selector, in sequence, by a loop. *
2317 * It is an invariant of this loop, that if eSyn # NIL, *
2318 * the expression has a valid, non-NIL type value. *
2319 * --------------------------------------------------------- *)
2320 WHILE (nextT
.sym
= T
.pointSym
) OR
2321 (nextT
.sym
= T
.lparenSym
) OR
2322 (nextT
.sym
= T
.lbrackSym
) OR
2323 (nextT
.sym
= T
.uparrowSym
) OR
2324 (nextT
.sym
= T
.dollarSym
) DO
2325 (* ------------------------------------------------------- *
2326 * If this is an opaque, resolve it if possible
2327 * ------------------------------------------------------- *)
2328 IF (eSyn
# NIL) & (eSyn
.type
IS Ty
.Opaque
) THEN
2329 eSyn
.type
:= eSyn
.type
.elaboration();
2330 IF eSyn
.type
IS Ty
.Opaque
THEN ReportIfOpaque(eSyn
) END;
2332 (* ------------------------------------------------------- *
2333 * If expr is typeName, must be static feature selection
2334 * ------------------------------------------------------- *)
2337 (eSyn
IS Xp
.IdLeaf
) &
2338 (nextT
.sym
# T
.pointSym
) THEN eSyn
.ExprError(85) END;
2340 IF nextT
.sym
= T
.pointSym
THEN
2341 (* ------------------------------------------------------- *
2342 * This must be a field selection, or a method call
2343 * ------------------------------------------------------- *)
2346 (* Check that this is a valid record type. *)
2347 IF eSyn
# NIL THEN eSyn
:= checkRecord(eSyn
, token
, inhScp
, isTp
) END;
2348 isTp
:= FALSE
; (* clear the flag *)
2349 ELSIF (nextT
.sym
= T
.lbrackSym
) THEN
2350 (* ------------------------------------------------------- *
2351 * This must be a indexed selection on an array type
2352 * ------------------------------------------------------- *)
2354 ExprList(iLst
, inhScp
);
2355 Expect(T
.rbrackSym
);
2356 (* Check that this is a valid array type. *)
2357 IF eSyn
# NIL THEN eSyn
:= checkArray(eSyn
, iLst
) END;
2358 ELSIF (nextT
.sym
= T
.lparenSym
) THEN
2359 (* -------------------------------------------------------------- *
2360 * This could be a function/procedure call, or a type assertion *
2361 * -------------------------------------------------------------- *)
2363 OptExprList(iLst
, inhScp
);
2365 qual
:= getTypeAssertId(iLst
);
2366 IF (qual
# NIL) & ~eSyn
.isStdFunc() THEN
2368 * This must be a type test, so ...
2370 * This following test is inline in checkTypeAssert()
2371 * IF eSyn.type.kind = Ty.ovlTp THEN FindOvlField(eSyn); END;
2373 eSyn
:= checkTypeAssert(eSyn
,qual
);
2374 ELSIF (eSyn
.type
.kind
= Ty
.prcTp
) OR
2375 (eSyn
.type
.kind
= Ty
.ovlTp
) OR
2376 (eSyn
.type
.kind
= Ty
.evtTp
) THEN
2377 (* A (possibly overloaded) function/procedure call *)
2378 eSyn
:= makeCall(eSyn
, iLst
, inhScp
);
2379 ELSE (* A syntax error. *)
2384 Expect(T
.rparenSym
);
2385 IF (eSyn
# NIL) & (eSyn
.kind
= Xp
.prCall
) THEN RETURN eSyn
; END;
2386 (* Watch it! that was a semantically selected parser action. *)
2387 ELSIF (nextT
.sym
= T
.uparrowSym
) THEN
2388 (* ------------------------------------------------------- *
2389 * This can be an explicit dereference or a super call *
2390 * ------------------------------------------------------- *)
2392 IF eSyn
# NIL THEN eSyn
:= explicitDerefOf(eSyn
) END;
2394 (* ------------------------------------------------------- *
2395 * This can only be an explicit make-string operator
2396 * ------------------------------------------------------- *)
2398 IF eSyn
# NIL THEN eSyn
:= stringifier(eSyn
) END;
2399 (* ------------------------------------------------------- *)
2402 (* ------------------------------------------------------- *
2403 * Some special case cleanup code for enums, opaques...
2404 * ------------------------------------------------------- *)
2407 eSyn
.type
:= Bi
.metaTp
;
2408 ELSIF eSyn
.type
# NIL THEN
2410 WITH exTp
: Ty
.Enum
DO
2411 eSyn
.type
:= Bi
.intTp
;
2412 | exTp
: Ty
.Opaque
DO
2413 eSyn
.type
:= exTp
.elaboration();
2421 (* ==================================================================== *)
2423 PROCEDURE FixAnon(defScp
: Sy
.Scope
; tTyp
: Sy
.Type
; mode
: INTEGER);
2426 IF (tTyp
# NIL) & (tTyp
.idnt
= NIL) THEN
2427 iSyn
:= Id
.newAnonId(tTyp
.serial
);
2431 ASSERT(Cs
.thisMod
.symTb
.enter(iSyn
.hash
, iSyn
));
2435 (* ==================================================================== *)
2437 PROCEDURE VariableDeclaration(defScp
: Sy
.Scope
);
2438 VAR vSeq
: Sy
.IdSeq
; (* idents of the shared type *)
2439 tTyp
: Sy
.Type
; (* the shared variable type desc *)
2441 neId
: Sy
.Idnt
; (* temp to hold Symbols.Idnet *)
2442 vrId
: Id
.AbVar
; (* same temp, but cast to VarId *)
2443 mOut
: INTEGER; (* maximum visibility of idlist *)
2445 IdentDefList(vSeq
, defScp
, Id
.varId
);
2446 CheckVisibility(vSeq
, Sy
.pubMode
, mOut
); (* no errors! *)
2448 tTyp
:= type(defScp
, mOut
);
2449 IF mOut
# Sy
.prvMode
THEN FixAnon(defScp
, tTyp
, mOut
) END;
2451 * Expect(T.colonSym);
2452 * tTyp := type(defScp, Sy.prvMode); (* not sure about this? *)
2454 FOR indx
:= 0 TO vSeq
.tide
-1 DO
2455 (* this works around a bug in the JVM boot compiler (kjg 7.jan.00) *)
2456 neId
:= vSeq
.a
[indx
];
2457 vrId
:= neId(Id
.AbVar
);
2458 (* ------------------------- *)
2460 vrId
.varOrd
:= defScp
.locals
.tide
;
2461 IF Sy
.refused(vrId
, defScp
) THEN
2464 Sy
.AppendIdnt(defScp
.locals
, vrId
);
2467 END VariableDeclaration
;
2469 (* ==================================================================== *)
2471 PROCEDURE FormalParameters(thsP
: Ty
.Procedure
;
2474 VAR group
: Id
.ParSeq
;
2475 (* typId : Id.TypId; *)
2477 (* --------------------------- *)
2478 PROCEDURE EnterFPs(VAR grp
, seq
: Id
.ParSeq
; pSc
, sSc
: Sy
.Scope
);
2479 VAR index
: INTEGER;
2482 FOR index
:= 0 TO grp
.tide
-1 DO
2483 param
:= grp
.a
[index
];
2484 Id
.AppendParam(seq
, param
);
2486 IF Sy
.refused(param
, pSc
) THEN
2489 param
.varOrd
:= pSc
.locals
.tide
;
2491 Sy
.AppendIdnt(pSc
.locals
, param
);
2496 (* --------------------------- *)
2497 PROCEDURE isPrivate(t
: Sy
.Type
) : BOOLEAN;
2499 WITH t
: Ty
.Array
DO
2500 RETURN isPrivate(t
.elemTp
);
2502 RETURN ~
(t
IS Ty
.Base
) & (t
.idnt
.vMod
= Sy
.prvMode
);
2505 (* --------------------------- *)
2506 PROCEDURE CheckRetType(tst
: BOOLEAN; tok
: S
.Token
; typ
: Sy
.Type
);
2509 IF typ
= NIL THEN RETURN;
2510 ELSIF typ
.kind
= Ty
.recTp
THEN SemErrorT(78, tok
);
2511 ELSIF typ
.kind
= Ty
.arrTp
THEN SemErrorT(79, tok
);
2512 ELSIF typ
.idnt
# NIL THEN (* not anon *)
2513 IF tst
& isPrivate(typ
) THEN SemErrorT(151, tok
) END;
2514 ELSIF typ
.kind
= Ty
.ptrTp
THEN
2515 bndT
:= typ(Ty
.Pointer
).boundTp
;
2516 IF tst
& (bndT
# NIL) & isPrivate(bndT
) THEN SemErrorT(151, tok
) END;
2519 (* --------------------------- *)
2520 PROCEDURE ReturnType(typ
: Ty
.Procedure
; prc
: Id
.Procs
; scp
: Sy
.Scope
);
2525 Get
; (* read past colon symbol *)
2527 tpRt
:= type(scp
, Sy
.prvMode
);
2528 typ
.retType
:= tpRt
;
2529 test
:= ~Cs
.special
& (prc
# NIL) & (prc
.vMod
= Sy
.pubMode
);
2530 CheckRetType(test
, tokn
, tpRt
);
2532 (* --------------------------- *)
2534 Get
; (* read past lparenSym *)
2535 IF (nextT
.sym
= T
.identSym
) OR
2536 (nextT
.sym
= T
.INSym
) OR
2537 (nextT
.sym
= T
.VARSym
) OR
2538 (nextT
.sym
= T
.OUTSym
) THEN
2539 FPSection(group
, proc
, scpe
);
2540 EnterFPs(group
, thsP
.formals
, proc
, scpe
);
2542 WHILE weakSeparator(22, 10, 11) DO
2543 Id
.ResetParSeq(group
);
2544 FPSection(group
, proc
, scpe
);
2545 EnterFPs(group
, thsP
.formals
, proc
, scpe
);
2548 Expect(T
.rparenSym
);
2549 IF (nextT
.sym
= T
.colonSym
) THEN ReturnType(thsP
, proc
, scpe
) END;
2550 END FormalParameters
;
2552 (* ==================================================================== *)
2554 PROCEDURE CheckVisibility(seq
: Sy
.IdSeq
; in
: INTEGER; OUT out
: INTEGER);
2560 FOR ix
:= 0 TO seq
.tide
-1 DO
2564 | Sy
.prvMode
: IF md
# Sy
.prvMode
THEN id
.IdError(183) END;
2566 | Sy
.rdoMode
: IF md
= Sy
.pubMode
THEN id
.IdError(184) END;
2568 out
:= Sy
.maxMode(md
, out
);
2570 END CheckVisibility
;
2572 (* ==================================================================== *)
2574 PROCEDURE IdentDefList(OUT iSeq
: Sy
.IdSeq
;
2578 Sy
.AppendIdnt(iSeq
, identDef(scp
, kind
));
2579 WHILE (nextT
.sym
= T
.commaSym
) DO
2581 Sy
.AppendIdnt(iSeq
, identDef(scp
, kind
));
2585 (* ==================================================================== *)
2587 PROCEDURE FieldList(recT
: Ty
.Record
;
2590 VAR list
: Sy
.IdSeq
;
2596 IF nextT
.sym
= T
.identSym
THEN
2597 IdentDefList(list
, defScp
, Id
.fldId
);
2598 CheckVisibility(list
, vMod
, vOut
);
2600 fTyp
:= type(defScp
, vOut
);
2601 IF vOut
# Sy
.prvMode
THEN FixAnon(defScp
, fTyp
, vOut
) END;
2603 FOR fIdx
:= 0 TO list
.tide
-1 DO
2604 fDsc
:= list
.a
[fIdx
](Id
.FldId
);
2606 fDsc
.recTyp
:= recT
;
2607 Sy
.AppendIdnt(recT
.fields
, fDsc
);
2612 (* ==================================================================== *)
2614 PROCEDURE FieldListSequence(recT
: Ty
.Record
;
2617 VAR start
: INTEGER;
2622 start
:= recT
.fields
.tide
;
2623 FieldList(recT
, defScp
, vMod
);
2624 WHILE (nextT
.sym
= T
.semicolonSym
) DO
2626 FieldList(recT
, defScp
, vMod
);
2628 final
:= recT
.fields
.tide
;
2629 (* now insert into the fieldname scope *)
2630 FOR index
:= start
TO final
-1 DO
2631 ident
:= recT
.fields
.a
[index
];
2632 IF ~recT
.symTb
.enter(ident
.hash
, ident
) THEN ident
.IdError(6) END;
2634 END FieldListSequence
;
2636 (* ==================================================================== *)
2638 PROCEDURE StaticStuff(recT
: Ty
.Record
;
2640 vMod
: INTEGER); (* vMod ??? *)
2641 (* ----------------------------------------- *)
2642 PROCEDURE StaticProc(rec
: Ty
.Record
; scp
: Sy
.Scope
);
2643 VAR prcD
: Id
.Procs
;
2644 prcT
: Ty
.Procedure
;
2645 name
: LitValue
.CharOpen
;
2649 Get
; (* read past procedureSym *)
2650 prcD
:= identDef(scp
, Id
.conPrc
)(Id
.Procs
);
2651 prcD
.SetKind(Id
.conPrc
);
2652 prcD
.bndType
:= rec
;
2653 IF nextT
.sym
= T
.lbrackSym
THEN
2654 IF ~Cs
.special
THEN SemError(144) END;
2656 Expect(T
.stringSym
);
2657 name
:= LitValue
.subStrToCharOpen(token
.pos
+1, token
.len
-2);
2659 Expect(T
.rbrackSym
);
2660 IF Cs
.verbose
THEN Cs
.Message('external procName
"' + name^ + '"'
) END;
2662 prcT
:= Ty
.newPrcTp();
2664 IF prcD
.vMod
# Sy
.prvMode
THEN INCL(prcD
.pAttr
, Id
.public
) END;
2665 IF nextT
.sym
= T
.lparenSym
THEN
2666 FormalParameters(prcT
, prcD
, scp
);
2669 Ty
.InsertInRec(prcD
,rec
,FALSE
,oId
,ok
);
2671 Sy
.AppendIdnt(rec
.statics
, prcD
);
2673 * Put this header on the procedure list,
2674 * so that it gets various semantic checks.
2676 Id
.AppendProc(Cs
.thisMod
.procs
, prcD
);
2681 (* ----------------------------------------- *)
2682 PROCEDURE StaticConst(lst
: Sy
.IdSeq
;
2693 * We have a list of VarId here. If the list
2694 * has more than one element, then that is an
2695 * error, otherwise copy info to a ConId ...
2697 IF lst
.tide
> 1 THEN lst
.a
[1].IdError(192); RETURN END;
2699 cnId
:= Id
.newConId();
2700 cnId
.token
:= vrId
.token
;
2701 cnId
.hash
:= vrId
.hash
;
2702 cnId
.dfScp
:= vrId
.dfScp
;
2703 cnId
.SetMode(vrId
.vMod
);
2704 cnEx
:= constExpression(scp
);
2705 cnId
.conExp
:= cnEx
;
2706 cnId
.type
:= cnEx
.type
;
2707 Ty
.InsertInRec(cnId
,rec
,FALSE
,oId
,ok
);
2709 Sy
.AppendIdnt(rec
.statics
, cnId
);
2714 (* ----------------------------------------- *)
2715 PROCEDURE StaticField(lst
: Sy
.IdSeq
;
2724 Get
; (* read past colon *)
2725 flTp
:= type(scp
, Sy
.pubMode
);
2726 FOR indx
:= 0 TO lst
.tide
-1 DO
2727 flId
:= lst
.a
[indx
](Id
.VarId
);
2730 Ty
.InsertInRec(flId
,rec
,FALSE
,oId
,ok
);
2732 Sy
.AppendIdnt(rec
.statics
, flId
);
2738 (* ----------------------------------------- *)
2739 PROCEDURE DoStatic(rec
: Ty
.Record
;
2742 * StatDef --> PROCEDURE ProcHeading
2743 * | IdentDef { ',' IdentDef } ":" Type
2744 * | IdentDef "=" Constant .
2746 VAR list
: Sy
.IdSeq
;
2748 IF nextT
.sym
= T
.PROCEDURESym
THEN
2749 StaticProc(rec
, scp
);
2750 ELSIF nextT
.sym
= T
.identSym
THEN
2752 * There is a syntactic ambiguity here.
2753 * after an abitrary lookahead we find
2754 * the symbol which determines if this
2755 * is a constant or a variable definition.
2756 * We will "predict" a variable and then
2757 * back-patch later, if necessary.
2759 IdentDefList(list
, scp
, Id
.varId
);
2760 IF nextT
.sym
= T
.colonSym
THEN
2761 StaticField(list
, rec
, scp
);
2762 ELSIF nextT
.sym
= T
.equalSym
THEN
2763 StaticConst(list
, rec
, scp
);
2767 ELSE (* skip redundant semicolons *)
2770 (* ----------------------------------------- *)
2772 DoStatic(recT
, defScp
);
2773 WHILE (nextT
.sym
= T
.semicolonSym
) DO
2775 DoStatic(recT
, defScp
);
2779 (* ==================================================================== *)
2781 PROCEDURE EnumConst(enum
: Ty
.Enum
;
2783 vMod
: INTEGER); (* vMod ??? *)
2788 IF nextT
.sym
# T
.identSym
THEN RETURN END; (* skip extra semis! *)
2789 idnt
:= identDef(defScp
, Id
.conId
);
2790 cnId
:= idnt(Id
.ConId
); (* don't insert yet! *)
2792 cnEx
:= constExpression(defScp
);
2793 cnId
.conExp
:= cnEx
;
2794 cnId
.type
:= cnEx
.type
;
2795 IF cnId
.type
# Bi
.intTp
THEN cnEx
.ExprError(37) END;
2796 IF enum
.symTb
.enter(cnId
.hash
, cnId
) THEN
2797 Sy
.AppendIdnt(enum
.statics
, cnId
);
2803 (* ==================================================================== *)
2805 PROCEDURE ArrLength(defScp
: Sy
.Scope
; OUT n
: INTEGER; OUT p
: BOOLEAN);
2806 VAR xSyn
: Xp
.LeafX
;
2810 xSyn
:= constExpression(defScp
);
2812 IF xSyn
.kind
= Xp
.numLt
THEN
2813 n
:= xSyn
.value
.int();
2814 IF n
> 0 THEN p
:= TRUE
ELSE SemError(68) END;
2821 (* ==================================================================== *)
2823 PROCEDURE PointerType(pTyp
: Ty
.Pointer
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2825 Expect(T
.POINTERSym
);
2827 pTyp
.boundTp
:= type(defScp
, vMod
);
2830 (* ==================================================================== *)
2832 PROCEDURE EventType(eTyp
: Ty
.Procedure
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2835 IF ~Cs
.targetIsNET() THEN SemError(208);
2836 ELSIF Cs
.strict
THEN SemError(221);
2838 IF ~
(defScp
IS Id
.BlkId
) THEN SemError(212) END;
2839 IF (nextT
.sym
= T
.lparenSym
) THEN
2840 FormalParameters(eTyp
, NIL, defScp
);
2845 (* ==================================================================== *)
2847 PROCEDURE RecordType(rTyp
: Ty
.Record
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2849 * Record --> RECORD ['(' tpQual { '+' tpQual } ')']
2851 * [ STATIC StatDef { ';' StatDef } ] END .
2853 VAR tpId
: Id
.TypId
;
2855 Expect(T
.RECORDSym
);
2856 IF Sy
.frnMd
IN Cs
.thisMod
.xAttr
THEN
2857 INCL(rTyp
.xAttr
, Sy
.isFn
); (* must be foreign *)
2859 IF (nextT
.sym
= T
.lparenSym
) THEN
2861 IF nextT
.sym
# T
.plusSym
THEN
2862 tpId
:= typeQualid(defScp
);
2866 IF tpId
# NIL THEN rTyp
.baseTp
:= tpId
.type
END;
2867 INCL(rTyp
.xAttr
, Sy
.clsTp
); (* must be a class *)
2868 (* interfaces ... *)
2869 WHILE (nextT
.sym
= T
.plusSym
) DO
2871 IF Cs
.strict
& (nextT
.sym
= T
.plusSym
) THEN SemError(221); END;
2872 tpId
:= typeQualid(defScp
);
2873 IF tpId
# NIL THEN Sy
.AppendType(rTyp
.interfaces
, tpId
.type
) END;
2875 Expect(T
.rparenSym
);
2877 FieldListSequence(rTyp
, defScp
, vMod
);
2878 IF nextT
.sym
= T
.STATICSym
THEN
2880 IF ~Cs
.special
THEN SemError(185) END;
2881 INCL(rTyp
.xAttr
, Sy
.isFn
); (* must be foreign *)
2882 StaticStuff(rTyp
, defScp
, vMod
);
2887 (* ==================================================================== *)
2889 PROCEDURE EnumType(enum
: Ty
.Enum
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2891 * Enum --> ENUM RECORD StatDef { ';' StatDef } END .
2894 IF ~Cs
.special
THEN SemError(185) END;
2895 Get
; (* read past ENUM *)
2896 (* Expect(T.RECORDSym); *)
2897 EnumConst(enum
, defScp
, vMod
);
2898 WHILE (nextT
.sym
= T
.semicolonSym
) DO
2900 EnumConst(enum
, defScp
, vMod
);
2905 (* ==================================================================== *)
2907 PROCEDURE OptAttr (rTyp
: Ty
.Record
);
2909 INCL(rTyp
.xAttr
, Sy
.clsTp
); (* must be a class *)
2910 IF nextT
.sym
= T
.ABSTRACTSym
THEN
2912 rTyp
.recAtt
:= Ty
.isAbs
;
2913 ELSIF nextT
.sym
= T
.EXTENSIBLESym
THEN
2915 rTyp
.recAtt
:= Ty
.extns
;
2916 ELSIF nextT
.sym
= T
.LIMITEDSym
THEN
2918 rTyp
.recAtt
:= Ty
.limit
;
2919 ELSIF nextT
.sym
= T
.INTERFACESym
THEN
2921 IF Cs
.strict
THEN SemError(221); END;
2922 rTyp
.recAtt
:= Ty
.iFace
;
2927 (* ==================================================================== *)
2929 PROCEDURE ArrayType (aTyp
: Ty
.Array
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2930 VAR length
: INTEGER;
2935 IF in(symSet
[3], nextT
.sym
) THEN
2936 ArrLength(defScp
, length
, ok
);
2937 IF ok
THEN aTyp
.length
:= length
END;
2938 WHILE (nextT
.sym
= T
.commaSym
) DO
2940 ArrLength(defScp
, length
, ok
);
2941 elemT
:= Ty
.newArrTp(); aTyp
.elemTp
:= elemT
; aTyp
:= elemT
;
2942 IF ok
THEN aTyp
.length
:= length
END;
2946 aTyp
.elemTp
:= type(defScp
, vMod
);
2948 IF vMod
# Sy
.prvMode
THEN FixAnon(defScp
, aTyp
.elemTp
, vMod
) END;
2951 (* ==================================================================== *)
2953 PROCEDURE VectorType (aTyp
: Ty
.Vector
; defScp
: Sy
.Scope
; vMod
: INTEGER);
2954 VAR length
: INTEGER;
2958 Expect(T
.VECTORSym
);
2960 aTyp
.elemTp
:= type(defScp
, vMod
);
2961 IF vMod
# Sy
.prvMode
THEN FixAnon(defScp
, aTyp
.elemTp
, vMod
) END;
2962 IF Cs
.strict
THEN SemError(221) END;
2965 (* ==================================================================== *)
2967 PROCEDURE ProcedureType(pTyp
: Ty
.Procedure
; defScp
: Sy
.Scope
);
2969 Expect(T
.PROCEDURESym
);
2970 IF (nextT
.sym
= T
.lparenSym
) THEN
2971 FormalParameters(pTyp
, NIL, defScp
);
2972 ELSIF (nextT
.sym
= T
.rparenSym
) OR
2973 (nextT
.sym
= T
.ENDSym
) OR
2974 (nextT
.sym
= T
.semicolonSym
) THEN
2980 (* ==================================================================== *)
2982 PROCEDURE CompoundType(defScp
: Sy
.Scope
; firstType
: Id
.TypId
) : Sy
.Type
;
2983 (* Parses a compound type from a series of comma separated qualidents.
2984 * One component of the compound type has already been parsed and is
2985 * passed as firstType. The next token is a comma. At most one of the
2986 * types can be a class, and all the others must be interfaces. The
2987 * type that is returned is a Pointer to a Record with the compound
2989 (* Things that could be checked here but aren't yet:
2990 * - that any interfaces are not part of the base type
2991 - that any interfaces are not entered more than once
2998 (* Checks to make sure the type is suitable for use in a compound
3000 PROCEDURE checkType(type
: Sy
.Type
) : BOOLEAN;
3003 ~
(type
.isRecordType() OR type
.isDynamicType()) THEN
3012 (* Check that we were passed an appropriate type and that
3013 * a comma is following *)
3014 IF ~
checkType(firstType
.type
) THEN Error(89); RETURN NIL END;
3015 IF nextT
.sym
# T
.commaSym
THEN Error(12); RETURN NIL END;
3017 (* Create the compound type *)
3018 cmpT
:= Ty
.newRecTp();
3019 cmpT
.recAtt
:= Ty
.cmpnd
;
3021 IF firstType
.type
.isInterfaceType() THEN
3022 (* Add it to the list of interfaces *)
3023 Sy
.AppendType(cmpT
.interfaces
, firstType
.type
);
3025 (* Make it our base type *)
3026 cmpT
.baseTp
:= firstType
.type
;
3029 WHILE nextT
.sym
= T
.commaSym
DO
3030 Get
; (* Eat the comma *)
3031 IF nextT
.sym
# T
.identSym
THEN Error(T
.identSym
) END;
3032 tpId
:= typeQualid(defScp
);
3033 IF ~
checkType(tpId
.type
) THEN RETURN NIL END;
3034 IF tpId
.type
.isInterfaceType() THEN
3035 Sy
.AppendType(cmpT
.interfaces
, tpId
.type
);
3037 IF cmpT
.baseTp
# NIL THEN Error(89); RETURN NIL END;
3038 cmpT
.baseTp
:= tpId
.type
;
3041 INCL(cmpT
.xAttr
, Sy
.clsTp
); (* must be a class *)
3042 ptrT
:= Ty
.newPtrTp();
3043 ptrT
.boundTp
:= cmpT
;
3047 (* ==================================================================== *)
3049 PROCEDURE type(defScp
: Sy
.Scope
; vMod
: INTEGER) : Sy
.Type
;
3050 VAR tpId
: Id
.TypId
;
3051 prcT
: Ty
.Procedure
;
3058 IF (nextT
.sym
= T
.identSym
) THEN
3059 tpId
:= typeQualid(defScp
);
3060 IF tpId
= NIL THEN RETURN NIL END;
3061 IF ~Cs
.extras
THEN RETURN tpId
.type
END;
3062 (* Compound type parsing... look for comma *)
3063 IF nextT
.sym
# T
.commaSym
THEN RETURN tpId
.type
3064 ELSE RETURN CompoundType(defScp
, tpId
) END;
3065 ELSIF (nextT
.sym
= T
.PROCEDURESym
) THEN
3066 prcT
:= Ty
.newPrcTp();
3067 ProcedureType(prcT
, defScp
); RETURN prcT
;
3068 ELSIF (nextT
.sym
= T
.ARRAYSym
) THEN
3069 arrT
:= Ty
.newArrTp();
3070 ArrayType(arrT
, defScp
, vMod
); RETURN arrT
;
3071 ELSIF (nextT
.sym
= T
.VECTORSym
) THEN
3072 vecT
:= Ty
.newVecTp();
3073 VectorType(vecT
, defScp
, vMod
); RETURN vecT
;
3074 ELSIF (nextT
.sym
= T
.ABSTRACTSym
) OR
3075 (nextT
.sym
= T
.EXTENSIBLESym
) OR
3076 (nextT
.sym
= T
.LIMITEDSym
) OR
3077 (nextT
.sym
= T
.INTERFACESym
) OR
3078 (nextT
.sym
= T
.RECORDSym
) THEN
3079 recT
:= Ty
.newRecTp();
3080 IF nextT
.sym
# T
.RECORDSym
THEN OptAttr(recT
) END;
3081 RecordType(recT
, defScp
, vMod
); RETURN recT
;
3082 ELSIF (nextT
.sym
= T
.POINTERSym
) THEN
3083 ptrT
:= Ty
.newPtrTp();
3084 PointerType(ptrT
, defScp
, vMod
); RETURN ptrT
;
3085 ELSIF (nextT
.sym
= T
.ENUMSym
) THEN
3086 enuT
:= Ty
.newEnuTp();
3087 EnumType(enuT
, defScp
, vMod
); RETURN enuT
;
3088 ELSIF (nextT
.sym
= T
.EVENTSym
) THEN
3089 prcT
:= Ty
.newEvtTp();
3090 EventType(prcT
, defScp
, vMod
); RETURN prcT
;
3092 Error(89); RETURN NIL;
3096 (* ==================================================================== *)
3098 PROCEDURE TypeDeclaration(defScp
: Sy
.Scope
);
3102 iTmp
:= identDef(defScp
, Id
.typId
);
3103 IF iTmp
.vMod
= Sy
.rdoMode
THEN SemError(134) END;
3105 iTmp
.type
:= type(defScp
, iTmp
.vMod
);
3106 IF (iTmp
.type
# NIL) & iTmp
.type
.isAnonType() THEN
3107 iTmp
.type
.idnt
:= iTmp
;
3109 stuck
:= Sy
.refused(iTmp
, defScp
);
3110 IF stuck
THEN iTmp
.IdError(4) END;
3111 END TypeDeclaration
;
3113 (* ==================================================================== *)
3115 PROCEDURE expression(scope
: Sy
.Scope
) : Sy
.Expr
;
3116 VAR relOp
: INTEGER;
3121 (* ------------------------------------------ *)
3122 PROCEDURE MarkAssign(id
: Sy
.Idnt
);
3124 IF (id
# NIL) & (id
IS Id
.Procs
) THEN
3125 INCL(id(Id
.Procs
).pAttr
, Id
.assgnd
);
3128 (* ------------------------------------------ *)
3131 expN1
:= simpleExpression(scope
);
3133 * Mark use of procedure-valued expressions.
3135 WITH expN1
: Xp
.IdLeaf
DO
3136 MarkAssign(expN1
.ident
);
3137 | expN1
: Xp
.IdentX
DO
3138 MarkAssign(expN1
.ident
);
3142 * ... and parse the substructures!
3144 IF in(symSet
[12], nextT
.sym
) THEN
3145 relOp
:= relation(); saveT
:= token
;
3146 expN2
:= simpleExpression(scope
);
3147 expN1
:= Xp
.newBinaryT(relOp
, expN1
, expN2
, saveT
);
3149 IF expN1
# NIL THEN expN1
.tSpan
:= S
.mkSpanTT(tokN1
, S
.prevTok
) END;
3153 (* ==================================================================== *)
3155 PROCEDURE constExpression(defScp
: Sy
.Scope
) : Xp
.LeafX
;
3158 (* ------------------------------------------ *)
3159 PROCEDURE eval(exp
: Sy
.Expr
) : Sy
.Expr
;
3161 RETURN exp
.exprAttr();
3166 (* ------------------------------------------ *)
3168 expr
:= expression(defScp
);
3172 IF expr
= NIL THEN (* skip *)
3173 ELSIF (expr
IS Xp
.LeafX
) &
3174 (expr
.kind
# Xp
.setXp
) THEN
3176 RETURN expr(Xp
.LeafX
);
3178 expr
.ExprError(25); (* expr not constant *)
3182 END constExpression
;
3184 (* ==================================================================== *)
3186 PROCEDURE ConstantDeclaration (defScp
: Sy
.Scope
);
3191 idnt
:= identDef(defScp
, Id
.conId
);
3192 cnId
:= idnt(Id
.ConId
); (* don't insert yet! *)
3194 cnEx
:= constExpression(defScp
);
3195 IF Sy
.refused(idnt
, defScp
) THEN idnt
.IdError(4) END;
3196 IF (cnId
# NIL) & (cnEx
# NIL) THEN
3197 cnId
.conExp
:= cnEx
;
3198 cnId
.type
:= cnEx
.type
;
3200 END ConstantDeclaration
;
3202 (* ==================================================================== *)
3204 PROCEDURE qualident(defScp
: Sy
.Scope
) : Sy
.Idnt
;
3205 (* Postcondition: returns a valid Id, or NIL. *
3206 * NIL ==> error already notified. *)
3211 (* modS : Sy.Scope; *)
3217 hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
3218 idnt
:= Sy
.bind(hash
, defScp
);
3220 SemError(2); RETURN NIL;
3221 ELSIF (idnt
.kind
# Id
.impId
) & (idnt
.kind
# Id
.alias
) THEN
3223 * This is a single token qualident.
3224 * Now we check for uplevel addressing.
3225 * Temporarily disallowed in boot version 0.n and 1.0
3227 IF (idnt
.dfScp
# NIL) & (* There is a scope, *)
3228 (idnt
.dfScp
# defScp
) & (* not current scope, *)
3229 (idnt
IS Id
.AbVar
) & (* is a variable, and *)
3230 (idnt
.dfScp
IS Id
.Procs
) THEN (* scope is a PROC. *)
3232 locl
:= idnt(Id
.LocId
);
3233 IF ~
(Id
.uplevA
IN locl
.locAtt
) THEN
3235 WITH locl
: Id
.ParId
DO
3236 IF (locl
.parMod
# Sy
.val
) &
3239 ~locl
.type
.isRefSurrogate() THEN
3241 INCL(locl
.locAtt
, Id
.cpVarP
);
3245 locl
.IdErrorStr(eNum
, Sy
.getName
.ChPtr(idnt
));
3246 INCL(idnt
.dfScp(Id
.Procs
).pAttr
, Id
.hasXHR
);
3247 INCL(locl
.locAtt
, Id
.uplevA
); (* uplevel Any *)
3252 modS
:= idnt(Id
.BlkId
);
3253 IF Sy
.anon
IN modS
.xAttr
THEN
3254 SemErrorS1(239, Sy
.getName
.ChPtr(modS
.aliasMod
));
3260 * At this point the only live control flow branch is
3261 * the one predicated on the ident being a scope name.
3263 idnt
:= bindTokenLocal(modS
);
3265 SemError(3); (* name not known in qualified scope *)
3266 ELSIF modS
.isWeak() THEN
3267 SemErrorS1(175, Sy
.getName
.ChPtr(modS
)); (* mod not directly imported *)
3274 (* ==================================================================== *)
3276 PROCEDURE typeQualid(defScp
: Sy
.Scope
) : Id
.TypId
;
3277 (** This procedure returns one of --
3278 a valid Id.TypId (possibly a forward type)
3279 NIL (with an error already notified) *)
3287 hash
:= NameHash
.enterSubStr(token
.pos
, token
.len
);
3288 idnt
:= Sy
.bind(hash
, defScp
);
3292 * This _might_ just be a forward type. It cannot be so
3293 * if the next token is "." or if declarations in this
3294 * scope are officially closed.
3296 IF (nextT
.sym
= T
.pointSym
) OR defScp
.endDecl
THEN
3298 IF nextT
.sym
# T
.pointSym
THEN RETURN NIL END;
3300 tpTp
:= Ty
.newTmpTp();
3301 tpId
:= Id
.newTypId(tpTp
);
3302 tpId
.dfScp
:= defScp
;
3303 tpId
.token
:= token
;
3308 ELSIF idnt
.kind
= Id
.typId
THEN
3309 RETURN idnt(Id
.TypId
);
3310 ELSIF (idnt
.kind
= Id
.impId
) OR (idnt
.kind
= Id
.alias
) THEN
3311 modS
:= idnt(Id
.BlkId
);
3312 IF Sy
.anon
IN modS
.xAttr
THEN
3313 SemErrorS1(239, Sy
.getName
.ChPtr(modS
.aliasMod
));
3317 IF nextT
.sym
# T
.pointSym
THEN RETURN NIL END;
3321 IF modS
= NIL THEN RETURN NIL END;
3323 * At this point the only live control flow branch is
3324 * the one predicated on the ident being a scope name.
3326 idnt
:= bindTokenLocal(modS
);
3328 SemError(3); (* name not known in qualified scope *)
3329 ELSIF modS
.isWeak() THEN
3330 SemErrorS1(175, Sy
.getName
.ChPtr(modS
)); (* mod not directly imported *)
3331 ELSIF idnt
.kind
# Id
.typId
THEN
3332 SemError(7); (* name is not the name of a type *)
3334 tpId
:= idnt(Id
.TypId
);
3340 (* ==================================================================== *)
3342 PROCEDURE identDef(inhScp
: Sy
.Scope
; tag
: INTEGER) : Sy
.Idnt
;
3343 (** This non-terminal symbol creates an Id of prescribed kind for
3344 the ident. The Id has its parent scope assigned, but is not yet
3345 inserted into the prescribed scope. *)
3349 | Id
.conId
: iSyn
:= Id
.newConId();
3350 | Id
.parId
: iSyn
:= Id
.newParId();
3351 | Id
.quaId
: iSyn
:= Id
.newQuaId();
3352 | Id
.modId
: iSyn
:= Id
.newModId();
3353 | Id
.impId
: iSyn
:= Id
.newImpId();
3354 | Id
.fldId
: iSyn
:= Id
.newFldId();
3355 | Id
.fwdMth
: iSyn
:= Id
.newMthId();
3356 | Id
.conMth
: iSyn
:= Id
.newMthId();
3357 | Id
.fwdPrc
: iSyn
:= Id
.newPrcId();
3358 | Id
.conPrc
: iSyn
:= Id
.newPrcId();
3359 | Id
.typId
: iSyn
:= Id
.newTypId(NIL);
3360 | Id
.fwdTyp
: iSyn
:= Id
.newTypId(NIL);
3361 | Id
.varId
: IF inhScp
IS Id
.BlkId
THEN
3362 iSyn
:= Id
.newVarId();
3364 iSyn
:= Id
.newLocId();
3367 IF iSyn
IS Sy
.Scope
THEN iSyn(Sy
.Scope
).ovfChk
:= Cs
.ovfCheck
END;
3368 iSyn
.token
:= nextT
;
3369 iSyn
.hash
:= NameHash
.enterSubStr(nextT
.pos
, nextT
.len
);
3370 IF Cs
.verbose
THEN iSyn
.SetNameFromHash(iSyn
.hash
) END;
3371 iSyn
.dfScp
:= inhScp
;
3372 IF nextT
.dlr
& ~Cs
.special
THEN SemErrorT(186, nextT
) END;
3374 IF (nextT
.sym
= T
.starSym
) OR
3375 (nextT
.sym
= T
.bangSym
) OR
3376 (nextT
.sym
= T
.minusSym
) THEN
3377 IF (nextT
.sym
= T
.starSym
) THEN
3379 iSyn
.SetMode(Sy
.pubMode
);
3380 ELSIF (nextT
.sym
= T
.minusSym
) THEN
3382 iSyn
.SetMode(Sy
.rdoMode
);
3385 iSyn
.SetMode(Sy
.protect
);
3386 IF ~Cs
.special
THEN SemError(161) END;
3389 IF (iSyn
.vMod
# Sy
.prvMode
) & (inhScp
# Cs
.thisMod
) THEN
3395 (* ==================================================================== *)
3399 nam
: FileNames
.NameString
;
3403 IF nextT
.sym
= T
.identSym
THEN
3404 hsh
:= NameHash
.enterSubStr(nextT
.pos
, nextT
.len
);
3405 IF hsh
= Bi
.sysBkt
THEN
3407 INCL(Cs
.thisMod
.xAttr
, Sy
.rtsMd
);
3408 IF Cs
.verbose
THEN Cs
.Message("Compiling a SYSTEM Module") END;
3409 IF ~Cs
.special
THEN SemError(144) END;
3410 ELSIF hsh
= Bi
.frnBkt
THEN
3412 INCL(Cs
.thisMod
.xAttr
, Sy
.frnMd
);
3413 IF Cs
.verbose
THEN Cs
.Message("Compiling a FOREIGN Module") END;
3414 IF ~Cs
.special
THEN SemError(144) END;
3417 ELSIF nextT
.sym
= T
.MODULESym
THEN
3418 (* Except for empty bodies this next will be overwritten later *)
3419 Cs
.thisMod
.begTok
:= nextT
;
3422 Cs
.thisMod
.endTok
:= nextT
;
3425 S
.GetString(token
.pos
, token
.len
, nam
);
3426 IF nam
# Cs
.modNam
THEN
3427 IF token
.sym
= T
.identSym
THEN err
:= 1 ELSE err
:= 0 END;
3428 SemErrorS1(err
, Cs
.modNam$
);
3433 (* ==================================================================== *)
3437 NEW(nextT
); (* so that token is not even NIL initially *)
3439 Cs
.parseS
:= RTS
.GetMillis();
3443 (* ==================================================================== *)
3445 PROCEDURE parseTextAsStatement
*(text
: ARRAY OF LitValue
.CharOpen
; encScp
: Sy
.Scope
) : Sy
.Stmt
;
3446 VAR result
: Sy
.Stmt
;
3450 S
.NewReadBuffer(text
); Get
;
3451 result
:= statementSequence(NIL, encScp
);
3452 S
.RestoreFileBuffer();
3455 END parseTextAsStatement
;
3457 PROCEDURE ParseDeclarationText
*(text
: ARRAY OF LitValue
.CharOpen
; encScp
: Sy
.Scope
);
3461 S
.NewReadBuffer(text
); Get
;
3462 DeclarationSequence(encScp
);
3463 S
.RestoreFileBuffer();
3465 END ParseDeclarationText
;
3467 (* ==================================================================== *)
3470 comma
:= LitValue
.strToCharOpen(",");
3471 errDist
:= minErrDist
;
3472 (* ------------------------------------------------------------ *)
3474 symSet
[ 0, 0] := {T
.EOFSYM
, T
.identSym
, T
.ENDSym
, T
.semicolonSym
};
3475 symSet
[ 0, 1] := {T
.EXITSym
-32, T
.RETURNSym
-32, T
.NEWSym
-32, T
.IFSym
-32,
3476 T
.ELSIFSym
-32, T
.ELSESym
-32, T
.CASESym
-32, T
.barSym
-32,
3477 T
.WHILESym
-32, T
.REPEATSym
-32, T
.UNTILSym
-32, T
.FORSym
-32};
3478 symSet
[ 0, 2] := {T
.LOOPSym
-64, T
.WITHSym
-64, T
.CLOSESym
-64};
3479 (* ------------------------------------------------------------ *)
3481 (* Follow comma in ident-list *)
3482 symSet
[ 1, 0] := {T
.identSym
};
3483 symSet
[ 1, 1] := {};
3484 symSet
[ 1, 2] := {};
3485 (* ------------------------------------------------------------ *)
3487 (* Follow(ident-list) *)
3488 symSet
[ 2, 0] := {T
.colonSym
};
3489 symSet
[ 2, 1] := {};
3490 symSet
[ 2, 2] := {};
3491 (* ------------------------------------------------------------ *)
3493 (* Start(expression) *)
3494 symSet
[ 3, 0] := {T
.identSym
, T
.integerSym
, T
.realSym
, T
.CharConstantSym
,
3495 T
.stringSym
, T
.minusSym
, T
.lparenSym
, T
.plusSym
};
3496 symSet
[ 3, 1] := {T
.NILSym
-32, T
.tildeSym
-32, T
.lbraceSym
-32};
3497 symSet
[ 3, 2] := {T
.bangStrSym
-64};
3498 (* ------------------------------------------------------------ *)
3500 (* lookahead of optional statement *)
3501 symSet
[ 4, 0] := {T
.EOFSYM
, T
.identSym
, T
.ENDSym
, T
.semicolonSym
};
3502 symSet
[ 4, 1] := {T
.EXITSym
-32, T
.RETURNSym
-32, T
.NEWSym
-32, T
.IFSym
-32,
3503 T
.ELSIFSym
-32, T
.ELSESym
-32, T
.CASESym
-32, T
.barSym
-32,
3504 T
.WHILESym
-32, T
.REPEATSym
-32, T
.UNTILSym
-32, T
.FORSym
-32};
3505 symSet
[ 4, 2] := {T
.LOOPSym
-64, T
.WITHSym
-64, T
.CLOSESym
-64, T
.RESCUESym
-64};
3506 (* ------------------------------------------------------------ *)
3508 (* follow semicolon in statementSequence *)
3509 symSet
[ 5, 0] := {T
.identSym
, T
.ENDSym
, T
.semicolonSym
};
3510 symSet
[ 5, 1] := {T
.EXITSym
-32, T
.RETURNSym
-32, T
.NEWSym
-32, T
.IFSym
-32,
3511 T
.ELSIFSym
-32, T
.ELSESym
-32, T
.CASESym
-32, T
.barSym
-32,
3512 T
.WHILESym
-32, T
.REPEATSym
-32, T
.UNTILSym
-32, T
.FORSym
-32};
3513 symSet
[ 5, 2] := {T
.LOOPSym
-64, T
.WITHSym
-64, T
.CLOSESym
-64, T
.RESCUESym
-64};
3514 (* ------------------------------------------------------------ *)
3516 (* Follow(statementSequence) *)
3517 symSet
[ 6, 0] := {T
.ENDSym
};
3518 symSet
[ 6, 1] := {T
.ELSIFSym
-32, T
.ELSESym
-32, T
.barSym
-32, T
.UNTILSym
-32};
3519 symSet
[ 6, 2] := {T
.CLOSESym
-64, T
.RESCUESym
-64};
3520 (* ------------------------------------------------------------ *)
3522 (* Follow(barSym) *)
3523 symSet
[ 7, 0] := {T
.EOFSYM
, T
.identSym
, T
.integerSym
, T
.realSym
,
3524 T
.CharConstantSym
, T
.stringSym
, T
.minusSym
, T
.lparenSym
,
3525 T
.plusSym
, T
.ENDSym
, T
.semicolonSym
};
3526 symSet
[ 7, 1] := {T
.NILSym
-32, T
.tildeSym
-32, T
.lbraceSym
-32,
3527 T
.EXITSym
-32, T
.RETURNSym
-32, T
.NEWSym
-32, T
.IFSym
-32,
3528 T
.ELSIFSym
-32, T
.ELSESym
-32, T
.CASESym
-32, T
.barSym
-32,
3529 T
.WHILESym
-32, T
.REPEATSym
-32, T
.UNTILSym
-32, T
.FORSym
-32};
3530 symSet
[ 7, 2] := {T
.LOOPSym
-64, T
.WITHSym
-64, T
.CLOSESym
-64};
3531 (* ------------------------------------------------------------ *)
3533 (* lookahead to optional arglist *)
3534 symSet
[ 8, 0] := {(*T.lparenSym,*) T
.ENDSym
, T
.semicolonSym
};
3535 symSet
[ 8, 1] := {T
.ELSIFSym
-32, T
.ELSESym
-32, T
.barSym
-32, T
.UNTILSym
-32};
3536 symSet
[ 8, 2] := {T
.CLOSESym
-64};
3537 (* ------------------------------------------------------------ *)
3539 (* Start(statement) *)
3540 symSet
[ 9, 0] := {T
.identSym
};
3541 symSet
[ 9, 1] := {T
.EXITSym
-32, T
.RETURNSym
-32, T
.NEWSym
-32, T
.IFSym
-32,
3542 T
.CASESym
-32, T
.WHILESym
-32, T
.REPEATSym
-32, T
.FORSym
-32};
3543 symSet
[ 9, 2] := {T
.LOOPSym
-64, T
.WITHSym
-64};
3544 (* ------------------------------------------------------------ *)
3546 (* follow semicolon in FormalParamLists *)
3547 symSet
[10, 0] := {T
.identSym
};
3548 symSet
[10, 1] := {T
.INSym
-32};
3549 symSet
[10, 2] := {T
.VARSym
-64, T
.OUTSym
-64};
3550 (* ------------------------------------------------------------ *)
3552 (* Follow(FPsection-repetition) *)
3553 symSet
[11, 0] := {T
.rparenSym
};
3554 symSet
[11, 1] := {};
3555 symSet
[11, 2] := {};
3556 (* ------------------------------------------------------------ *)
3558 (* Follow(simpleExpression) - Follow(expression) *)
3559 symSet
[12, 0] := {T
.equalSym
, T
.hashSym
};
3560 symSet
[12, 1] := {T
.lessSym
-32, T
.lessequalSym
-32, T
.greaterSym
-32,
3561 T
.greaterequalSym
-32, T
.INSym
-32, T
.ISSym
-32};
3562 symSet
[12, 2] := {};
3563 (* ------------------------------------------------------------ *)