IMPLEMENTATION MODULE SimpleMP; (* Parser generated by Coco/R - assuming ISO IO library will be available. *) IMPORT SimpleMS, FileIO; IMPORT SymTab, CodeGen; CONST maxT = 66; 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 .. 4] 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 SimpleMS.Error(errNo, SimpleMS.line, SimpleMS.col, SimpleMS.pos); END; errDist := 0; END SemError; PROCEDURE SynError (errNo: INTEGER); BEGIN IF errDist >= minErrDist THEN SimpleMS.Error(errNo, SimpleMS.nextLine, SimpleMS.nextCol, SimpleMS.nextPos); END; errDist := 0; END SynError; PROCEDURE Get; VAR s: ARRAY [0 .. 31] OF CHAR; BEGIN REPEAT SimpleMS.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 ~ 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 ~ In(s, sym) DO Get END; RETURN In(symSet[syFol], sym) END END WeakSeparator; PROCEDURE LexName (VAR Lex: ARRAY OF CHAR); BEGIN SimpleMS.GetName(SimpleMS.pos, SimpleMS.len, Lex) END LexName; PROCEDURE LexString (VAR Lex: ARRAY OF CHAR); BEGIN SimpleMS.GetString(SimpleMS.pos, SimpleMS.len, Lex) END LexString; PROCEDURE LookAheadName (VAR Lex: ARRAY OF CHAR); BEGIN SimpleMS.GetName(SimpleMS.nextPos, SimpleMS.nextLen, Lex) END LookAheadName; PROCEDURE LookAheadString (VAR Lex: ARRAY OF CHAR); BEGIN SimpleMS.GetString(SimpleMS.nextPos, SimpleMS.nextLen, Lex) END LookAheadString; PROCEDURE Successful (): BOOLEAN; BEGIN RETURN SimpleMS.errors = 0 END Successful; (* ----- FORWARD not needed in multipass compilers PROCEDURE Elem (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE SetLit (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE MulOp (VAR op: INTEGER); FORWARD; PROCEDURE Fact (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE AddOp (VAR op: INTEGER); FORWARD; PROCEDURE Term (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE Rel (VAR op: INTEGER); FORWARD; PROCEDURE SimExpr (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE Labels (sel: SymTab.TypeIndex); FORWARD; PROCEDURE LabelList (sel: SymTab.TypeIndex); FORWARD; PROCEDURE Case (sel: SymTab.TypeIndex); FORWARD; PROCEDURE Design (VAR t: SymTab.TypeIndex; VAR k: INTEGER); FORWARD; PROCEDURE WithStat; FORWARD; PROCEDURE ForStat; FORWARD; PROCEDURE LoopStat; FORWARD; PROCEDURE RepeatStat; FORWARD; PROCEDURE WhileStat; FORWARD; PROCEDURE CaseStat; FORWARD; PROCEDURE IfStat; FORWARD; PROCEDURE Assign; FORWARD; PROCEDURE Stat; FORWARD; PROCEDURE FieldIdents (rt: SymTab.TypeIndex); FORWARD; PROCEDURE Field (rt: SymTab.TypeIndex); FORWARD; PROCEDURE FieldSeq (rt: SymTab.TypeIndex); FORWARD; PROCEDURE Enum (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 SimpleType (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE QualIdent (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE VarIdents; FORWARD; PROCEDURE Type (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE Expr (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE ConstExpr (VAR t: SymTab.TypeIndex); FORWARD; PROCEDURE VarDecl; FORWARD; PROCEDURE TypeDecl; FORWARD; PROCEDURE ConstDecl; FORWARD; PROCEDURE StatSeq; FORWARD; PROCEDURE Declaration; FORWARD; PROCEDURE ImportList; FORWARD; PROCEDURE Block; FORWARD; PROCEDURE Import; FORWARD; PROCEDURE GetIdent (VAR n: SymTab.Name); FORWARD; PROCEDURE SimpleMod2; FORWARD; ----- *) PROCEDURE Elem (VAR t: SymTab.TypeIndex); VAR t2: SymTab.TypeIndex; BEGIN Expr(t); IF (sym = 19) THEN Get; CodeGen.Emit(".."); Expr(t2); IF ~SymTab.SetElemCheck(t, t2) THEN SemError(222) END;; END; END Elem; PROCEDURE SetLit (VAR t: SymTab.TypeIndex); VAR first, et: SymTab.TypeIndex; BEGIN Expect(64); CodeGen.Emit("{"); t := SymTab.SetFor(SymTab.IntType());; IF In(symSet[1], sym) THEN Elem(et); first := et; t := SymTab.SetFor(et);; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); Elem(et); IF ~SymTab.SetElemCheck(first, et) THEN SemError(222) END;; END; END; Expect(65); CodeGen.Emit("}"); END SetLit; PROCEDURE MulOp (VAR op: INTEGER); BEGIN CASE sym OF 56 : Get; CodeGen.Emit(" * "); op := SymTab.OpTimes;; | 57 : Get; CodeGen.Emit(" / "); op := SymTab.OpSlash;; | 58 : Get; CodeGen.Emit(" DIV "); op := SymTab.OpDiv;; | 59 : Get; CodeGen.Emit(" MOD "); op := SymTab.OpMod;; | 60 : Get; CodeGen.Emit(" AND "); op := SymTab.OpAnd;; | 61 : Get; CodeGen.Emit(" & "); op := SymTab.OpAnd;; ELSE SynError(67); END; END MulOp; PROCEDURE Fact (VAR t: SymTab.TypeIndex); VAR s: ARRAY [0 .. 255] OF CHAR; t2, et, dt, st: SymTab.TypeIndex; dk: INTEGER; BEGIN CASE sym OF 2 : Get; LexString(s); CodeGen.Emit(s); t := SymTab.IntType();; | 3 : Get; LexString(s); CodeGen.Emit(s); t := SymTab.RealType();; | 4 : Get; LexString(s); CodeGen.Emit(s); IF SymTab.StrLen(s) <= 3 THEN t := SymTab.CharType() ELSE t := SymTab.NewStr() END;; | 1 : Design(dt, dk); t := dt;; | 21 : Get; CodeGen.Emit("("); Expr(et); Expect(22); CodeGen.Emit(")"); t := et;; | 62, 63 : IF (sym = 62) THEN Get; CodeGen.Emit("NOT "); ELSE Get; CodeGen.Emit("~"); END; Fact(t2); IF SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END;; | 64 : SetLit(st); t := st;; ELSE SynError(68); END; END Fact; PROCEDURE AddOp (VAR op: INTEGER); BEGIN IF (sym = 53) THEN Get; CodeGen.Emit(" + "); op := SymTab.OpAdd;; ELSIF (sym = 54) THEN Get; CodeGen.Emit(" - "); op := SymTab.OpSub;; ELSIF (sym = 55) THEN Get; CodeGen.Emit(" OR "); op := SymTab.OpOr;; ELSE SynError(69); END; END AddOp; PROCEDURE Term (VAR t: SymTab.TypeIndex); VAR t2, res2: SymTab.TypeIndex; op: INTEGER; BEGIN Fact(t); WHILE In(symSet[2], sym) DO MulOp(op); Fact(t2); IF op = SymTab.OpAnd THEN IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType 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 END;; END; END Term; PROCEDURE Rel (VAR op: INTEGER); BEGIN CASE sym OF 16 : Get; CodeGen.Emit(" = "); op := SymTab.OpEq;; | 46 : Get; CodeGen.Emit(" # "); op := SymTab.OpNeq1;; | 47 : Get; CodeGen.Emit(" <> "); op := SymTab.OpNeq2;; | 48 : Get; CodeGen.Emit(" < "); op := SymTab.OpLt;; | 49 : Get; CodeGen.Emit(" <= "); op := SymTab.OpLe;; | 50 : Get; CodeGen.Emit(" > "); op := SymTab.OpGt;; | 51 : Get; CodeGen.Emit(" >= "); op := SymTab.OpGe;; | 52 : Get; CodeGen.Emit(" IN "); op := SymTab.OpIn;; ELSE SynError(70); END; END Rel; PROCEDURE SimExpr (VAR t: SymTab.TypeIndex); VAR t2, res2: SymTab.TypeIndex; op: INTEGER; BEGIN IF (sym = 53) OR (sym = 54) THEN IF (sym = 53) THEN Get; CodeGen.Emit("+"); ELSE Get; CodeGen.Emit("-"); END; END; Term(t); WHILE (sym = 53) OR (sym = 54) OR (sym = 55) DO AddOp(op); Term(t2); IF op = SymTab.OpOr THEN IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN t := SymTab.BoolType() ELSE SemError(212); t := SymTab.InvalidType END ELSE IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2 ELSE SemError(211); t := SymTab.InvalidType END END;; END; END SimExpr; PROCEDURE Labels (sel: SymTab.TypeIndex); VAR t, t2: SymTab.TypeIndex; BEGIN ConstExpr(t); IF ~SymTab.EqCheck(t, sel) THEN SemError(213) END;; IF (sym = 19) THEN Get; CodeGen.Emit(".."); ConstExpr(t2); IF ~SymTab.EqCheck(t2, sel) THEN SemError(213) END;; END; END Labels; PROCEDURE LabelList (sel: SymTab.TypeIndex); BEGIN Labels(sel); WHILE (sym = 10) DO Get; CodeGen.Emit(", "); Labels(sel); END; END LabelList; PROCEDURE Case (sel: SymTab.TypeIndex); BEGIN IF In(symSet[1], sym) THEN LabelList(sel); Expect(17); CodeGen.Emit(" : "); StatSeq; END; END Case; PROCEDURE Design (VAR t: SymTab.TypeIndex; VAR k: INTEGER); VAR n, m: SymTab.Name; it: SymTab.TypeIndex; BEGIN GetIdent(n); IF ~SymTab.Lookup(n) THEN SemError(201); t := SymTab.InvalidType; k := -1 ELSE t := SymTab.SymType(n); k := SymTab.SymKind(n) END;; WHILE (sym = 7) OR (sym = 18) OR (sym = 45) DO IF (sym = 7) THEN Get; CodeGen.Emit("."); GetIdent(m); IF t = SymTab.InvalidType THEN ELSIF SymTab.ClassOf(t) # SymTab.ClRecord THEN SemError(215); t := SymTab.InvalidType ELSIF ~SymTab.FieldExists(t, m) THEN SemError(216); t := SymTab.InvalidType ELSE t := SymTab.FieldType(t, m) END;; ELSIF (sym = 18) THEN Get; CodeGen.Emit("["); Expr(it); IF t = SymTab.InvalidType THEN ELSIF SymTab.ClassOf(t) # SymTab.ClArray THEN SemError(217); t := SymTab.InvalidType ELSIF (it # SymTab.InvalidType) & ~SymTab.IsIntFamily(it) THEN SemError(218); t := SymTab.InvalidType ELSE t := SymTab.ArrayElem(t) END;; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); Expr(it); IF (it # SymTab.InvalidType) & ~SymTab.IsIntFamily(it) THEN SemError(218) END;; END; Expect(20); CodeGen.Emit("]"); ELSE Get; CodeGen.Emit("^"); IF t = SymTab.InvalidType THEN ELSIF SymTab.ClassOf(t) # SymTab.ClPtr THEN SemError(219); t := SymTab.InvalidType ELSE t := SymTab.PtrBase(t) END;; END; END; END Design; PROCEDURE WithStat; VAR dt: SymTab.TypeIndex; dk: INTEGER; pushed: BOOLEAN; BEGIN Expect(44); CodeGen.Emit("WITH "); Design(dt, dk); pushed := FALSE; IF dt # SymTab.InvalidType THEN pushed := SymTab.PushRecord(dt); IF ~pushed THEN SemError(215) END END;; Expect(38); CodeGen.Emit(" DO"); CodeGen.Brk; CodeGen.Ind;; StatSeq; Expect(12); IF pushed THEN SymTab.PopScope END; CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END WithStat; PROCEDURE ForStat; VAR n: SymTab.Name; lo, hi, by: SymTab.TypeIndex; BEGIN Expect(42); CodeGen.Emit("FOR "); GetIdent(n); IF ~SymTab.Lookup(n) THEN SemError(201) ELSIF (SymTab.SymKind(n) # SymTab.KindVar) & (SymTab.SymKind(n) # SymTab.KindField) THEN SemError(220) ELSIF (SymTab.SymType(n) # SymTab.InvalidType) & ~SymTab.IsIntFamily( SymTab.SymType(n)) THEN SemError(220) END;; Expect(30); CodeGen.Emit(" := "); Expr(lo); IF (lo # SymTab.InvalidType) & ~SymTab.IsIntFamily(lo) THEN SemError(220) END;; Expect(28); CodeGen.Emit(" TO "); Expr(hi); IF (hi # SymTab.InvalidType) & ~SymTab.IsIntFamily(hi) THEN SemError(220) END;; IF (sym = 43) THEN Get; CodeGen.Emit(" BY "); ConstExpr(by); IF (by # SymTab.InvalidType) & ~SymTab.IsIntFamily(by) THEN SemError(220) END;; END; Expect(38); CodeGen.Emit(" DO"); CodeGen.Brk; CodeGen.Ind;; StatSeq; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END ForStat; PROCEDURE LoopStat; BEGIN Expect(41); CodeGen.Emit("LOOP"); CodeGen.Brk; CodeGen.Ind;; StatSeq; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END LoopStat; PROCEDURE RepeatStat; VAR t: SymTab.TypeIndex; BEGIN Expect(39); CodeGen.Emit("REPEAT"); CodeGen.Brk; CodeGen.Ind;; StatSeq; Expect(40); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("UNTIL "); Expr(t); IF ~SymTab.BoolCheck(t) THEN SemError(214) END;; END RepeatStat; PROCEDURE WhileStat; VAR t: SymTab.TypeIndex; BEGIN Expect(37); CodeGen.Emit("WHILE "); Expr(t); IF ~SymTab.BoolCheck(t) THEN SemError(214) END;; Expect(38); CodeGen.Emit(" DO"); CodeGen.Brk; CodeGen.Ind;; StatSeq; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END WhileStat; PROCEDURE CaseStat; VAR st: SymTab.TypeIndex; BEGIN Expect(35); CodeGen.Emit("CASE "); Expr(st); Expect(24); CodeGen.Emit(" OF"); CodeGen.Brk; CodeGen.Ind;; Case(st); WHILE (sym = 36) DO Get; CodeGen.Brk; CodeGen.Emit("| "); Case(st); END; IF (sym = 34) THEN Get; CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("ELSE "); CodeGen.Ind; CodeGen.Brk;; StatSeq; END; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END CaseStat; PROCEDURE IfStat; VAR t: SymTab.TypeIndex; BEGIN Expect(31); CodeGen.Emit("IF "); Expr(t); IF ~SymTab.BoolCheck(t) THEN SemError(214) END;; Expect(32); CodeGen.Emit(" THEN"); CodeGen.Brk; CodeGen.Ind;; StatSeq; WHILE (sym = 33) DO Get; CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("ELSIF "); Expr(t); IF ~SymTab.BoolCheck(t) THEN SemError(214) END;; Expect(32); CodeGen.Emit(" THEN"); CodeGen.Brk; CodeGen.Ind;; StatSeq; END; IF (sym = 34) THEN Get; CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("ELSE"); CodeGen.Ind; CodeGen.Brk;; StatSeq; END; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END IfStat; PROCEDURE Assign; VAR dt, et: SymTab.TypeIndex; dk: INTEGER; BEGIN Design(dt, dk); Expect(30); CodeGen.Emit(" := "); Expr(et); IF (dt # SymTab.InvalidType) & (dk # SymTab.KindVar) & (dk # SymTab.KindField) & (dk # SymTab.KindImport) THEN SemError(210) ELSIF ~SymTab.Assignable(et, dt) THEN SemError(210) END;; END Assign; PROCEDURE Stat; BEGIN IF In(symSet[3], sym) THEN CASE sym OF 1 : Assign; | 31 : IfStat; | 35 : CaseStat; | 37 : WhileStat; | 39 : RepeatStat; | 41 : LoopStat; | 42 : ForStat; | 44 : WithStat; | 29 : Get; CodeGen.Emit("EXIT"); END; END; END Stat; PROCEDURE FieldIdents (rt: SymTab.TypeIndex); VAR n: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.FieldPending(rt, n) THEN SemError(200) END; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); GetIdent(n); IF ~SymTab.FieldPending(rt, n) THEN SemError(200) END; END; END FieldIdents; PROCEDURE Field (rt: SymTab.TypeIndex); VAR et: SymTab.TypeIndex; BEGIN IF (sym = 1) THEN FieldIdents(rt); Expect(17); CodeGen.Emit(" : "); Type(et); SymTab.FixPendingF(rt, et);; END; END Field; PROCEDURE FieldSeq (rt: SymTab.TypeIndex); BEGIN Field(rt); WHILE (sym = 6) DO Get; CodeGen.Emit(";"); CodeGen.Brk;; Field(rt); END; END FieldSeq; PROCEDURE Enum (VAR t: SymTab.TypeIndex); VAR n: SymTab.Name; BEGIN Expect(21); CodeGen.Emit("("); t := SymTab.NewEnum();; GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; SymTab.SetSymType(n, t);; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; SymTab.SetSymType(n, t);; END; Expect(22); CodeGen.Emit(")"); END Enum; PROCEDURE PointerType (VAR t: SymTab.TypeIndex); VAR b: SymTab.TypeIndex; BEGIN Expect(27); CodeGen.Emit("POINTER "); Expect(28); CodeGen.Emit("TO "); Type(b); t := SymTab.NewPtr(b);; END PointerType; PROCEDURE SetType (VAR t: SymTab.TypeIndex); VAR s: SymTab.TypeIndex; BEGIN Expect(26); CodeGen.Emit("SET "); Expect(24); CodeGen.Emit("OF "); SimpleType(s); IF (s # SymTab.InvalidType) & (SymTab.ClassOf(s) # SymTab.ClInt) & (SymTab.ClassOf(s) # SymTab.ClChar) & (SymTab.ClassOf(s) # SymTab.ClEnum) THEN SemError(224) END; t := SymTab.NewSet(s);; END SetType; PROCEDURE RecordType (VAR t: SymTab.TypeIndex); BEGIN Expect(25); CodeGen.Emit("RECORD"); CodeGen.Ind; CodeGen.Brk; t := SymTab.NewRecord();; FieldSeq(t); Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END"); END RecordType; PROCEDURE ArrayType (VAR t: SymTab.TypeIndex); VAR s, s2, e: SymTab.TypeIndex; BEGIN Expect(23); CodeGen.Emit("ARRAY "); SimpleType(s); IF (s # SymTab.InvalidType) & (SymTab.ClassOf(s) # SymTab.ClInt) & (SymTab.ClassOf(s) # SymTab.ClChar) & (SymTab.ClassOf(s) # SymTab.ClEnum) THEN SemError(224) END;; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); SimpleType(s2); IF (s2 # SymTab.InvalidType) & (SymTab.ClassOf(s2) # SymTab.ClInt) & (SymTab.ClassOf(s2) # SymTab.ClChar) & (SymTab.ClassOf(s2) # SymTab.ClEnum) THEN SemError(224) END;; END; Expect(24); CodeGen.Emit(" OF "); Type(e); t := SymTab.NewArray(e);; END ArrayType; PROCEDURE SimpleType (VAR t: SymTab.TypeIndex); VAR t1, t2: SymTab.TypeIndex; BEGIN IF (sym = 1) THEN QualIdent(t); IF (sym = 18) THEN Get; CodeGen.Emit("["); ConstExpr(t1); IF (t1 # SymTab.InvalidType) & (SymTab.ClassOf(t1) # SymTab.ClInt) & (SymTab.ClassOf(t1) # SymTab.ClChar) & (SymTab.ClassOf(t1) # SymTab.ClEnum) THEN SemError(224) END;; Expect(19); CodeGen.Emit(".."); ConstExpr(t2); IF (t2 # SymTab.InvalidType) & (SymTab.ClassOf(t2) # SymTab.ClInt) & (SymTab.ClassOf(t2) # SymTab.ClChar) & (SymTab.ClassOf(t2) # SymTab.ClEnum) THEN SemError(224) END;; Expect(20); CodeGen.Emit("]"); t := SymTab.NewSub(t1);; END; ELSIF (sym = 18) THEN Get; CodeGen.Emit("["); ConstExpr(t1); IF (t1 # SymTab.InvalidType) & (SymTab.ClassOf(t1) # SymTab.ClInt) & (SymTab.ClassOf(t1) # SymTab.ClChar) & (SymTab.ClassOf(t1) # SymTab.ClEnum) THEN SemError(224) END;; Expect(19); CodeGen.Emit(".."); ConstExpr(t2); IF (t2 # SymTab.InvalidType) & (SymTab.ClassOf(t2) # SymTab.ClInt) & (SymTab.ClassOf(t2) # SymTab.ClChar) & (SymTab.ClassOf(t2) # SymTab.ClEnum) THEN SemError(224) END;; Expect(20); CodeGen.Emit("]"); t := SymTab.NewSub(t1);; ELSIF (sym = 21) THEN Enum(t); ELSE SynError(71); END; END SimpleType; PROCEDURE QualIdent (VAR t: SymTab.TypeIndex); VAR n, m: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.Lookup(n) THEN SemError(201); t := SymTab.InvalidType ELSIF (SymTab.SymKind(n) # SymTab.KindType) & (SymTab.SymKind(n) # SymTab.KindPredef) & (SymTab.SymKind(n) # SymTab.KindImport) THEN SemError(221); t := SymTab.InvalidType ELSE t := SymTab.SymType(n) END;; WHILE (sym = 7) DO Get; CodeGen.Emit("."); t := SymTab.InvalidType;; GetIdent(m); END; END QualIdent; PROCEDURE VarIdents; VAR n: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.EnterPending(n, SymTab.KindVar) THEN SemError(200) END; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); GetIdent(n); IF ~SymTab.EnterPending(n, SymTab.KindVar) THEN SemError(200) END; END; END VarIdents; PROCEDURE Type (VAR t: SymTab.TypeIndex); BEGIN IF (sym = 1) OR (sym = 18) OR (sym = 21) THEN SimpleType(t); ELSIF (sym = 23) THEN ArrayType(t); ELSIF (sym = 25) THEN RecordType(t); ELSIF (sym = 26) THEN SetType(t); ELSIF (sym = 27) THEN PointerType(t); ELSE SynError(72); END; END Type; PROCEDURE Expr (VAR t: SymTab.TypeIndex); VAR t2: SymTab.TypeIndex; op: INTEGER; BEGIN SimExpr(t); IF In(symSet[4], sym) THEN Rel(op); SimExpr(t2); IF op = SymTab.OpIn THEN IF SymTab.InCheck(t, t2) THEN t := SymTab.BoolType() ELSE SemError(222); t := SymTab.InvalidType END ELSE IF SymTab.RelCheck(t, t2, op) THEN t := SymTab.BoolType() ELSE SemError(213); t := SymTab.InvalidType END END;; END; END Expr; PROCEDURE ConstExpr (VAR t: SymTab.TypeIndex); BEGIN Expr(t); END ConstExpr; PROCEDURE VarDecl; VAR t: SymTab.TypeIndex; BEGIN VarIdents; Expect(17); CodeGen.Emit(" : "); Type(t); SymTab.FixPending(t);; END VarDecl; PROCEDURE TypeDecl; VAR n: SymTab.Name; t0, t1: SymTab.TypeIndex; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindType) THEN SemError(200) END; t0 := SymTab.NewAlias(); SymTab.SetSymType(n, t0);; Expect(16); CodeGen.Emit(" = "); Type(t1); IF t1 = t0 THEN SemError(223); SymTab.SetTarget(t0, SymTab.InvalidType) ELSE SymTab.SetTarget(t0, t1) END;; END TypeDecl; PROCEDURE ConstDecl; VAR n: SymTab.Name; t: SymTab.TypeIndex; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindConst) THEN SemError(200) END; Expect(16); CodeGen.Emit(" = "); ConstExpr(t); SymTab.SetSymType(n, t);; END ConstDecl; PROCEDURE StatSeq; BEGIN Stat; WHILE (sym = 6) DO Get; CodeGen.Emit(";"); CodeGen.Brk;; Stat; END; END StatSeq; PROCEDURE Declaration; BEGIN IF (sym = 13) THEN Get; CodeGen.Emit("CONST"); CodeGen.Ind;; WHILE (sym = 1) DO CodeGen.Brk;; ConstDecl; Expect(6); CodeGen.Emit(";"); END; CodeGen.Ded; CodeGen.Brk;; ELSIF (sym = 14) THEN Get; CodeGen.Emit("TYPE"); CodeGen.Ind;; WHILE (sym = 1) DO CodeGen.Brk;; TypeDecl; Expect(6); CodeGen.Emit(";"); END; CodeGen.Ded; CodeGen.Brk;; ELSIF (sym = 15) THEN Get; CodeGen.Emit("VAR"); CodeGen.Ind;; WHILE (sym = 1) DO CodeGen.Brk;; VarDecl; Expect(6); CodeGen.Emit(";"); END; CodeGen.Ded; CodeGen.Brk;; ELSE SynError(73); END; END Declaration; PROCEDURE ImportList; VAR n: SymTab.Name; BEGIN GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END; WHILE (sym = 10) DO Get; CodeGen.Emit(", "); GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END; END; END ImportList; PROCEDURE Block; BEGIN WHILE (sym = 13) OR (sym = 14) OR (sym = 15) DO Declaration; END; IF (sym = 11) THEN Get; CodeGen.Emit("BEGIN"); CodeGen.Ind; CodeGen.Brk;; StatSeq; END; Expect(12); CodeGen.Ded; CodeGen.Brk; CodeGen.Emit("END "); END Block; PROCEDURE Import; VAR n: SymTab.Name; BEGIN IF (sym = 8) THEN Get; CodeGen.Emit("FROM "); GetIdent(n); IF ~SymTab.Enter(n, SymTab.KindImport) THEN SemError(200) END; Expect(9); CodeGen.Emit(" IMPORT "); ImportList; Expect(6); CodeGen.Emit(";"); CodeGen.Brk;; ELSIF (sym = 9) THEN Get; CodeGen.Emit("IMPORT "); ImportList; Expect(6); CodeGen.Emit(";"); CodeGen.Brk;; ELSE SynError(74); END; END Import; PROCEDURE GetIdent (VAR n: SymTab.Name); BEGIN Expect(1); LexName(n); CodeGen.Emit(n);; END GetIdent; PROCEDURE SimpleMod2; VAR m1, m2: SymTab.Name; BEGIN Expect(5); CodeGen.Emit("MODULE "); GetIdent(m1); SymTab.Init; CodeGen.OpenModule(m1); CodeGen.Emit("MODULE "); CodeGen.Emit(m1); IF ~SymTab.Enter(m1, SymTab.KindModule) THEN SemError(200) END; Expect(6); CodeGen.Emit(";"); CodeGen.Brk;; WHILE (sym = 8) OR (sym = 9) DO Import; END; Block; GetIdent(m2); IF ~SymTab.Equal(m1, m2) THEN SemError(202) END; Expect(7); CodeGen.Emit("."); CodeGen.Close; SymTab.PrintTable;; END SimpleMod2; PROCEDURE Parse; BEGIN SimpleMS.Reset; Get; SimpleMod2; 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[ 1, 0] := BITSET{1, 2, 3, 4}; symSet[ 1, 1] := BITSET{5}; symSet[ 1, 2] := BITSET{}; symSet[ 1, 3] := BITSET{5, 6, 14, 15}; symSet[ 1, 4] := BITSET{0}; symSet[ 2, 0] := BITSET{}; symSet[ 2, 1] := BITSET{}; symSet[ 2, 2] := BITSET{}; symSet[ 2, 3] := BITSET{8, 9, 10, 11, 12, 13}; symSet[ 2, 4] := BITSET{}; symSet[ 3, 0] := BITSET{1}; symSet[ 3, 1] := BITSET{13, 15}; symSet[ 3, 2] := BITSET{3, 5, 7, 9, 10, 12}; symSet[ 3, 3] := BITSET{}; symSet[ 3, 4] := BITSET{}; symSet[ 4, 0] := BITSET{}; symSet[ 4, 1] := BITSET{0}; symSet[ 4, 2] := BITSET{14, 15}; symSet[ 4, 3] := BITSET{0, 1, 2, 3, 4}; symSet[ 4, 4] := BITSET{}; END SimpleMP.