| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- COMPILER SimpleMod2
- (* Simplified Modula-2 without PROCEDURE / FUNCTION
- - program module only, no DEFINITION / IMPLEMENTATION split
- - no local modules, no EXPORT, no PRIORITY
- - no ProcedureDeclaration, FormalParameters, ProcedureType,
- ProcedureCall, ActualParameters, FORWARD, RETURN
- - statements: assignment, IF, CASE, WHILE, REPEAT, LOOP/EXIT, FOR, WITH
- - symbol table (SymTab) with static type checking:
- 200 = duplicate identifier, 201 = undeclared identifier,
- 202 = MODULE / END name mismatch,
- 210 = incompatible assignment (incl. assignment to a constant),
- 211 = arithmetic operand must be numeric,
- 212 = boolean operand required,
- 213 = incompatible comparison / CASE label mismatch,
- 214 = BOOLEAN condition required,
- 215 = not a RECORD type, 216 = unknown field,
- 217 = not an ARRAY type, 218 = array index must be integer,
- 219 = not a POINTER type,
- 220 = FOR needs integer variable and bounds,
- 221 = not a type name, 222 = set operand mismatch,
- 223 = cyclical type definition, 224 = ordinal type required
- - type rules (single pass, declare-before-use):
- . INTEGER, CARDINAL and subranges form one integer family;
- no mixed INTEGER/REAL arithmetic; INTEGER assigns to REAL
- . each TYPE name gets an alias descriptor, so self-references
- (POINTER TO Person) resolve; A = A is caught as cyclical
- . record fields live in the type descriptor; WITH pushes them
- as an inner scope, so unqualified field access works there
- . string literal of length 1 is CHAR, longer ones are string
- type (assignable to ARRAY types only)
- . unknown types (InvalidType) suppress follow-on errors
- - backend (CodeGen): pretty-prints a complete, ready-to-compile
- Modula-2 program module to gen/<ModName>.mod (directory gen/
- must exist). Comments are dropped; layout is regenerated. *)
- IMPORT SymTab, CodeGen;
- CHARACTERS
- eol = CHR(13) .
- letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
- digit = "0123456789" .
- hexDigit = digit + "ABCDEF" .
- noQuote1 = ANY - "'" - eol .
- noQuote2 = ANY - '"' - eol .
- IGNORE CHR(9) .. CHR(13)
- COMMENTS
- FROM "(*" TO "*)" NESTED
- TOKENS
- ident = letter { letter | digit } .
- integer = digit { digit }
- | digit { digit } CONTEXT("..")
- | digit { hexDigit } "H" .
- real = digit { digit } "." { digit }
- [ "E" [ "+" | "-" ] digit { digit } ] .
- string = "'" { noQuote1 } "'"
- | '"' { noQuote2 } '"' .
- PRODUCTIONS
- SimpleMod2 (. VAR m1, m2: SymTab.Name; .)
- = "MODULE" (. 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 .)
- ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
- { Import } Block GetIdent<m2> (. IF ~SymTab.Equal(m1, m2)
- THEN SemError(202) END .)
- "." (. CodeGen.Emit(".");
- CodeGen.Close;
- SymTab.PrintTable; .) .
- Import (. VAR n: SymTab.Name; .)
- = "FROM" (. CodeGen.Emit("FROM ") .)
- GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
- THEN SemError(200) END .)
- "IMPORT" (. CodeGen.Emit(" IMPORT ") .)
- ImportList ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
- | "IMPORT" (. CodeGen.Emit("IMPORT ") .)
- ImportList ";" (. CodeGen.Emit(";"); CodeGen.Brk; .) .
- ImportList (. VAR n: SymTab.Name; .)
- = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
- THEN SemError(200) END .)
- { "," (. CodeGen.Emit(", ") .)
- GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
- THEN SemError(200) END .) } .
- Block = { Declaration }
- [ "BEGIN" (. CodeGen.Emit("BEGIN");
- CodeGen.Ind; CodeGen.Brk; .)
- StatSeq ]
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END ") .) .
- Declaration = "CONST" (. CodeGen.Emit("CONST"); CodeGen.Ind; .)
- { (. CodeGen.Brk; .)
- ConstDecl ";" (. CodeGen.Emit(";") .) }
- (. CodeGen.Ded; CodeGen.Brk; .)
- | "TYPE" (. CodeGen.Emit("TYPE"); CodeGen.Ind; .)
- { (. CodeGen.Brk; .)
- TypeDecl ";" (. CodeGen.Emit(";") .) }
- (. CodeGen.Ded; CodeGen.Brk; .)
- | "VAR" (. CodeGen.Emit("VAR"); CodeGen.Ind; .)
- { (. CodeGen.Brk; .)
- VarDecl ";" (. CodeGen.Emit(";") .) }
- (. CodeGen.Ded; CodeGen.Brk; .) .
- ConstDecl (. VAR n: SymTab.Name;
- t: SymTab.TypeIndex; .)
- = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindConst)
- THEN SemError(200) END .)
- "=" (. CodeGen.Emit(" = ") .)
- ConstExpr<t> (. SymTab.SetSymType(n, t); .) .
- ConstExpr <VAR t: SymTab.TypeIndex>
- = Expr<t> .
- TypeDecl (. VAR n: SymTab.Name;
- t0, t1: SymTab.TypeIndex; .)
- = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindType)
- THEN SemError(200) END;
- t0 := SymTab.NewAlias();
- SymTab.SetSymType(n, t0); .)
- "=" (. CodeGen.Emit(" = ") .)
- Type<t1> (. IF t1 = t0 THEN SemError(223);
- SymTab.SetTarget(t0,
- SymTab.InvalidType)
- ELSE SymTab.SetTarget(t0, t1) END; .) .
- VarDecl (. VAR t: SymTab.TypeIndex; .)
- = VarIdents ":" (. CodeGen.Emit(" : ") .)
- Type<t> (. SymTab.FixPending(t); .) .
- VarIdents (. VAR n: SymTab.Name; .)
- = GetIdent<n> (. IF ~SymTab.EnterPending(n,
- SymTab.KindVar)
- THEN SemError(200) END .)
- { "," (. CodeGen.Emit(", ") .)
- GetIdent<n> (. IF ~SymTab.EnterPending(n,
- SymTab.KindVar)
- THEN SemError(200) END .) } .
- QualIdent <VAR t: SymTab.TypeIndex>
- (. VAR n, m: SymTab.Name; .)
- = 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; .)
- { "." (. CodeGen.Emit(".");
- t := SymTab.InvalidType; .)
- GetIdent<m> } .
- (* Types: ProcedureType removed; subrange factored for LL(1) *)
- Type <VAR t: SymTab.TypeIndex>
- = SimpleType<t> | ArrayType<t> | RecordType<t>
- | SetType<t> | PointerType<t> .
- SimpleType <VAR t: SymTab.TypeIndex>
- (. VAR t1, t2: SymTab.TypeIndex; .)
- = QualIdent<t> [ "[" (. 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; .)
- ".." (. 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; .)
- "]" (. CodeGen.Emit("]") .)
- (. t := SymTab.NewSub(t1); .) ]
- | "[" (. 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; .)
- ".." (. 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; .)
- "]" (. CodeGen.Emit("]") .)
- (. t := SymTab.NewSub(t1); .)
- | Enum<t> .
- Enum <VAR t: SymTab.TypeIndex>
- (. VAR n: SymTab.Name; .)
- = "(" (. CodeGen.Emit("(");
- t := SymTab.NewEnum(); .)
- GetIdent<n> (. IF ~SymTab.Enter(n,
- SymTab.KindConst)
- THEN SemError(200) END;
- SymTab.SetSymType(n, t); .)
- { "," (. CodeGen.Emit(", ") .)
- GetIdent<n> (. IF ~SymTab.Enter(n,
- SymTab.KindConst)
- THEN SemError(200) END;
- SymTab.SetSymType(n, t); .) }
- ")" (. CodeGen.Emit(")") .) .
- ArrayType <VAR t: SymTab.TypeIndex>
- (. VAR s, s2, e: SymTab.TypeIndex; .)
- = "ARRAY" (. 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; .)
- { "," (. 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; .) }
- "OF" (. CodeGen.Emit(" OF ") .)
- Type<e> (. t := SymTab.NewArray(e); .) .
- RecordType <VAR t: SymTab.TypeIndex>
- = "RECORD" (. CodeGen.Emit("RECORD");
- CodeGen.Ind; CodeGen.Brk;
- t := SymTab.NewRecord(); .)
- FieldSeq<t>
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- FieldSeq <rt: SymTab.TypeIndex>
- = Field<rt> { ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
- Field<rt> } .
- Field <rt: SymTab.TypeIndex>
- (. VAR et: SymTab.TypeIndex; .)
- = [ FieldIdents<rt> ":" (. CodeGen.Emit(" : ") .)
- Type<et> (. SymTab.FixPendingF(rt, et); .) ] .
- FieldIdents <rt: SymTab.TypeIndex>
- (. VAR n: SymTab.Name; .)
- = GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
- THEN SemError(200) END .)
- { "," (. CodeGen.Emit(", ") .)
- GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
- THEN SemError(200) END .) } .
- SetType <VAR t: SymTab.TypeIndex>
- (. VAR s: SymTab.TypeIndex; .)
- = "SET" (. CodeGen.Emit("SET ") .)
- "OF" (. 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); .) .
- PointerType <VAR t: SymTab.TypeIndex>
- (. VAR b: SymTab.TypeIndex; .)
- = "POINTER" (. CodeGen.Emit("POINTER ") .)
- "TO" (. CodeGen.Emit("TO ") .)
- Type<b> (. t := SymTab.NewPtr(b); .) .
- (* Statements: ProcedureCall and RETURN removed *)
- StatSeq = Stat { ";" (. CodeGen.Emit(";") .)
- (. CodeGen.Brk; .)
- Stat } .
- Stat = [ Assign | IfStat | CaseStat | WhileStat
- | RepeatStat | LoopStat | ForStat | WithStat
- | "EXIT" (. CodeGen.Emit("EXIT") .) ] .
- Assign (. VAR dt, et: SymTab.TypeIndex;
- dk: INTEGER; .)
- = Design<dt, dk> ":=" (. 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; .) .
- IfStat (. VAR t: SymTab.TypeIndex; .)
- = "IF" (. CodeGen.Emit("IF ") .)
- Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
- SemError(214) END; .)
- "THEN" (. CodeGen.Emit(" THEN");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- { "ELSIF" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("ELSIF ") .)
- Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
- SemError(214) END; .)
- "THEN" (. CodeGen.Emit(" THEN");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq }
- [ "ELSE" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("ELSE");
- CodeGen.Ind; CodeGen.Brk; .)
- StatSeq ]
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- CaseStat (. VAR st: SymTab.TypeIndex; .)
- = "CASE" (. CodeGen.Emit("CASE ") .)
- Expr<st>
- "OF" (. CodeGen.Emit(" OF");
- CodeGen.Brk; CodeGen.Ind; .)
- Case<st> { "|" (. CodeGen.Brk; CodeGen.Emit("| ") .)
- Case<st> }
- [ "ELSE" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("ELSE ");
- CodeGen.Ind; CodeGen.Brk; .)
- StatSeq ]
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- Case <sel: SymTab.TypeIndex>
- = [ LabelList<sel> ":" (. CodeGen.Emit(" : ") .)
- StatSeq ] .
- LabelList <sel: SymTab.TypeIndex>
- = Labels<sel> { "," (. CodeGen.Emit(", ") .)
- Labels<sel> } .
- Labels <sel: SymTab.TypeIndex>
- (. VAR t, t2: SymTab.TypeIndex; .)
- = ConstExpr<t> (. IF ~SymTab.EqCheck(t, sel) THEN
- SemError(213) END; .)
- [ ".." (. CodeGen.Emit("..") .)
- ConstExpr<t2> (. IF ~SymTab.EqCheck(t2, sel) THEN
- SemError(213) END; .) ] .
- WhileStat (. VAR t: SymTab.TypeIndex; .)
- = "WHILE" (. CodeGen.Emit("WHILE ") .)
- Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
- SemError(214) END; .)
- "DO" (. CodeGen.Emit(" DO");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- RepeatStat (. VAR t: SymTab.TypeIndex; .)
- = "REPEAT" (. CodeGen.Emit("REPEAT");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- "UNTIL" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("UNTIL ") .)
- Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
- SemError(214) END; .) .
- LoopStat = "LOOP" (. CodeGen.Emit("LOOP");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- ForStat (. VAR n: SymTab.Name;
- lo, hi, by: SymTab.TypeIndex; .)
- = "FOR" (. 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; .)
- ":=" (. CodeGen.Emit(" := ") .)
- Expr<lo> (. IF (lo # SymTab.InvalidType)
- & ~SymTab.IsIntFamily(lo) THEN
- SemError(220) END; .)
- "TO" (. CodeGen.Emit(" TO ") .)
- Expr<hi> (. IF (hi # SymTab.InvalidType)
- & ~SymTab.IsIntFamily(hi) THEN
- SemError(220) END; .)
- [ "BY" (. CodeGen.Emit(" BY ") .)
- ConstExpr<by> (. IF (by # SymTab.InvalidType)
- & ~SymTab.IsIntFamily(by) THEN
- SemError(220) END; .) ]
- "DO" (. CodeGen.Emit(" DO");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- "END" (. CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- WithStat (. VAR dt: SymTab.TypeIndex;
- dk: INTEGER;
- pushed: BOOLEAN; .)
- = "WITH" (. CodeGen.Emit("WITH ") .)
- Design<dt, dk> (. pushed := FALSE;
- IF dt # SymTab.InvalidType THEN
- pushed :=
- SymTab.PushRecord(dt);
- IF ~pushed THEN
- SemError(215)
- END
- END; .)
- "DO" (. CodeGen.Emit(" DO");
- CodeGen.Brk; CodeGen.Ind; .)
- StatSeq
- "END" (. IF pushed THEN
- SymTab.PopScope
- END;
- CodeGen.Ded; CodeGen.Brk;
- CodeGen.Emit("END") .) .
- (* Expressions: Designator without ActualParameters.
- Only record fields resolve qualified access; WITH pushes an
- inner scope so field names also work unqualified in its body. *)
- Design <VAR t: SymTab.TypeIndex; VAR k: INTEGER>
- (. VAR n, m: SymTab.Name;
- it: SymTab.TypeIndex; .)
- = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
- SemError(201);
- t := SymTab.InvalidType; k := -1
- ELSE t := SymTab.SymType(n);
- k := SymTab.SymKind(n) END; .)
- { "." (. 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; .)
- | "[" (. 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; .)
- { "," (. CodeGen.Emit(", ") .)
- Expr<it> (. IF (it # SymTab.InvalidType)
- & ~SymTab.IsIntFamily(it) THEN
- SemError(218) END; .) }
- "]" (. CodeGen.Emit("]") .)
- | "^" (. 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; .) } .
- Expr <VAR t: SymTab.TypeIndex>
- (. VAR t2: SymTab.TypeIndex;
- op: INTEGER; .)
- = SimExpr<t> [ 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; .) ] .
- Rel <VAR op: INTEGER>
- = "=" (. CodeGen.Emit(" = "); op := SymTab.OpEq; .)
- | "#" (. CodeGen.Emit(" # "); op := SymTab.OpNeq1; .)
- | "<>" (. CodeGen.Emit(" <> "); op := SymTab.OpNeq2; .)
- | "<" (. CodeGen.Emit(" < "); op := SymTab.OpLt; .)
- | "<=" (. CodeGen.Emit(" <= "); op := SymTab.OpLe; .)
- | ">" (. CodeGen.Emit(" > "); op := SymTab.OpGt; .)
- | ">=" (. CodeGen.Emit(" >= "); op := SymTab.OpGe; .)
- | "IN" (. CodeGen.Emit(" IN "); op := SymTab.OpIn; .) .
- SimExpr <VAR t: SymTab.TypeIndex>
- (. VAR t2, res2: SymTab.TypeIndex;
- op: INTEGER; .)
- = [ "+" (. CodeGen.Emit("+") .)
- | "-" (. CodeGen.Emit("-") .) ]
- Term<t> { 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; .) } .
- AddOp <VAR op: INTEGER>
- = "+" (. CodeGen.Emit(" + "); op := SymTab.OpAdd; .)
- | "-" (. CodeGen.Emit(" - "); op := SymTab.OpSub; .)
- | "OR" (. CodeGen.Emit(" OR "); op := SymTab.OpOr; .) .
- Term <VAR t: SymTab.TypeIndex>
- (. VAR t2, res2: SymTab.TypeIndex;
- op: INTEGER; .)
- = Fact<t> { 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; .) } .
- MulOp <VAR op: INTEGER>
- = "*" (. CodeGen.Emit(" * "); op := SymTab.OpTimes; .)
- | "/" (. CodeGen.Emit(" / "); op := SymTab.OpSlash; .)
- | "DIV" (. CodeGen.Emit(" DIV "); op := SymTab.OpDiv; .)
- | "MOD" (. CodeGen.Emit(" MOD "); op := SymTab.OpMod; .)
- | "AND" (. CodeGen.Emit(" AND "); op := SymTab.OpAnd; .)
- | "&" (. CodeGen.Emit(" & "); op := SymTab.OpAnd; .) .
- Fact <VAR t: SymTab.TypeIndex>
- (. VAR s: ARRAY [0 .. 255] OF CHAR;
- t2, et, dt, st: SymTab.TypeIndex;
- dk: INTEGER; .)
- = integer (. LexString(s); CodeGen.Emit(s);
- t := SymTab.IntType(); .)
- | real (. LexString(s); CodeGen.Emit(s);
- t := SymTab.RealType(); .)
- | string (. LexString(s); CodeGen.Emit(s);
- IF SymTab.StrLen(s) <= 3 THEN
- t := SymTab.CharType()
- ELSE t := SymTab.NewStr() END; .)
- | Design<dt, dk> (. t := dt; .)
- | "(" (. CodeGen.Emit("(") .)
- Expr<et> ")" (. CodeGen.Emit(")"); t := et; .)
- | ( "NOT" (. CodeGen.Emit("NOT ") .)
- | "~" (. CodeGen.Emit("~") .) )
- Fact<t2> (. IF SymTab.BoolCheck(t2) THEN
- t := SymTab.BoolType()
- ELSE SemError(212);
- t := SymTab.InvalidType END; .)
- | SetLit<st> (. t := st; .) .
- SetLit <VAR t: SymTab.TypeIndex>
- (. VAR first, et: SymTab.TypeIndex; .)
- = "{" (. CodeGen.Emit("{");
- t := SymTab.SetFor(SymTab.IntType()); .)
- [ Elem<et> (. first := et; t := SymTab.SetFor(et); .)
- { "," (. CodeGen.Emit(", ") .)
- Elem<et> (. IF ~SymTab.SetElemCheck(first, et) THEN
- SemError(222) END; .) } ]
- "}" (. CodeGen.Emit("}") .) .
- Elem <VAR t: SymTab.TypeIndex>
- (. VAR t2: SymTab.TypeIndex; .)
- = Expr<t> [ ".." (. CodeGen.Emit("..") .)
- Expr<t2> (. IF ~SymTab.SetElemCheck(t, t2) THEN
- SemError(222) END; .) ] .
- GetIdent <VAR n: SymTab.Name>
- = ident (. LexName(n); CodeGen.Emit(n); .) .
- END SimpleMod2.
|