IMPLEMENTATION MODULE M2P; (* Parser generated by Coco/R - assuming ISO IO library will be available. *) IMPORT M2S, FileIO; IMPORT SymTab, QbeGen; CONST maxT = 82; minErrDist = 2; (* minimal distance (good tokens) between two errors *) setsize = 16; (* sets are stored in 16 bits *) TYPE SymbolSet = ARRAY [0 .. maxT DIV setsize] OF BITSET; VAR symSet: ARRAY [0 .. 11] OF SymbolSet; (*symSet[0] = allSyncSyms*) errDist: CARDINAL; (* number of symbols recognized since last error *) sym: CARDINAL; (* current input symbol *) PROCEDURE SemError (errNo: INTEGER); BEGIN IF errDist >= minErrDist THEN M2S.Error(errNo, M2S.line, M2S.col, M2S.pos); END; errDist := 0; END SemError; PROCEDURE SynError (errNo: INTEGER); BEGIN IF errDist >= minErrDist THEN M2S.Error(errNo, M2S.nextLine, M2S.nextCol, M2S.nextPos); END; errDist := 0; END SynError; PROCEDURE Get; VAR s: ARRAY [0 .. 31] OF CHAR; BEGIN REPEAT M2S.Get(sym); IF sym <= maxT THEN INC(errDist); ELSE END; UNTIL sym <= maxT END Get; PROCEDURE In (VAR s: SymbolSet; x: CARDINAL): BOOLEAN; BEGIN RETURN x MOD setsize IN s[x DIV setsize]; END In; PROCEDURE Expect (n: CARDINAL); BEGIN IF sym = n THEN Get ELSE SynError(n) END END Expect; PROCEDURE ExpectWeak (n, follow: CARDINAL); BEGIN IF sym = n THEN Get ELSE SynError(n); WHILE NOT In(symSet[follow], sym) DO Get END END END ExpectWeak; PROCEDURE WeakSeparator (n, syFol, repFol: CARDINAL): BOOLEAN; VAR s: SymbolSet; i: CARDINAL; BEGIN IF sym = n THEN Get; RETURN TRUE ELSIF In(symSet[repFol], sym) THEN RETURN FALSE ELSE i := 0; WHILE i <= maxT DIV setsize DO s[i] := symSet[0, i] + symSet[syFol, i] + symSet[repFol, i]; INC(i) END; SynError(n); WHILE NOT In(s, sym) DO Get END; RETURN In(symSet[syFol], sym) END END WeakSeparator; PROCEDURE LexName (VAR Lex: ARRAY OF CHAR); BEGIN M2S.GetName(M2S.pos, M2S.len, Lex) END LexName; PROCEDURE LexString (VAR Lex: ARRAY OF CHAR); BEGIN M2S.GetString(M2S.pos, M2S.len, Lex) END LexString; PROCEDURE LookAheadName (VAR Lex: ARRAY OF CHAR); BEGIN M2S.GetName(M2S.nextPos, M2S.nextLen, Lex) END LookAheadName; PROCEDURE LookAheadString (VAR Lex: ARRAY OF CHAR); BEGIN M2S.GetString(M2S.nextPos, M2S.nextLen, Lex) END LookAheadString; PROCEDURE Successful (): BOOLEAN; BEGIN RETURN M2S.errors = 0 END Successful; (* ----- FORWARD not needed in multipass compilers PROCEDURE SetItem; FORWARD; PROCEDURE MapTail; FORWARD; PROCEDURE SetItems; FORWARD; PROCEDURE MulOp (VAR op: INTEGER); FORWARD; PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); FORWARD; PROCEDURE AddOp (VAR op: INTEGER); FORWARD; PROCEDURE Term (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); FORWARD; PROCEDURE Rel (VAR op: INTEGER); FORWARD; PROCEDURE SimExpr (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); FORWARD; PROCEDURE ExprList; FORWARD; PROCEDURE CaseLabel (tsel: SymTab.TypeIndex; qsel: QbeGen.QVal; lBody: QbeGen.QVal); FORWARD; PROCEDURE CaseAlt (tsel: SymTab.TypeIndex; qsel: QbeGen.QVal; lEnd: QbeGen.QVal); FORWARD; PROCEDURE Design2 (VAR t: SymTab.TypeIndex; VAR k: INTEGER; VAR q: QbeGen.QVal; VAR qn: SymTab.Name); FORWARD; PROCEDURE ReturnStat; FORWARD; PROCEDURE WithStat; FORWARD; PROCEDURE CaseStat; FORWARD; PROCEDURE ForStat; FORWARD; PROCEDURE LoopStat; FORWARD; PROCEDURE RepeatStat; FORWARD; PROCEDURE WhileStat; FORWARD; PROCEDURE IfStat; FORWARD; PROCEDURE DesignStat; FORWARD; PROCEDURE Statement; FORWARD; PROCEDURE ActualParams; FORWARD; PROCEDURE Design (VAR t: SymTab.TypeIndex; VAR k: INTEGER; VAR q: QbeGen.QVal; VAR qn: SymTab.Name); FORWARD; PROCEDURE ParamSection; FORWARD; PROCEDURE FormalParams; FORWARD; PROCEDURE ParIdents (isV: BOOLEAN); FORWARD; PROCEDURE VarIdents; FORWARD; PROCEDURE VarDecl; FORWARD; PROCEDURE Block (pn: SymTab.Name); FORWARD; PROCEDURE MethodImpl (ct: SymTab.TypeIndex); FORWARD; PROCEDURE Parent1 (ct: SymTab.TypeIndex); FORWARD; PROCEDURE MethodHeading (VAR pn: SymTab.Name); FORWARD; PROCEDURE ClassField (ct: SymTab.TypeIndex); FORWARD; PROCEDURE Parents (ct: SymTab.TypeIndex); FORWARD; PROCEDURE ClassRest; FORWARD; PROCEDURE ClassImplRest; FORWARD; PROCEDURE ProcTypeParam; FORWARD; PROCEDURE VariantLabel; FORWARD; PROCEDURE VariantLabels; FORWARD; PROCEDURE Variant (rec: SymTab.TypeIndex); FORWARD; PROCEDURE FieldIdents (rec: SymTab.TypeIndex); FORWARD; PROCEDURE VariantList (rec: SymTab.TypeIndex); FORWARD; PROCEDURE FieldList (rec: SymTab.TypeIndex); FORWARD; PROCEDURE FieldListSequence (rec: SymTab.TypeIndex); FORWARD; PROCEDURE Bound; FORWARD; PROCEDURE Expr (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); FORWARD; PROCEDURE ProcType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE PointerType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE SetType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE RecordType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE ArrayType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE Enum (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE SubrangeRest (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE TypeIdent2 (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE Type (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE TypeItem (isDef: BOOLEAN); FORWARD; PROCEDURE ImpList; FORWARD; PROCEDURE Export; FORWARD; PROCEDURE LabelList; FORWARD; PROCEDURE NestedModule; FORWARD; PROCEDURE ProcDecl; FORWARD; PROCEDURE Priority; FORWARD; PROCEDURE StatSeq; FORWARD; PROCEDURE DeclSeq; FORWARD; PROCEDURE ClassItem; FORWARD; PROCEDURE ProcHeading (VAR pn: SymTab.Name); FORWARD; PROCEDURE ConstDecl; FORWARD; PROCEDURE VarBlock; FORWARD; PROCEDURE TypeBlock (isDef: BOOLEAN); FORWARD; PROCEDURE ConstBlock; FORWARD; PROCEDURE Import; FORWARD; PROCEDURE GetIdent (VAR n: SymTab.Name); FORWARD; PROCEDURE ProgModule; FORWARD; PROCEDURE ImplUnit; FORWARD; PROCEDURE DefUnit; FORWARD; PROCEDURE Unit; FORWARD; PROCEDURE M2; FORWARD; ----- *) PROCEDURE SetItem; VAR t1, t2: SymTab.TypeIndex; q1, q2: QbeGen.QVal; BEGIN Expr(t1, q1); SemError(230);; IF (sym = 25) THEN Get; Expr(t2, q2); SemError(230);; END; END SetItem; PROCEDURE MapTail; VAR mq: SymTab.Name; et: SymTab.TypeIndex; q2: QbeGen.QVal; BEGIN WHILE (sym = 5) OR (sym = 15) OR (sym = 26) OR (sym = 59) DO IF (sym = 5) THEN Get; GetIdent(mq); SemError(230);; ELSIF (sym = 59) THEN Get; SemError(230);; ELSIF (sym = 15) THEN Get; Expr(et, q2); Expect(16); SemError(230);; ELSE Get; IF In(symSet[1], sym) THEN ActualParams; END; Expect(27); SemError(230);; END; END; END MapTail; PROCEDURE SetItems; BEGIN SetItem; WHILE (sym = 14) DO Get; SetItem; END; END SetItems; PROCEDURE MulOp (VAR op: INTEGER); BEGIN CASE sym OF 70 : Get; op := SymTab.OpTimes;; | 71 : Get; op := SymTab.OpSlash;; | 72 : Get; op := SymTab.OpDiv;; | 73 : Get; op := SymTab.OpMod;; | 74 : Get; op := SymTab.OpAnd;; | 75 : Get; op := SymTab.OpAnd;; | 76 : Get; op := 10;; | 77 : Get; op := 11;; ELSE SynError(83); END; END MulOp; PROCEDURE Fact (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); VAR s: ARRAY [0 .. 255] OF CHAR; et, dt, t2, b: SymTab.TypeIndex; dk: INTEGER; qd, q2: QbeGen.QVal; qn: SymTab.Name; isCh: BOOLEAN; BEGIN CASE sym OF 2 : Get; LexString(s); QbeGen.NormLit(s, q, isCh); IF isCh THEN t := SymTab.CharType() ELSE t := SymTab.IntType() END;; | 3 : Get; LexString(s); QbeGen.NormReal(s, q); t := SymTab.RealType();; | 4 : Get; LexString(s); IF SymTab.StrLen(s) <= 3 THEN t := SymTab.CharType(); QbeGen.IntStr( QbeGen.CharVal(s), q) ELSE t := SymTab.NewStr(); SemError(230); QbeGen.CopyOp("0", q) END;; | 78 : Get; IF In(symSet[1], sym) THEN SetItems; END; Expect(79); SemError(230); QbeGen.CopyOp("0", q); t := SymTab.InvalidType;; | 15 : Get; Expr(et, q); Expect(32); Expr(t2, q2); SemError(230); QbeGen.CopyOp("0", q); t := SymTab.InvalidType;; IF (sym = 1) THEN TypeIdent2(b); END; Expect(16); MapTail; | 1 : Design2(dt, dk, qd, qn); t := dt; QbeGen.CopyOp(qd, q);; | 26 : Get; Expr(et, q); Expect(27); t := et;; | 80 : Get; Fact(t2, q2); IF SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END; IF t # SymTab.InvalidType THEN QbeGen.NotQ(q2, q) ELSE QbeGen.CopyOp("0", q) END;; | 81 : Get; Fact(t2, q2); IF SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END; IF t # SymTab.InvalidType THEN QbeGen.NotQ(q2, q) ELSE QbeGen.CopyOp("0", q) END;; ELSE SynError(84); END; END Fact; PROCEDURE AddOp (VAR op: INTEGER); BEGIN IF (sym = 67) THEN Get; op := SymTab.OpAdd;; ELSIF (sym = 68) THEN Get; op := SymTab.OpSub;; ELSIF (sym = 69) THEN Get; op := SymTab.OpOr;; ELSE SynError(85); END; END AddOp; PROCEDURE Term (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); VAR t2, res2: SymTab.TypeIndex; op: INTEGER; q2, qt: QbeGen.QVal; isR: BOOLEAN; BEGIN Fact(t, q); WHILE In(symSet[2], sym) DO MulOp(op); Fact(t2, q2); IF (op = SymTab.OpAnd) THEN IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END; IF t # SymTab.InvalidType THEN QbeGen.NewTemp(qt); QbeGen.Op3("and", qt, q, q2, FALSE); QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END ELSIF (op = 10) OR (op = 11) THEN (* << and >> : V3 word shifts; QBE shl/sar. *) IF ~SymTab.IsIntFamily(t) OR ~SymTab.IsIntFamily(t2) THEN SemError(211); t := SymTab.InvalidType END; IF t # SymTab.InvalidType THEN QbeGen.NewTemp(qt); IF op = 10 THEN QbeGen.Op3("shl", qt, q, q2, FALSE) ELSE QbeGen.Op3("sar", qt, q, q2, FALSE) END; QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END ELSE IF SymTab.ArithCheck(t, t2, (op = SymTab.OpDiv) OR (op = SymTab.OpMod), res2) THEN t := res2 ELSE SemError(211); t := SymTab.InvalidType END; isR := SymTab.ClassOf(t) = SymTab.ClReal; IF t # SymTab.InvalidType THEN QbeGen.NewTemp(qt); IF op = SymTab.OpTimes THEN QbeGen.Op3("mul", qt, q, q2, isR) ELSIF (op = SymTab.OpDiv) OR (op = SymTab.OpSlash) THEN QbeGen.Op3("div", qt, q, q2, isR) ELSE QbeGen.Op3("rem", qt, q, q2, isR) END; QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END END;; END; END Term; PROCEDURE Rel (VAR op: INTEGER); BEGIN CASE sym OF 22 : Get; op := SymTab.OpEq;; | 61 : Get; op := SymTab.OpNeq1;; | 62 : Get; op := SymTab.OpNeq1;; | 63 : Get; op := SymTab.OpLt;; | 64 : Get; op := SymTab.OpLe;; | 65 : Get; op := SymTab.OpGt;; | 66 : Get; op := SymTab.OpGe;; ELSE SynError(86); END; END Rel; PROCEDURE SimExpr (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); VAR t2, res2: SymTab.TypeIndex; op: INTEGER; q2, qt: QbeGen.QVal; neg, isR: BOOLEAN; BEGIN neg := FALSE;; IF (sym = 67) OR (sym = 68) THEN IF (sym = 67) THEN Get; ELSE Get; neg := TRUE;; END; END; Term(t, q); IF neg THEN IF QbeGen.IsImm(q) THEN QbeGen.NegFold(q, q) ELSE QbeGen.NewTemp(qt); QbeGen.NegQ(q, qt, SymTab.ClassOf(t) = SymTab.ClReal); QbeGen.CopyOp(qt, q) END END;; WHILE (sym = 67) OR (sym = 68) OR (sym = 69) DO AddOp(op); Term(t2, q2); IF op = SymTab.OpOr THEN IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END; IF t # SymTab.InvalidType THEN QbeGen.NewTemp(qt); QbeGen.Op3("or", qt, q, q2, FALSE); QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END ELSE IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2 ELSE SemError(211); t := SymTab.InvalidType END; isR := SymTab.ClassOf(t) = SymTab.ClReal; IF t # SymTab.InvalidType THEN QbeGen.NewTemp(qt); IF op = SymTab.OpAdd THEN QbeGen.Op3("add", qt, q, q2, isR) ELSE QbeGen.Op3("sub", qt, q, q2, isR) END; QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END END;; END; END SimExpr; PROCEDURE ExprList; VAR t: SymTab.TypeIndex; q: QbeGen.QVal; BEGIN Expr(t, q); WHILE (sym = 14) DO Get; Expr(t, q); END; END ExprList; PROCEDURE CaseLabel (tsel: SymTab.TypeIndex; qsel: QbeGen.QVal; lBody: QbeGen.QVal); VAR t2, t3: SymTab.TypeIndex; q2, q3, qc, qd, qe: QbeGen.QVal; lNext: QbeGen.QVal; BEGIN Expr(t2, q2); IF (t2 # SymTab.InvalidType) & (tsel # SymTab.InvalidType) & ~SymTab.EqCheck(t2, tsel) THEN SemError(213) END; IF ~QbeGen.IsImm(q2) THEN SemError(230); QbeGen.CopyOp("0", q2) END; QbeGen.NewLabel(lNext); QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE); QbeGen.Jnz(qc, lBody, lNext); QbeGen.EmitLabel(lNext);; IF (sym = 25) THEN Get; Expr(t3, q3); IF (t3 # SymTab.InvalidType) & (tsel # SymTab.InvalidType) & ~SymTab.EqCheck(t3, tsel) THEN SemError(213) END; IF ~QbeGen.IsImm(q3) THEN SemError(230); QbeGen.CopyOp("0", q3) END; QbeGen.Cmp(SymTab.OpGe, qsel, q2, qc, FALSE); QbeGen.Cmp(SymTab.OpLe, qsel, q3, qd, FALSE); QbeGen.NewTemp(qe); QbeGen.Op3("and", qe, qc, qd, FALSE); QbeGen.NewLabel(lNext); QbeGen.Jnz(qe, lBody, lNext); QbeGen.EmitLabel(lNext);; END; END CaseLabel; PROCEDURE CaseAlt (tsel: SymTab.TypeIndex; qsel: QbeGen.QVal; lEnd: QbeGen.QVal); VAR lBody, lAfter: QbeGen.QVal; BEGIN QbeGen.NewLabel(lBody); QbeGen.NewLabel(lAfter);; CaseLabel(tsel, qsel, lBody); WHILE (sym = 14) DO Get; CaseLabel(tsel, qsel, lBody); END; Expect(32); QbeGen.Jmp(lAfter); QbeGen.EmitLabel(lBody);; IF In(symSet[3], sym) THEN StatSeq; QbeGen.Jmp(lEnd);; END; QbeGen.EmitLabel(lAfter);; END CaseAlt; PROCEDURE Design2 (VAR t: SymTab.TypeIndex; VAR k: INTEGER; VAR q: QbeGen.QVal; VAR qn: SymTab.Name); BEGIN Design(t, k, q, qn); WHILE (sym = 5) OR (sym = 15) OR (sym = 26) OR (sym = 59) DO IF (sym = 5) THEN Get; GetIdent(qn); SemError(230); t := SymTab.InvalidType;; ELSIF (sym = 59) THEN Get; SemError(230); t := SymTab.InvalidType;; ELSIF (sym = 15) THEN Get; ExprList; Expect(16); SemError(230); t := SymTab.InvalidType;; ELSE Get; IF In(symSet[1], sym) THEN ActualParams; END; Expect(27); SemError(230); t := SymTab.InvalidType;; END; END; END Design2; PROCEDURE ReturnStat; VAR t: SymTab.TypeIndex; q: QbeGen.QVal; res: SymTab.TypeIndex; hadE: BOOLEAN; BEGIN Expect(57); hadE := FALSE;; IF In(symSet[1], sym) THEN Expr(t, q); hadE := TRUE;; END; IF ~SymTab.InProc() THEN SemError(232) ELSE res := SymTab.CurRes(); IF ~hadE THEN IF res # SymTab.InvalidType THEN SemError(232) END ELSIF (res = SymTab.InvalidType) OR (t # SymTab.InvalidType) & ~SymTab.Assignable(t, res) THEN SemError(232) END END;; END ReturnStat; PROCEDURE WithStat; VAR t: SymTab.TypeIndex; k: INTEGER; q: QbeGen.QVal; qn: SymTab.Name; BEGIN Expect(58); Design2(t, k, q, qn); IF ~SymTab.PushRecord(t) THEN SemError(230) END;; Expect(51); IF In(symSet[3], sym) THEN StatSeq; END; Expect(9); SymTab.PopScope; SemError(230);; END WithStat; PROCEDURE CaseStat; VAR tsel: SymTab.TypeIndex; qsel, lEnd: QbeGen.QVal; BEGIN Expect(31); Expr(tsel, qsel); QbeGen.NewLabel(lEnd);; Expect(29); IF (sym = 33) THEN Get; END; WHILE In(symSet[1], sym) DO CaseAlt(tsel, qsel, lEnd); IF (sym = 8) THEN Get; END; IF (sym = 33) THEN Get; END; END; IF (sym = 34) THEN Get; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); QbeGen.EmitLabel(lEnd);; END CaseStat; PROCEDURE ForStat; VAR lv: SymTab.Name; tlo, thi, tby: SymTab.TypeIndex; qlo, qhi, qby, qt, qk, qb: QbeGen.QVal; lTop, lBody, lEnd: QbeGen.QVal; by: INTEGER; ok: BOOLEAN; BEGIN Expect(55); by := 1;; GetIdent(lv); ok := SymTab.Lookup(lv); IF ~ok THEN SemError(201) ELSIF (SymTab.SymKind(lv) # SymTab.KindVar) & (SymTab.SymKind(lv) # SymTab.KindParam) THEN SemError(220); ok := FALSE ELSIF ~SymTab.IsIntFamily( SymTab.SymType(lv)) THEN SemError(220); ok := FALSE END;; Expect(46); Expr(tlo, qlo); IF ~SymTab.IsIntFamily(tlo) THEN SemError(220); ok := FALSE END;; Expect(36); Expr(thi, qhi); IF ~SymTab.IsIntFamily(thi) THEN SemError(220); ok := FALSE END;; IF (sym = 56) THEN Get; Expr(tby, qby); IF (tby # SymTab.InvalidType) & ~SymTab.IsIntFamily(tby) THEN SemError(220); ok := FALSE END; IF ~SymTab.ConstInt(qby, by) THEN SemError(230); by := 1 ELSIF by = 0 THEN SemError(220); by := 1 END;; END; Expect(51); IF ok THEN QbeGen.StoreVar(lv, qlo, FALSE) END; QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd); QbeGen.EmitLabel(lTop); QbeGen.LoadVar(lv, FALSE, qt); QbeGen.NewTemp(qk); IF by > 0 THEN QbeGen.Op3("cslew", qk, qt, qhi, FALSE) ELSE QbeGen.Op3("csgew", qk, qt, qhi, FALSE) END; QbeGen.Jnz(qk, lBody, lEnd); QbeGen.EmitLabel(lBody);; IF In(symSet[3], sym) THEN StatSeq; END; Expect(9); IF ok THEN QbeGen.LoadVar(lv, FALSE, qt); QbeGen.IntStr(by, qb); QbeGen.NewTemp(qk); QbeGen.Op3("add", qk, qt, qb, FALSE); QbeGen.StoreVar(lv, qk, FALSE) END; QbeGen.Jmp(lTop); QbeGen.EmitLabel(lEnd);; END ForStat; PROCEDURE LoopStat; VAR lTop, lEnd: QbeGen.QVal; BEGIN Expect(54); QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd); QbeGen.PushLoop(lEnd); QbeGen.EmitLabel(lTop);; IF In(symSet[3], sym) THEN StatSeq; END; Expect(9); QbeGen.Jmp(lTop); QbeGen.PopLoop; QbeGen.EmitLabel(lEnd);; END LoopStat; PROCEDURE RepeatStat; VAR t: SymTab.TypeIndex; q, lTop, lEnd: QbeGen.QVal; BEGIN Expect(52); QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd); QbeGen.EmitLabel(lTop);; IF In(symSet[3], sym) THEN StatSeq; END; Expect(53); Expr(t, q); IF ~SymTab.BoolCheck(t) THEN SemError(214) END; QbeGen.Jnz(q, lEnd, lTop); QbeGen.EmitLabel(lEnd);; END RepeatStat; PROCEDURE WhileStat; VAR t: SymTab.TypeIndex; q, lTop, lBody, lEnd: QbeGen.QVal; BEGIN Expect(50); QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd); QbeGen.EmitLabel(lTop);; Expr(t, q); IF ~SymTab.BoolCheck(t) THEN SemError(214) END; QbeGen.Jnz(q, lBody, lEnd); QbeGen.EmitLabel(lBody);; Expect(51); IF In(symSet[3], sym) THEN StatSeq; END; QbeGen.Jmp(lTop);; Expect(9); QbeGen.EmitLabel(lEnd);; END WhileStat; PROCEDURE IfStat; VAR t: SymTab.TypeIndex; q, lThen, lElse, lEnd: QbeGen.QVal; hasElse: BOOLEAN; BEGIN Expect(47); hasElse := FALSE;; Expr(t, q); IF ~SymTab.BoolCheck(t) THEN SemError(214) END; QbeGen.NewLabel(lThen); QbeGen.NewLabel(lElse); QbeGen.NewLabel(lEnd); QbeGen.Jnz(q, lThen, lElse); QbeGen.EmitLabel(lThen);; Expect(48); IF In(symSet[3], sym) THEN StatSeq; END; QbeGen.Jmp(lEnd);; WHILE (sym = 49) DO Get; QbeGen.EmitLabel(lElse); QbeGen.NewLabel(lElse);; Expr(t, q); IF ~SymTab.BoolCheck(t) THEN SemError(214) END; QbeGen.NewLabel(lThen); QbeGen.Jnz(q, lThen, lElse); QbeGen.EmitLabel(lThen);; Expect(48); IF In(symSet[3], sym) THEN StatSeq; END; QbeGen.Jmp(lEnd);; END; IF (sym = 34) THEN Get; QbeGen.EmitLabel(lElse); hasElse := TRUE;; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); IF hasElse THEN QbeGen.EmitLabel(lEnd) ELSE QbeGen.EmitLabel(lElse); QbeGen.EmitLabel(lEnd) END;; END IfStat; PROCEDURE DesignStat; VAR dt, et: SymTab.TypeIndex; dk: INTEGER; qd, qe, qt: QbeGen.QVal; qn: SymTab.Name; isR, conv: BOOLEAN; BEGIN Design2(dt, dk, qd, qn); IF (sym = 46) THEN Get; Expr(et, qe); IF (dt # SymTab.InvalidType) & (dk # SymTab.KindVar) & (dk # SymTab.KindParam) THEN SemError(210) ELSIF ~SymTab.Assignable(et, dt) THEN SemError(210) END; isR := (dt # SymTab.InvalidType) & (SymTab.ClassOf(dt) = SymTab.ClReal); conv := isR & SymTab.IsIntFamily(et); IF ((dk = SymTab.KindVar) OR (dk = SymTab.KindParam)) & (dt # SymTab.InvalidType) & (et # SymTab.InvalidType) THEN IF conv THEN QbeGen.ConvIR(qe, qt); QbeGen.StoreVar(qn, qt, TRUE) ELSE QbeGen.StoreVar(qn, qe, isR) END END;; ELSIF (sym = 26) THEN Get; IF In(symSet[1], sym) THEN ActualParams; END; Expect(27); SemError(230);; ELSIF In(symSet[4], sym) THEN SemError(230);; ELSE SynError(87); END; END DesignStat; PROCEDURE Statement; VAR lx: QbeGen.QVal; lqn: SymTab.Name; BEGIN CASE sym OF 1 : DesignStat; | 47 : IfStat; | 50 : WhileStat; | 52 : RepeatStat; | 54 : LoopStat; | 55 : ForStat; | 31 : CaseStat; | 58 : WithStat; | 57 : ReturnStat; | 44 : Get; GetIdent(lqn); SemError(230);; | 45 : Get; IF QbeGen.TopLoop(lx) THEN QbeGen.Jmp(lx) ELSE SemError(230) END;; ELSE SynError(88); END; END Statement; PROCEDURE ActualParams; VAR t: SymTab.TypeIndex; q: QbeGen.QVal; BEGIN Expr(t, q); WHILE (sym = 14) DO Get; Expr(t, q); END; END ActualParams; PROCEDURE Design (VAR t: SymTab.TypeIndex; VAR k: INTEGER; VAR q: QbeGen.QVal; VAR qn: SymTab.Name); VAR n: SymTab.Name; cls: INTEGER; BEGIN GetIdent(n); QbeGen.CopyOp(n, qn); IF ~SymTab.Lookup(n) THEN SemError(201); t := SymTab.InvalidType; k := -1; QbeGen.CopyOp("0", q) ELSE t := SymTab.SymType(n); k := SymTab.SymKind(n); IF k = SymTab.KindConst THEN IF SymTab.Equal(n, "TRUE") THEN t := SymTab.BoolType(); QbeGen.CopyOp("1", q) ELSIF SymTab.Equal(n, "FALSE") THEN t := SymTab.BoolType(); QbeGen.CopyOp("0", q) ELSE cls := SymTab.ClassOf(t); IF (t # SymTab.InvalidType) & ((cls = SymTab.ClInt) OR (cls = SymTab.ClChar) OR (cls = SymTab.ClReal)) THEN QbeGen.LoadVar(n, cls = SymTab.ClReal, q) ELSE IF t # SymTab.InvalidType THEN SemError(230) END; QbeGen.CopyOp("0", q) END END ELSIF (k = SymTab.KindVar) OR (k = SymTab.KindParam) THEN cls := SymTab.ClassOf(t); IF (cls = SymTab.ClInt) OR (cls = SymTab.ClBool) OR (cls = SymTab.ClChar) OR (cls = SymTab.ClReal) THEN QbeGen.LoadVar(n, cls = SymTab.ClReal, q) ELSE SemError(230); QbeGen.CopyOp("0", q) END ELSE QbeGen.CopyOp("0", q); IF (k = SymTab.KindImport) OR (k = SymTab.KindProc) OR (k = SymTab.KindField) THEN SemError(230) END END END;; END Design; PROCEDURE ParamSection; VAR t: SymTab.TypeIndex; isV: BOOLEAN; BEGIN isV := FALSE;; IF (sym = 38) THEN Get; isV := TRUE;; END; ParIdents(isV); Expect(32); Type(t); IF NOT SymTab.FixPending(t) THEN END;; END ParamSection; PROCEDURE FormalParams; BEGIN Expect(26); IF (sym = 1) OR (sym = 38) THEN ParamSection; WHILE (sym = 8) DO Get; ParamSection; END; END; Expect(27); END FormalParams; PROCEDURE ParIdents (isV: BOOLEAN); VAR n: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.EnterParam(n, isV) THEN SemError(200) END;; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.EnterParam(n, isV) THEN SemError(200) END;; END; END ParIdents; PROCEDURE VarIdents; VAR n: SymTab.Name; t: SymTab.TypeIndex; q: QbeGen.QVal; BEGIN GetIdent(n); IF ~SymTab.EnterPending(n, SymTab.KindVar) THEN SemError(200) END;; IF (sym = 15) THEN Get; Expr(t, q); SemError(230);; IF (sym = 32) THEN Get; Expr(t, q); SemError(230);; END; Expect(16); END; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.EnterPending(n, SymTab.KindVar) THEN SemError(200) END;; IF (sym = 15) THEN Get; Expr(t, q); SemError(230);; IF (sym = 32) THEN Get; Expr(t, q); SemError(230);; END; Expect(16); END; END; END VarIdents; PROCEDURE VarDecl; VAR nm: SymTab.Name; t: SymTab.TypeIndex; i: CARDINAL; cls: INTEGER; BEGIN VarIdents; Expect(32); Type(t); cls := SymTab.ClassOf(t); IF (t # SymTab.InvalidType) & (cls # SymTab.ClInt) & (cls # SymTab.ClBool) & (cls # SymTab.ClChar) & (cls # SymTab.ClReal) THEN SemError(230) END; i := 0; WHILE i < SymTab.PendCount() DO SymTab.PendName(i, nm); QbeGen.DeclVar(nm, t); INC(i) END; IF NOT SymTab.FixPending(t) THEN END;; END VarDecl; PROCEDURE Block (pn: SymTab.Name); VAR m2: SymTab.Name; BEGIN DeclSeq; IF (sym = 11) THEN Get; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(pn, m2) THEN SemError(202) END;; END Block; PROCEDURE MethodImpl (ct: SymTab.TypeIndex); VAR pn: SymTab.Name; BEGIN MethodHeading(pn); Expect(8); IF (ct # SymTab.InvalidType) & ~SymTab.MethodExists(ct, pn) THEN SemError(201) END;; IF (sym = 40) THEN Get; SymTab.MarkFwd; SymTab.CloseProc;; ELSIF In(symSet[5], sym) THEN Block(pn); SymTab.CloseProc; SemError(230);; ELSE SynError(89); END; END MethodImpl; PROCEDURE Parent1 (ct: SymTab.TypeIndex); VAR p: SymTab.Name; pt: SymTab.TypeIndex; BEGIN GetIdent(p); IF ~SymTab.Lookup(p) THEN SemError(201) ELSE pt := SymTab.SymType(p); IF SymTab.ClassOf(pt) # SymTab.ClClass THEN SemError(230) ELSE SymTab.SetParent(ct, pt) END END;; END Parent1; PROCEDURE MethodHeading (VAR pn: SymTab.Name); VAR wantVirt: BOOLEAN; BEGIN wantVirt := FALSE;; IF (sym = 23) THEN Get; wantVirt := TRUE;; END; ProcHeading(pn); IF wantVirt THEN SymTab.MarkVirtual END;; END MethodHeading; PROCEDURE ClassField (ct: SymTab.TypeIndex); VAR n, rhs: SymTab.Name; t: SymTab.TypeIndex; BEGIN GetIdent(n); IF (sym = 22) THEN Get; GetIdent(rhs); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; IF SymTab.Lookup(rhs) THEN SymTab.SetSymType(n, SymTab.SymType(rhs)) END;; ELSIF (sym = 14) OR (sym = 32) THEN IF ~SymTab.FieldPending(ct, n) THEN SemError(200) END;; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.FieldPending(ct, n) THEN SemError(200) END;; END; Expect(32); TypeIdent2(t); SymTab.FixPendingF(ct, t);; ELSE SynError(90); END; END ClassField; PROCEDURE Parents (ct: SymTab.TypeIndex); VAR p: SymTab.Name; BEGIN Expect(26); Parent1(ct); WHILE (sym = 14) DO Get; GetIdent(p); SemError(230);; END; Expect(27); END Parents; PROCEDURE ClassRest; VAR cn, m2, pn, q: SymTab.Name; ct: SymTab.TypeIndex; BEGIN GetIdent(cn); IF ~SymTab.Enter(cn, SymTab.KindType) THEN SemError(200) END; ct := SymTab.NewClass(); SymTab.SetSymType(cn, ct); SymTab.PushClassScope(ct);; IF (sym = 26) THEN Parents(ct); END; Expect(8); WHILE (sym = 1) DO ClassField(ct); Expect(8); END; WHILE (sym = 23) OR (sym = 37) DO MethodHeading(pn); Expect(8); IF (sym = 40) THEN Get; SymTab.MarkFwd; SymTab.CloseProc;; Expect(8); ELSIF (sym = 11) THEN Get; IF In(symSet[3], sym) THEN StatSeq; END; Expect(9); GetIdent(q); IF ~SymTab.Equal(pn, q) THEN SemError(202) END; SymTab.CloseProc; SemError(230);; Expect(8); ELSIF (sym = 9) OR (sym = 11) OR (sym = 23) OR (sym = 37) THEN SymTab.CloseProc;; ELSE SynError(91); END; END; IF (sym = 11) THEN Get; SemError(230);; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(cn, m2) THEN SemError(202) END; SymTab.PopScope; SemError(230);; END ClassRest; PROCEDURE ClassImplRest; VAR cn, m2: SymTab.Name; ct: SymTab.TypeIndex; BEGIN GetIdent(cn); IF ~SymTab.Lookup(cn) THEN SemError(201); ct := SymTab.InvalidType ELSE ct := SymTab.SymType(cn); IF SymTab.ClassOf(ct) # SymTab.ClClass THEN SemError(230); ct := SymTab.InvalidType END END; IF ct # SymTab.InvalidType THEN IF ~SymTab.PushClassMembers( ct) THEN SemError(230) END END;; Expect(8); WHILE (sym = 23) OR (sym = 37) DO MethodImpl(ct); Expect(8); END; IF (sym = 11) THEN Get; QbeGen.BeginBody;; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(cn, m2) THEN SemError(202) END; SymTab.PopScope; SemError(230);; END ClassImplRest; PROCEDURE ProcTypeParam; VAR b: SymTab.TypeIndex; BEGIN IF (sym = 38) THEN Get; END; Type(b); SemError(230);; END ProcTypeParam; PROCEDURE VariantLabel; VAR t1, t2: SymTab.TypeIndex; q1, q2: QbeGen.QVal; BEGIN Expr(t1, q1); SemError(230);; IF (sym = 25) THEN Get; Expr(t2, q2); SemError(230);; END; END VariantLabel; PROCEDURE VariantLabels; BEGIN VariantLabel; WHILE (sym = 14) DO Get; VariantLabel; END; END VariantLabels; PROCEDURE Variant (rec: SymTab.TypeIndex); BEGIN VariantLabels; Expect(32); SymTab.PushScope;; FieldListSequence(rec); SymTab.PopScope;; END Variant; PROCEDURE FieldIdents (rec: SymTab.TypeIndex); VAR n: SymTab.Name; t: SymTab.TypeIndex; BEGIN GetIdent(n); IF ~SymTab.FieldPending(rec, n) THEN SemError(200) END;; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.FieldPending(rec, n) THEN SemError(200) END;; END; Expect(32); Type(t); SymTab.FixPendingF(rec, t);; END FieldIdents; PROCEDURE VariantList (rec: SymTab.TypeIndex); BEGIN IF (sym = 33) THEN Get; END; Variant(rec); WHILE (sym = 33) DO Get; IF In(symSet[1], sym) THEN Variant(rec); END; END; IF (sym = 34) THEN Get; FieldListSequence(rec); END; END VariantList; PROCEDURE FieldList (rec: SymTab.TypeIndex); VAR tag: SymTab.Name; ti: SymTab.TypeIndex; BEGIN IF (sym = 31) THEN Get; SemError(230);; IF (sym = 1) THEN GetIdent(tag); Expect(32); (* named selector *); ELSIF (sym = 32) THEN Get; (* anonymous selector *); ELSIF In(symSet[6], sym) THEN (* no selector *); ELSE SynError(92); END; Type(ti); Expect(29); VariantList(rec); Expect(9); ELSIF (sym = 1) THEN FieldIdents(rec); ELSE SynError(93); END; END FieldList; PROCEDURE FieldListSequence (rec: SymTab.TypeIndex); BEGIN IF (sym = 1) OR (sym = 31) THEN FieldList(rec); WHILE (sym = 8) DO Get; IF (sym = 1) OR (sym = 31) THEN FieldList(rec); END; END; END; END FieldListSequence; PROCEDURE Bound; VAR t: SymTab.TypeIndex; q: QbeGen.QVal; BEGIN Expr(t, q); IF (sym = 25) THEN Get; Expr(t, q); END; SemError(230);; END Bound; PROCEDURE Expr (VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); VAR t2: SymTab.TypeIndex; op: INTEGER; q2, qt: QbeGen.QVal; isR: BOOLEAN; BEGIN SimExpr(t, q); IF In(symSet[7], sym) THEN IF In(symSet[8], sym) THEN Rel(op); SimExpr(t2, q2); IF SymTab.RelCheck(t, t2, op) THEN isR := SymTab.ClassOf(t) = SymTab.ClReal; t := SymTab.BoolType() ELSE SemError(213); t := SymTab.InvalidType; isR := FALSE END; IF t # SymTab.InvalidType THEN QbeGen.Cmp(op, q, q2, qt, isR); QbeGen.CopyOp(qt, q) ELSE QbeGen.CopyOp("0", q) END;; ELSIF (sym = 43) THEN Get; SimExpr(t2, q2); IF ~SymTab.InCheck(t, t2) THEN SemError(222) END; SemError(230); QbeGen.CopyOp("0", q); t := SymTab.InvalidType;; ELSE Get; TypeIdent2(t2); SemError(213); SemError(230); QbeGen.CopyOp("0", q); t := SymTab.InvalidType;; END; END; END Expr; PROCEDURE ProcType (VAR t: SymTab.TypeIndex); VAR b: SymTab.TypeIndex; BEGIN Expect(37); t := SymTab.InvalidType; SemError(230);; IF (sym = 26) THEN Get; IF In(symSet[9], sym) THEN ProcTypeParam; WHILE (sym = 14) DO Get; ProcTypeParam; END; END; Expect(27); END; IF (sym = 32) THEN Get; TypeIdent2(b); SemError(230);; END; END ProcType; PROCEDURE PointerType (VAR t: SymTab.TypeIndex); VAR b: SymTab.TypeIndex; BEGIN Expect(24); Expect(36); Type(b); t := SymTab.NewPtr(b); SemError(230);; END PointerType; PROCEDURE SetType (VAR t: SymTab.TypeIndex); VAR b: SymTab.TypeIndex; BEGIN Expect(35); Expect(29); IF (sym = 1) THEN TypeIdent2(b); t := SymTab.NewSet(b); SemError(230);; ELSIF (sym = 15) THEN Get; SubrangeRest(b); Expect(16); t := SymTab.NewSet(b); SemError(230);; ELSIF (sym = 26) THEN Enum(b); t := SymTab.NewSet(b); SemError(230);; ELSE SynError(94); END; END SetType; PROCEDURE RecordType (VAR t: SymTab.TypeIndex); VAR n: SymTab.Name; rt: SymTab.TypeIndex; BEGIN Expect(30); rt := SymTab.NewRecord(); t := rt;; FieldListSequence(rt); Expect(9); SemError(230);; END RecordType; PROCEDURE ArrayType (VAR t: SymTab.TypeIndex); VAR e: SymTab.TypeIndex; i: CARDINAL; BEGIN Expect(28); IF (sym = 15) THEN Get; Bound; WHILE (sym = 14) DO Get; Bound; END; Expect(16); t := SymTab.InvalidType;; ELSIF In(symSet[1], sym) THEN Bound; t := SymTab.InvalidType;; ELSIF (sym = 29) THEN t := SymTab.InvalidType;; ELSE SynError(95); END; Expect(29); Type(e); t := SymTab.NewOpenArray(e); SemError(230);; END ArrayType; PROCEDURE Enum (VAR t: SymTab.TypeIndex); VAR n: SymTab.Name; BEGIN Expect(26); t := SymTab.NewEnum();; GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; SymTab.SetSymType(n, t);; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; SymTab.SetSymType(n, t);; END; Expect(27); END Enum; PROCEDURE SubrangeRest (VAR t: SymTab.TypeIndex); VAR tlo, thi: SymTab.TypeIndex; qlo, qhi: QbeGen.QVal; lo, hi: INTEGER; BEGIN Expr(tlo, qlo); Expect(25); Expr(thi, qhi); IF (tlo = SymTab.InvalidType) OR (thi = SymTab.InvalidType) THEN t := SymTab.InvalidType ELSIF (SymTab.ClassOf(tlo) # SymTab.ClInt) OR (SymTab.ClassOf(thi) # SymTab.ClInt) THEN SemError(230); t := SymTab.InvalidType ELSIF ~SymTab.ConstInt(qlo, lo) OR ~SymTab.ConstInt(qhi, hi) OR (lo > hi) THEN SemError(230); t := SymTab.InvalidType ELSE t := SymTab.NewSubR(lo, hi) END;; END SubrangeRest; PROCEDURE TypeIdent2 (VAR t: SymTab.TypeIndex); VAR n: SymTab.Name; k: INTEGER; BEGIN GetIdent(n); IF ~SymTab.Lookup(n) THEN SemError(201); t := SymTab.InvalidType ELSE k := SymTab.SymKind(n); IF (k = SymTab.KindType) OR (k = SymTab.KindPredef) THEN t := SymTab.SymType(n) ELSIF k = SymTab.KindImport THEN t := SymTab.InvalidType ELSE SemError(221); t := SymTab.InvalidType END END;; WHILE (sym = 5) DO Get; GetIdent(n); SemError(230); t := SymTab.InvalidType;; END; END TypeIdent2; PROCEDURE Type (VAR t: SymTab.TypeIndex); BEGIN CASE sym OF 1 : TypeIdent2(t); IF (sym = 15) THEN Get; SubrangeRest(t); (* anchored subrange: SHORTINT[-1..1], SHORTCARD[0..7] *); Expect(16); END; | 15 : Get; SubrangeRest(t); Expect(16); | 26 : Enum(t); | 28 : ArrayType(t); | 30 : RecordType(t); | 35 : SetType(t); | 24 : PointerType(t); | 23 : Get; Expect(24); TypeIdent2(t); SemError(230);; | 37 : ProcType(t); ELSE SynError(96); END; END Type; PROCEDURE TypeItem (isDef: BOOLEAN); VAR n: SymTab.Name; t: SymTab.TypeIndex; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindType) THEN SemError(200) END;; IF (sym = 22) THEN Get; Type(t); SymTab.SetSymType(n, t);; ELSIF (sym = 8) THEN IF ~isDef THEN SemError(231) END; SymTab.SetSymType(n, SymTab.NewAlias());; ELSE SynError(97); END; END TypeItem; PROCEDURE ImpList; VAR n: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END;; WHILE (sym = 14) DO Get; GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END;; END; END ImpList; PROCEDURE Export; VAR nm: SymTab.Name; BEGIN Expect(17); IF (sym = 18) THEN Get; END; GetIdent(nm); WHILE (sym = 14) DO Get; GetIdent(nm); END; Expect(8); END Export; PROCEDURE LabelList; VAR nm: SymTab.Name; BEGIN GetIdent(nm); SemError(230);; WHILE (sym = 14) DO Get; GetIdent(nm); SemError(230);; END; END LabelList; PROCEDURE NestedModule; VAR m1, m2: SymTab.Name; BEGIN Expect(7); GetIdent(m1); IF ~SymTab.Enter(m1, SymTab.KindModule) THEN SemError(200) END; SymTab.PushScope;; IF (sym = 15) THEN Priority; END; Expect(8); WHILE (sym = 19) OR (sym = 20) DO Import; END; IF (sym = 17) THEN Export; END; DeclSeq; IF (sym = 11) THEN Get; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(m1, m2) THEN SemError(202) END; SymTab.PopScope; SemError(230);; END NestedModule; PROCEDURE ProcDecl; VAR pn, assem: SymTab.Name; at: SymTab.TypeIndex; ak: INTEGER; aq: QbeGen.QVal; BEGIN ProcHeading(pn); IF (sym = 8) THEN Get; IF (sym = 40) THEN Get; SymTab.MarkFwd; SymTab.CloseProc;; ELSIF (sym = 43) THEN Get; GetIdent(assem); SymTab.CloseProc; SemError(230);; ELSIF In(symSet[5], sym) THEN Block(pn); SymTab.CloseProc; SemError(230);; ELSE SynError(98); END; ELSIF (sym = 22) THEN Get; Design(at, ak, aq, assem); SymTab.CloseProc; SemError(230);; Expect(26); IF In(symSet[1], sym) THEN ActualParams; END; Expect(27); ELSE SynError(99); END; END ProcDecl; PROCEDURE Priority; BEGIN Expect(15); Expect(2); Expect(16); SemError(230);; END Priority; PROCEDURE StatSeq; BEGIN Statement; WHILE (sym = 8) DO Get; IF In(symSet[3], sym) THEN Statement; END; END; END StatSeq; PROCEDURE DeclSeq; BEGIN WHILE In(symSet[10], sym) DO CASE sym OF 41 : ConstBlock; | 21 : TypeBlock(FALSE); | 38 : VarBlock; | 1 : ConstDecl; Expect(8); (* manifest const, no CONST *); | 12, 37 : IF (sym = 12) THEN Get; END; ProcDecl; Expect(8); | 7 : NestedModule; Expect(8); | 39 : ClassItem; Expect(8); | 13 : Get; LabelList; Expect(8); END; END; END DeclSeq; PROCEDURE ClassItem; BEGIN Expect(39); IF (sym = 10) THEN Get; ClassImplRest; ELSIF (sym = 1) THEN ClassRest; ELSE SynError(100); END; END ClassItem; PROCEDURE ProcHeading (VAR pn: SymTab.Name); VAR t: SymTab.TypeIndex; BEGIN Expect(37); GetIdent(pn); IF ~SymTab.EnterProc(pn) THEN IF ~SymTab.ReenterProc(pn) THEN SemError(200) END END;; IF (sym = 26) THEN FormalParams; END; IF (sym = 32) THEN Get; TypeIdent2(t); IF NOT SymTab.SetProcRes(t) THEN END;; END; END ProcHeading; PROCEDURE ConstDecl; VAR n: SymTab.Name; t: SymTab.TypeIndex; qv: QbeGen.QVal; cls: INTEGER; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END;; IF (sym = 42) THEN Get; SemError(230);; Expr(t, qv); SymTab.SetSymType(n, t); QbeGen.DeclConst(n, "0", SymTab.InvalidType);; ELSIF (sym = 22) THEN Get; Expr(t, qv); SymTab.SetSymType(n, t); cls := SymTab.ClassOf(t); IF cls = SymTab.ClStr THEN SemError(230) ELSIF ~QbeGen.IsImm(qv) THEN SemError(230) END; QbeGen.DeclConst(n, qv, t);; ELSE SynError(101); END; END ConstDecl; PROCEDURE VarBlock; BEGIN Expect(38); WHILE (sym = 1) DO VarDecl; Expect(8); END; END VarBlock; PROCEDURE TypeBlock (isDef: BOOLEAN); BEGIN Expect(21); WHILE (sym = 1) OR (sym = 39) DO IF (sym = 1) THEN TypeItem(isDef); Expect(8); ELSE ClassItem; Expect(8); END; END; END TypeBlock; PROCEDURE ConstBlock; BEGIN Expect(41); WHILE (sym = 1) DO ConstDecl; Expect(8); END; END ConstBlock; PROCEDURE Import; VAR n: SymTab.Name; BEGIN IF (sym = 19) THEN Get; GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END;; Expect(20); ImpList; Expect(8); ELSIF (sym = 20) THEN Get; ImpList; Expect(8); ELSE SynError(102); END; END Import; PROCEDURE GetIdent (VAR n: SymTab.Name); BEGIN Expect(1); LexName(n);; END GetIdent; PROCEDURE ProgModule; VAR m1, m2: SymTab.Name; BEGIN Expect(7); GetIdent(m1); SymTab.Init; QbeGen.OpenModule(m1); IF ~SymTab.Enter(m1, SymTab.KindModule) THEN SemError(200) END;; IF (sym = 15) THEN Priority; END; Expect(8); WHILE (sym = 19) OR (sym = 20) DO Import; END; DeclSeq; IF (sym = 11) THEN Get; QbeGen.BeginBody;; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(m1, m2) THEN SemError(202) END;; QbeGen.EndModule(m1); SymTab.PrintTable;; END ProgModule; PROCEDURE ImplUnit; VAR m1, m2: SymTab.Name; BEGIN Expect(10); Expect(7); GetIdent(m1); SymTab.Init; QbeGen.OpenModule(m1); IF ~SymTab.Enter(m1, SymTab.KindModule) THEN SemError(200) END;; Expect(8); WHILE (sym = 19) OR (sym = 20) DO Import; END; DeclSeq; IF (sym = 11) THEN Get; QbeGen.BeginBody;; IF In(symSet[3], sym) THEN StatSeq; END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(m1, m2) THEN SemError(202) END;; QbeGen.CloseModule; SemError(230); SymTab.PrintTable;; END ImplUnit; PROCEDURE DefUnit; VAR m1, m2, pn: SymTab.Name; BEGIN Expect(6); Expect(7); GetIdent(m1); SymTab.Init; QbeGen.OpenModule(m1); IF ~SymTab.Enter(m1, SymTab.KindModule) THEN SemError(200) END;; Expect(8); WHILE (sym = 19) OR (sym = 20) DO Import; END; WHILE In(symSet[11], sym) DO CASE sym OF 41 : ConstBlock; | 21 : TypeBlock(TRUE); | 38 : VarBlock; | 1 : ConstDecl; Expect(8); (* manifest const, no CONST *); | 37 : ProcHeading(pn); Expect(8); SymTab.CloseProc;; | 39 : ClassItem; Expect(8); END; END; Expect(9); GetIdent(m2); IF ~SymTab.Equal(m1, m2) THEN SemError(202) END;; QbeGen.CloseModule; SemError(230); SymTab.PrintTable;; END DefUnit; PROCEDURE Unit; BEGIN IF (sym = 6) THEN DefUnit; ELSIF (sym = 10) THEN ImplUnit; ELSIF (sym = 7) THEN ProgModule; ELSE SynError(103); END; END Unit; PROCEDURE M2; BEGIN Unit; Expect(5); END M2; PROCEDURE Parse; BEGIN M2S.Reset; Get; M2; END Parse; BEGIN errDist := minErrDist; symSet[ 0, 0] := BITSET{0}; symSet[ 0, 1] := BITSET{}; symSet[ 0, 2] := BITSET{}; symSet[ 0, 3] := BITSET{}; symSet[ 0, 4] := BITSET{}; symSet[ 0, 5] := BITSET{}; symSet[ 1, 0] := BITSET{1, 2, 3, 4, 15}; symSet[ 1, 1] := BITSET{10}; symSet[ 1, 2] := BITSET{}; symSet[ 1, 3] := BITSET{}; symSet[ 1, 4] := BITSET{3, 4, 14}; symSet[ 1, 5] := BITSET{0, 1}; symSet[ 2, 0] := BITSET{}; symSet[ 2, 1] := BITSET{}; symSet[ 2, 2] := BITSET{}; symSet[ 2, 3] := BITSET{}; symSet[ 2, 4] := BITSET{6, 7, 8, 9, 10, 11, 12, 13}; symSet[ 2, 5] := BITSET{}; symSet[ 3, 0] := BITSET{1}; symSet[ 3, 1] := BITSET{15}; symSet[ 3, 2] := BITSET{12, 13, 15}; symSet[ 3, 3] := BITSET{2, 4, 6, 7, 9, 10}; symSet[ 3, 4] := BITSET{}; symSet[ 3, 5] := BITSET{}; symSet[ 4, 0] := BITSET{1, 2, 3, 4, 8, 9, 15}; symSet[ 4, 1] := BITSET{10}; symSet[ 4, 2] := BITSET{1, 2}; symSet[ 4, 3] := BITSET{1, 5}; symSet[ 4, 4] := BITSET{3, 4, 14}; symSet[ 4, 5] := BITSET{0, 1}; symSet[ 5, 0] := BITSET{1, 7, 9, 11, 12, 13}; symSet[ 5, 1] := BITSET{5}; symSet[ 5, 2] := BITSET{5, 6, 7, 9}; symSet[ 5, 3] := BITSET{}; symSet[ 5, 4] := BITSET{}; symSet[ 5, 5] := BITSET{}; symSet[ 6, 0] := BITSET{1, 15}; symSet[ 6, 1] := BITSET{7, 8, 10, 12, 14}; symSet[ 6, 2] := BITSET{3, 5}; symSet[ 6, 3] := BITSET{}; symSet[ 6, 4] := BITSET{}; symSet[ 6, 5] := BITSET{}; symSet[ 7, 0] := BITSET{}; symSet[ 7, 1] := BITSET{6}; symSet[ 7, 2] := BITSET{11}; symSet[ 7, 3] := BITSET{12, 13, 14, 15}; symSet[ 7, 4] := BITSET{0, 1, 2}; symSet[ 7, 5] := BITSET{}; symSet[ 8, 0] := BITSET{}; symSet[ 8, 1] := BITSET{6}; symSet[ 8, 2] := BITSET{}; symSet[ 8, 3] := BITSET{13, 14, 15}; symSet[ 8, 4] := BITSET{0, 1, 2}; symSet[ 8, 5] := BITSET{}; symSet[ 9, 0] := BITSET{1, 15}; symSet[ 9, 1] := BITSET{7, 8, 10, 12, 14}; symSet[ 9, 2] := BITSET{3, 5, 6}; symSet[ 9, 3] := BITSET{}; symSet[ 9, 4] := BITSET{}; symSet[ 9, 5] := BITSET{}; symSet[10, 0] := BITSET{1, 7, 12, 13}; symSet[10, 1] := BITSET{5}; symSet[10, 2] := BITSET{5, 6, 7, 9}; symSet[10, 3] := BITSET{}; symSet[10, 4] := BITSET{}; symSet[10, 5] := BITSET{}; symSet[11, 0] := BITSET{1}; symSet[11, 1] := BITSET{5}; symSet[11, 2] := BITSET{5, 6, 7, 9}; symSet[11, 3] := BITSET{}; symSet[11, 4] := BITSET{}; symSet[11, 5] := BITSET{}; END M2P.