|
@@ -10,16 +10,919 @@ Undefined nonterminals: -- none --
|
|
|
Unreachable nonterminals: -- none --
|
|
Unreachable nonterminals: -- none --
|
|
|
Circular derivations: -- none --
|
|
Circular derivations: -- none --
|
|
|
Underivable nonterminals: -- none --
|
|
Underivable nonterminals: -- none --
|
|
|
-LL(1) conditions: -- ok --
|
|
|
|
|
|
|
+LL(1) conditions:
|
|
|
|
|
+ LL(1) error in TypeBlock: "CLASS" is the start & successor of a deletable structure
|
|
|
|
|
+
|
|
|
|
|
+Listing:
|
|
|
|
|
+
|
|
|
|
|
+ 1 COMPILER M2
|
|
|
|
|
+ 2 (* Step 1 — minimal integer pipeline (m2compiler-V3).
|
|
|
|
|
+ 3 Subset: program MODULE + CONST (literal) + VAR INTEGER +
|
|
|
|
|
+ 4 assignment + integer expressions (+ - * DIV MOD, leading sign,
|
|
|
|
|
+ 5 parens). Fresh QBE backend (QbeGen) to gen_ssa/<Module>.ssa;
|
|
|
|
|
+ 6 assemble with qbe, link with cc.
|
|
|
|
|
+ 7
|
|
|
|
|
+ 8 Test convention: a global VAR ExitCode : INTEGER makes generated
|
|
|
|
|
+ 9 $main return its value as the process exit code, else return 0.
|
|
|
|
|
+ 10
|
|
|
|
|
+ 11 Semantic errors reuse the V1/V2/Test2 family: 200 duplicate,
|
|
|
|
|
+ 12 201 undeclared, 202 module name mismatch, 210 bad assignment,
|
|
|
|
|
+ 13 211 bad arithmetic, 221 not a type, 230 not supported yet,
|
|
|
|
|
+ 14 231 opaque type outside definition.
|
|
|
|
|
+ 15 Scalar-phase TYPEs (named, integer subrange, enum) check fully;
|
|
|
|
|
+ 16 composite forms wait for step 3. Procedure headings (formals,
|
|
|
|
|
+ 17 result, FORWARD) enter scopes now; bodies parse + check with one
|
|
|
|
|
+ 18 230 at END (lowering = step 4).
|
|
|
|
|
+ 19 Statements: assignment, IF/ELSIF/ELSE, WHILE, REPEAT/UNTIL,
|
|
|
|
|
+ 20 LOOP/EXIT (230 outside LOOP), FOR/TO/static-sign-BY, full CASE
|
|
|
|
|
+ 21 (labels, ranges, ELSE; compare-chain), RETURN with 232 checks
|
|
|
|
|
+ 22 (outside proc / value mismatch / missing value). WITH waits for
|
|
|
|
|
+ 23 records (step 3). Boolean connectives are eager (or/and/xor);
|
|
|
|
|
+ 24 relations yield 0/1 via cXXw.
|
|
|
|
|
+ 25 Clarion-form classes (docs/OOP.txt): CLASS decl + single
|
|
|
|
|
+ 26 inheritance + CLASS IMPLEMENTATION blocks, methods with ";"
|
|
|
|
|
+ 27 (per the Table example, not the sketch's ","), VIRTUAL flagged.
|
|
|
|
|
+ 28 Scopes and member checks now; lowering later (one 230 per
|
|
|
|
|
+ 29 class/impl block). Classic identifiers: no underscores, so the
|
|
|
|
|
+ 30 Table example's _names stay lexically out of reach. *)
|
|
|
|
|
+ 31
|
|
|
|
|
+ 32 IMPORT SymTab, QbeGen;
|
|
|
|
|
+ 33
|
|
|
|
|
+ 34 CHARACTERS
|
|
|
|
|
+ 35 eol = CHR(13) .
|
|
|
|
|
+ 36 lf = CHR(10) .
|
|
|
|
|
+ 37 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
|
|
+ 38 digit = "0123456789" .
|
|
|
|
|
+ 39 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
|
|
+ 40 noQuote1 = ANY - "'" - eol .
|
|
|
|
|
+ 41 noQuote2 = ANY - '"' - eol .
|
|
|
|
|
+ 42
|
|
|
|
|
+ 43 IGNORE CHR(9) .. CHR(13)
|
|
|
|
|
+ 44
|
|
|
|
|
+ 45 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
|
|
+ 46 COMMENTS FROM "//" TO lf
|
|
|
|
|
+ 47
|
|
|
|
|
+ 48 TOKENS
|
|
|
|
|
+ 49 ident = letter { letter | digit } .
|
|
|
|
|
+ 50 integer = digit { digit }
|
|
|
|
|
+ 51 | digit { digit } CONTEXT("..")
|
|
|
|
|
+ 52 | "0x" hexDigit { hexDigit }
|
|
|
|
|
+ 53 | "0X" hexDigit { hexDigit } .
|
|
|
|
|
+ 54 real = digit { digit } "." { digit }
|
|
|
|
|
+ 55 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
|
|
+ 56 string = "'" { noQuote1 } "'"
|
|
|
|
|
+ 57 | '"' { noQuote2 } '"' .
|
|
|
|
|
+ 58
|
|
|
|
|
+ 59 PRODUCTIONS
|
|
|
|
|
+ 60 M2
|
|
|
|
|
+ 61 = Unit "." .
|
|
|
|
|
+ 62 (* Units: program modules compile fully; DEFINITION and
|
|
|
|
|
+ 63 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
|
|
+ 64 (each ends with one 230); same for nested local modules. *)
|
|
|
|
|
+ 65 Unit
|
|
|
|
|
+ 66 = DefUnit
|
|
|
|
|
+ 67 | ImplUnit
|
|
|
|
|
+ 68 | ProgModule .
|
|
|
|
|
+ 69 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
|
|
+ 70 = "DEFINITION" "MODULE"
|
|
|
|
|
+ 71 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
|
|
+ 72 IF ~SymTab.Enter(m1,
|
|
|
|
|
+ 73 SymTab.KindModule) THEN
|
|
|
|
|
+ 74 SemError(200) END; .)
|
|
|
|
|
+ 75 ";"
|
|
|
|
|
+ 76 { Import }
|
|
|
|
|
+ 77 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
|
|
+ 78 | ProcHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
|
|
+ 79 "END"
|
|
|
|
|
+ 80 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 81 SemError(202) END; .)
|
|
|
|
|
+ 82 (. QbeGen.CloseModule;
|
|
|
|
|
+ 83 SemError(230);
|
|
|
|
|
+ 84 SymTab.PrintTable; .) .
|
|
|
|
|
+ 85 ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
|
|
+ 86 = "IMPLEMENTATION" "MODULE"
|
|
|
|
|
+ 87 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
|
|
+ 88 IF ~SymTab.Enter(m1,
|
|
|
|
|
+ 89 SymTab.KindModule) THEN
|
|
|
|
|
+ 90 SemError(200) END; .)
|
|
|
|
|
+ 91 ";"
|
|
|
|
|
+ 92 { Import }
|
|
|
|
|
+ 93 DeclSeq
|
|
|
|
|
+ 94 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
|
|
+ 95 [ StatSeq ] ]
|
|
|
|
|
+ 96 "END"
|
|
|
|
|
+ 97 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 98 SemError(202) END; .)
|
|
|
|
|
+ 99 (. QbeGen.CloseModule;
|
|
|
|
|
+ 100 SemError(230);
|
|
|
|
|
+ 101 SymTab.PrintTable; .) .
|
|
|
|
|
+ 102 ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
|
|
+ 103 = "MODULE"
|
|
|
|
|
+ 104 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
|
|
+ 105 IF ~SymTab.Enter(m1,
|
|
|
|
|
+ 106 SymTab.KindModule) THEN
|
|
|
|
|
+ 107 SemError(200) END; .)
|
|
|
|
|
+ 108 [ Priority ]
|
|
|
|
|
+ 109 ";"
|
|
|
|
|
+ 110 { Import }
|
|
|
|
|
+ 111 DeclSeq
|
|
|
|
|
+ 112 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
|
|
+ 113 [ StatSeq ] ]
|
|
|
|
|
+ 114 "END"
|
|
|
|
|
+ 115 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 116 SemError(202) END; .)
|
|
|
|
|
+ 117 (. QbeGen.EndModule;
|
|
|
|
|
+ 118 SymTab.PrintTable; .) .
|
|
|
|
|
+ 119 DeclSeq
|
|
|
|
|
+ 120 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
|
|
+ 121 | NestedModule ";" | ClassItem ";" } .
|
|
|
|
|
+ 122 (* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
|
|
+ 123 lowering waits for step 4, marked by one 230 at END. *)
|
|
|
|
|
+ 124 NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
|
|
+ 125 = "MODULE"
|
|
|
|
|
+ 126 GetIdent<m1> (. IF ~SymTab.Enter(m1,
|
|
|
|
|
+ 127 SymTab.KindModule) THEN
|
|
|
|
|
+ 128 SemError(200) END;
|
|
|
|
|
+ 129 SymTab.PushScope; .)
|
|
|
|
|
+ 130 [ Priority ]
|
|
|
|
|
+ 131 ";"
|
|
|
|
|
+ 132 { Import }
|
|
|
|
|
+ 133 [ Export ]
|
|
|
|
|
+ 134 DeclSeq
|
|
|
|
|
+ 135 [ "BEGIN"
|
|
|
|
|
+ 136 [ StatSeq ] ]
|
|
|
|
|
+ 137 "END"
|
|
|
|
|
+ 138 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 139 SemError(202) END;
|
|
|
|
|
+ 140 SymTab.PopScope;
|
|
|
|
|
+ 141 SemError(230); .) .
|
|
|
|
|
+ 142 Priority
|
|
|
|
|
+ 143 = "[" integer "]" (. SemError(230); .) .
|
|
|
|
|
+ 144 Export (. VAR nm: SymTab.Name; .)
|
|
|
|
|
+ 145 = "EXPORT" (* names wire up in step 4 *)
|
|
|
|
|
+ 146 [ "QUALIFIED" ]
|
|
|
|
|
+ 147 GetIdent<nm>
|
|
|
|
|
+ 148 { "," GetIdent<nm> }
|
|
|
|
|
+ 149 ";" .
|
|
|
|
|
+ 150 Import (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 151 = "FROM"
|
|
|
|
|
+ 152 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 153 SymTab.KindImport) THEN
|
|
|
|
|
+ 154 SemError(200) END; .)
|
|
|
|
|
+ 155 "IMPORT"
|
|
|
|
|
+ 156 ImpList ";"
|
|
|
|
|
+ 157 | "IMPORT"
|
|
|
|
|
+ 158 ImpList ";" .
|
|
|
|
|
+ 159 ImpList (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 160 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 161 SymTab.KindImport) THEN
|
|
|
|
|
+ 162 SemError(200) END; .)
|
|
|
|
|
+ 163 { ","
|
|
|
|
|
+ 164 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 165 SymTab.KindImport) THEN
|
|
|
|
|
+ 166 SemError(200) END; .) } .
|
|
|
|
|
+ 167 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
|
|
+ 168 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
|
|
+ 169 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
|
|
+ 170 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
|
|
+ 171 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
|
|
+ 172 TypeBlock<isDef: BOOLEAN>
|
|
|
|
|
+ 173 = "TYPE" { TypeItem<isDef> ";" | ClassItem ";" } .
|
|
|
|
|
+ 174 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 175 t: SymTab.TypeIndex; .)
|
|
|
|
|
+ 176 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 177 SymTab.KindType) THEN
|
|
|
|
|
+ 178 SemError(200) END; .)
|
|
|
|
|
+ 179 ( "=" Type<t> (. SymTab.SetSymType(n, t); .)
|
|
|
|
|
+ 180 | (. IF ~isDef THEN
|
|
|
|
|
+ 181 SemError(231) END;
|
|
|
|
|
+ 182 SymTab.SetSymType(n,
|
|
|
|
|
+ 183 SymTab.NewAlias()); .) ) .
|
|
|
|
|
+ 184 Type<VAR t: SymTab.TypeIndex>
|
|
|
|
|
+ 185 = TypeIdent<t>
|
|
|
|
|
+ 186 | Subrange<t>
|
|
|
|
|
+ 187 | Enum<t> .
|
|
|
|
|
+ 188 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 189 k: INTEGER; .)
|
|
|
|
|
+ 190 = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
|
|
+ 191 SemError(201);
|
|
|
|
|
+ 192 t := SymTab.InvalidType
|
|
|
|
|
+ 193 ELSE k := SymTab.SymKind(n);
|
|
|
|
|
+ 194 IF (k = SymTab.KindType)
|
|
|
|
|
+ 195 OR (k = SymTab.KindPredef) THEN
|
|
|
|
|
+ 196 t := SymTab.SymType(n)
|
|
|
|
|
+ 197 ELSIF k = SymTab.KindImport THEN
|
|
|
|
|
+ 198 t := SymTab.InvalidType
|
|
|
|
|
+ 199 ELSE SemError(221);
|
|
|
|
|
+ 200 t := SymTab.InvalidType
|
|
|
|
|
+ 201 END
|
|
|
|
|
+ 202 END; .) .
|
|
|
|
|
+ 203 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
+ 204 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ 205 lo, hi: INTEGER; .)
|
|
|
|
|
+ 206 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
+ 207 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
+ 208 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
+ 209 t := SymTab.InvalidType
|
|
|
|
|
+ 210 ELSIF (SymTab.ClassOf(tlo) #
|
|
|
|
|
+ 211 SymTab.ClInt)
|
|
|
|
|
+ 212 OR (SymTab.ClassOf(thi) #
|
|
|
|
|
+ 213 SymTab.ClInt) THEN
|
|
|
|
|
+ 214 SemError(230);
|
|
|
|
|
+ 215 t := SymTab.InvalidType
|
|
|
|
|
+ 216 ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
|
|
+ 217 OR ~SymTab.ConstInt(qhi, hi)
|
|
|
|
|
+ 218 OR (lo > hi) THEN
|
|
|
|
|
+ 219 SemError(230);
|
|
|
|
|
+ 220 t := SymTab.InvalidType
|
|
|
|
|
+ 221 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
|
|
+ 222 END; .)
|
|
|
|
|
+ 223 "]" .
|
|
|
|
|
+ 224 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 225 = "(" (. t := SymTab.NewEnum(); .)
|
|
|
|
|
+ 226 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 227 SymTab.KindConst) THEN
|
|
|
|
|
+ 228 SemError(200) END;
|
|
|
|
|
+ 229 SymTab.SetSymType(n, t); .)
|
|
|
|
|
+ 230 { "," GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 231 SymTab.KindConst) THEN
|
|
|
|
|
+ 232 SemError(200) END;
|
|
|
|
|
+ 233 SymTab.SetSymType(n, t); .) }
|
|
|
|
|
+ 234 ")" .
|
|
|
|
|
+ 235 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
|
|
+ 236 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
|
|
+ 237 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
|
|
+ 238 class/impl block. Methods end with ";" per the Table example
|
|
|
|
|
+ 239 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
|
|
+ 240 (* Single CLASS item in both loops: separating declaration from
|
|
|
|
|
+ 241 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
|
|
+ 242 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
|
|
+ 243 The second token decides after CLASS is consumed. A misplaced
|
|
|
|
|
+ 244 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
|
|
+ 245 whole unit ends 230 until lowering). *)
|
|
|
|
|
+ 246 ClassItem
|
|
|
|
|
+ 247 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
|
|
+ 248 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
|
|
+ 249 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 250 = GetIdent<cn> (. IF ~SymTab.Enter(cn,
|
|
|
|
|
+ 251 SymTab.KindType) THEN
|
|
|
|
|
+ 252 SemError(200) END;
|
|
|
|
|
+ 253 ct := SymTab.NewClass();
|
|
|
|
|
+ 254 SymTab.SetSymType(cn, ct);
|
|
|
|
|
+ 255 SymTab.PushClassScope(ct); .)
|
|
|
|
|
+ 256 [ Parents<ct> ]
|
|
|
|
|
+ 257 ";"
|
|
|
|
|
+ 258 { ClassField<ct> ";" }
|
|
|
|
|
+ 259 { MethodHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
|
|
+ 260 "END"
|
|
|
|
|
+ 261 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 262 SemError(202) END;
|
|
|
|
|
+ 263 SymTab.PopScope;
|
|
|
|
|
+ 264 SemError(230); .) .
|
|
|
|
|
+ 265 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
|
|
+ 266 = "(" Parent1<ct>
|
|
|
|
|
+ 267 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
|
|
+ 268 ")" .
|
|
|
|
|
+ 269 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
|
|
+ 270 pt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 271 = GetIdent<p> (. IF ~SymTab.Lookup(p) THEN
|
|
|
|
|
+ 272 SemError(201)
|
|
|
|
|
+ 273 ELSE pt := SymTab.SymType(p);
|
|
|
|
|
+ 274 IF SymTab.ClassOf(pt) #
|
|
|
|
|
+ 275 SymTab.ClClass THEN
|
|
|
|
|
+ 276 SemError(230)
|
|
|
|
|
+ 277 ELSE SymTab.SetParent(ct, pt)
|
|
|
|
|
+ 278 END
|
|
|
|
|
+ 279 END; .) .
|
|
|
|
|
+ 280 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
|
|
+ 281 t: SymTab.TypeIndex; .)
|
|
|
|
|
+ 282 = GetIdent<n>
|
|
|
|
|
+ 283 ( "=" GetIdent<rhs> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 284 SymTab.KindConst) THEN
|
|
|
|
|
+ 285 SemError(200) END;
|
|
|
|
|
+ 286 IF SymTab.Lookup(rhs) THEN
|
|
|
|
|
+ 287 SymTab.SetSymType(n,
|
|
|
|
|
+ 288 SymTab.SymType(rhs))
|
|
|
|
|
+ 289 END; .)
|
|
|
|
|
+ 290 | (. IF ~SymTab.FieldPending(ct,
|
|
|
|
|
+ 291 n) THEN
|
|
|
|
|
+ 292 SemError(200) END; .)
|
|
|
|
|
+ 293 { "," GetIdent<n> (. IF ~SymTab.FieldPending(ct,
|
|
|
|
|
+ 294 n) THEN
|
|
|
|
|
+ 295 SemError(200) END; .) }
|
|
|
|
|
+ 296 ":" TypeIdent<t> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
|
|
+ 297 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
|
|
|
|
|
+ 298 = (. wantVirt := FALSE; .)
|
|
|
|
|
+ 299 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
|
|
+ 300 ProcHeading<pn> (. IF wantVirt THEN
|
|
|
|
|
+ 301 SymTab.MarkVirtual END; .) .
|
|
|
|
|
+ 302 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
|
|
+ 303 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 304 = GetIdent<cn> (. IF ~SymTab.Lookup(cn) THEN
|
|
|
|
|
+ 305 SemError(201);
|
|
|
|
|
+ 306 ct := SymTab.InvalidType
|
|
|
|
|
+ 307 ELSE ct := SymTab.SymType(cn);
|
|
|
|
|
+ 308 IF SymTab.ClassOf(ct) #
|
|
|
|
|
+ 309 SymTab.ClClass THEN
|
|
|
|
|
+ 310 SemError(230);
|
|
|
|
|
+ 311 ct := SymTab.InvalidType
|
|
|
|
|
+ 312 END
|
|
|
|
|
+ 313 END;
|
|
|
|
|
+ 314 IF ct #
|
|
|
|
|
+ 315 SymTab.InvalidType THEN
|
|
|
|
|
+ 316 IF ~SymTab.PushClassMembers(
|
|
|
|
|
+ 317 ct) THEN
|
|
|
|
|
+ 318 SemError(230) END
|
|
|
|
|
+ 319 END; .)
|
|
|
|
|
+ 320 ";" { MethodImpl<ct> ";" }
|
|
|
|
|
+ 321 [ "BEGIN"
|
|
|
|
|
+ 322 [ StatSeq ] ]
|
|
|
|
|
+ 323 "END"
|
|
|
|
|
+ 324 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 325 SemError(202) END;
|
|
|
|
|
+ 326 SymTab.PopScope;
|
|
|
|
|
+ 327 SemError(230); .) .
|
|
|
|
|
+ 328 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
|
|
|
|
|
+ 329 = MethodHeading<pn> ";"
|
|
|
|
|
+ 330 (. IF (ct #
|
|
|
|
|
+ 331 SymTab.InvalidType)
|
|
|
|
|
+ 332 & ~SymTab.MethodExists(ct,
|
|
|
|
|
+ 333 pn) THEN
|
|
|
|
|
+ 334 SemError(201) END; .)
|
|
|
|
|
+ 335 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
+ 336 SymTab.CloseProc; .)
|
|
|
|
|
+ 337 | Block<pn> (. SymTab.CloseProc;
|
|
|
|
|
+ 338 SemError(230); .) ) .
|
|
|
|
|
+ 339 ConstBlock
|
|
|
|
|
+ 340 = "CONST" { ConstDecl ";" } .
|
|
|
|
|
+ 341 ConstDecl (. VAR n: SymTab.Name;
|
|
|
|
|
+ 342 t: SymTab.TypeIndex;
|
|
|
|
|
+ 343 qv: QbeGen.QVal;
|
|
|
|
|
+ 344 cls: INTEGER; .)
|
|
|
|
|
+ 345 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
|
|
+ 346 SymTab.KindConst) THEN
|
|
|
|
|
+ 347 SemError(200) END; .)
|
|
|
|
|
+ 348 "="
|
|
|
|
|
+ 349 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
|
|
+ 350 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 351 IF cls = SymTab.ClStr THEN
|
|
|
|
|
+ 352 SemError(230)
|
|
|
|
|
+ 353 ELSIF ~QbeGen.IsImm(qv) THEN
|
|
|
|
|
+ 354 SemError(230) END;
|
|
|
|
|
+ 355 QbeGen.DeclConst(n, qv, t); .) .
|
|
|
|
|
+ 356 VarBlock
|
|
|
|
|
+ 357 = "VAR" { VarDecl ";" } .
|
|
|
|
|
+ 358 VarDecl (. VAR nm: SymTab.Name;
|
|
|
|
|
+ 359 t: SymTab.TypeIndex;
|
|
|
|
|
+ 360 i: CARDINAL;
|
|
|
|
|
+ 361 cls: INTEGER; .)
|
|
|
|
|
+ 362 = VarIdents ":"
|
|
|
|
|
+ 363 TypeIdent<t> (. cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 364 IF (t # SymTab.InvalidType)
|
|
|
|
|
+ 365 & (cls # SymTab.ClInt)
|
|
|
|
|
+ 366 & (cls # SymTab.ClBool)
|
|
|
|
|
+ 367 & (cls # SymTab.ClChar)
|
|
|
|
|
+ 368 & (cls # SymTab.ClReal) THEN
|
|
|
|
|
+ 369 SemError(230) END;
|
|
|
|
|
+ 370 i := 0;
|
|
|
|
|
+ 371 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 372 SymTab.PendName(i, nm);
|
|
|
|
|
+ 373 QbeGen.DeclVar(nm, t);
|
|
|
|
|
+ 374 INC(i)
|
|
|
|
|
+ 375 END;
|
|
|
|
|
+ 376 SymTab.FixPending(t); .) .
|
|
|
|
|
+ 377 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 378 = GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
|
|
+ 379 SymTab.KindVar) THEN
|
|
|
|
|
+ 380 SemError(200) END; .)
|
|
|
|
|
+ 381 { ","
|
|
|
|
|
+ 382 GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
|
|
+ 383 SymTab.KindVar) THEN
|
|
|
|
|
+ 384 SemError(200) END; .) } .
|
|
|
|
|
+ 385 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 386 = GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
+ 387 SemError(200) END; .)
|
|
|
|
|
+ 388 { "," GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
+ 389 SemError(200) END; .) } .
|
|
|
|
|
+ 390 (* Procedure headings enter now (scopes, params, result); bodies
|
|
|
|
|
+ 391 parse + check with one 230 at END (lowering = step 4).
|
|
|
|
|
+ 392 FORWARD marks; the body heading re-enters (signature compare
|
|
|
|
|
+ 393 tightens in step 4). *)
|
|
|
|
|
+ 394 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex; .)
|
|
|
|
|
+ 395 = "PROCEDURE"
|
|
|
|
|
+ 396 GetIdent<pn> (. IF ~SymTab.EnterProc(pn) THEN
|
|
|
|
|
+ 397 IF ~SymTab.ReenterProc(pn) THEN
|
|
|
|
|
+ 398 SemError(200) END
|
|
|
|
|
+ 399 END; .)
|
|
|
|
|
+ 400 [ FormalParams ]
|
|
|
|
|
+ 401 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t); .) ] .
|
|
|
|
|
+ 402 FormalParams
|
|
|
|
|
+ 403 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
|
|
+ 404 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 405 isV: BOOLEAN; .)
|
|
|
|
|
+ 406 = (. isV := FALSE; .)
|
|
|
|
|
+ 407 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
+ 408 ParIdents<isV> ":" TypeIdent<t> (. SymTab.FixPending(t); .) .
|
|
|
|
|
+ 409 ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
|
|
|
+ 410 = ProcHeading<pn> ";"
|
|
|
|
|
+ 411 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
+ 412 SymTab.CloseProc; .)
|
|
|
|
|
+ 413 | Block<pn> (. SymTab.CloseProc;
|
|
|
|
|
+ 414 SemError(230); .) ) .
|
|
|
|
|
+ 415 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
|
|
+ 416 = DeclSeq
|
|
|
|
|
+ 417 [ "BEGIN"
|
|
|
|
|
+ 418 [ StatSeq ] ]
|
|
|
|
|
+ 419 "END"
|
|
|
|
|
+ 420 GetIdent<m2> (. IF ~SymTab.Equal(pn, m2) THEN
|
|
|
|
|
+ 421 SemError(202) END; .) .
|
|
|
|
|
+ 422 StatSeq
|
|
|
|
|
+ 423 = Statement { ";" Statement } .
|
|
|
|
|
+ 424 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
|
|
+ 425 = Assign
|
|
|
|
|
+ 426 | IfStat
|
|
|
|
|
+ 427 | WhileStat
|
|
|
|
|
+ 428 | RepeatStat
|
|
|
|
|
+ 429 | LoopStat
|
|
|
|
|
+ 430 | ForStat
|
|
|
|
|
+ 431 | CaseStat
|
|
|
|
|
+ 432 | ReturnStat
|
|
|
|
|
+ 433 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
|
|
+ 434 QbeGen.Jmp(lx)
|
|
|
|
|
+ 435 ELSE SemError(230) END; .) .
|
|
|
|
|
+ 436 Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
|
|
|
+ 437 dk: INTEGER;
|
|
|
|
|
+ 438 qd, qe, qt: QbeGen.QVal;
|
|
|
|
|
+ 439 qn: SymTab.Name;
|
|
|
|
|
+ 440 isR, conv: BOOLEAN; .)
|
|
|
|
|
+ 441 = Design<dt, dk, qd, qn> ":="
|
|
|
|
|
+ 442 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 443 & (dk # SymTab.KindVar)
|
|
|
|
|
+ 444 & (dk # SymTab.KindParam) THEN
|
|
|
|
|
+ 445 SemError(210)
|
|
|
|
|
+ 446 ELSIF ~SymTab.Assignable(et,
|
|
|
|
|
+ 447 dt) THEN
|
|
|
|
|
+ 448 SemError(210) END;
|
|
|
|
|
+ 449 isR := (dt #
|
|
|
|
|
+ 450 SymTab.InvalidType)
|
|
|
|
|
+ 451 & (SymTab.ClassOf(dt)
|
|
|
|
|
+ 452 = SymTab.ClReal);
|
|
|
|
|
+ 453 conv := isR
|
|
|
|
|
+ 454 & SymTab.IsIntFamily(et);
|
|
|
|
|
+ 455 IF ((dk = SymTab.KindVar)
|
|
|
|
|
+ 456 OR (dk = SymTab.KindParam))
|
|
|
|
|
+ 457 & (dt # SymTab.InvalidType)
|
|
|
|
|
+ 458 & (et # SymTab.InvalidType) THEN
|
|
|
|
|
+ 459 IF conv THEN
|
|
|
|
|
+ 460 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
+ 461 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
|
|
+ 462 ELSE
|
|
|
|
|
+ 463 QbeGen.StoreVar(qn, qe, isR)
|
|
|
|
|
+ 464 END
|
|
|
|
|
+ 465 END; .) .
|
|
|
|
|
+ 466 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 467 q, lThen, lElse, lEnd:
|
|
|
|
|
+ 468 QbeGen.QVal;
|
|
|
|
|
+ 469 hasElse: BOOLEAN; .)
|
|
|
|
|
+ 470 = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
+ 471 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 472 SemError(214) END;
|
|
|
|
|
+ 473 QbeGen.NewLabel(lThen);
|
|
|
|
|
+ 474 QbeGen.NewLabel(lElse);
|
|
|
|
|
+ 475 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 476 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ 477 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ 478 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .)
|
|
|
|
|
+ 479 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 480 QbeGen.NewLabel(lElse); .)
|
|
|
|
|
+ 481 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 482 SemError(214) END;
|
|
|
|
|
+ 483 QbeGen.NewLabel(lThen);
|
|
|
|
|
+ 484 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ 485 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ 486 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
|
|
+ 487 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 488 hasElse := TRUE; .)
|
|
|
|
|
+ 489 StatSeq ]
|
|
|
|
|
+ 490 "END" (. IF hasElse THEN
|
|
|
|
|
+ 491 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ 492 ELSE QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 493 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ 494 END; .) .
|
|
|
|
|
+ 495 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 496 q, lTop, lBody, lEnd:
|
|
|
|
|
+ 497 QbeGen.QVal; .)
|
|
|
|
|
+ 498 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 499 QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 500 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 501 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 502 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 503 SemError(214) END;
|
|
|
|
|
+ 504 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
|
|
+ 505 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 506 "DO" StatSeq (. QbeGen.Jmp(lTop); .)
|
|
|
|
|
+ 507 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 508 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 509 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 510 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 511 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 512 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 513 StatSeq
|
|
|
|
|
+ 514 "UNTIL" Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 515 SemError(214) END;
|
|
|
|
|
+ 516 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
|
|
+ 517 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 518 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 519 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 520 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 521 QbeGen.PushLoop(lEnd);
|
|
|
|
|
+ 522 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 523 StatSeq
|
|
|
|
|
+ 524 "END" (. QbeGen.Jmp(lTop);
|
|
|
|
|
+ 525 QbeGen.PopLoop;
|
|
|
|
|
+ 526 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 527 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
+ 528 Runtime direction would need a compare-select; the literal
|
|
|
|
|
+ 529 sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
+ 530 ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
+ 531 tlo, thi, tby:
|
|
|
|
|
+ 532 SymTab.TypeIndex;
|
|
|
|
|
+ 533 qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
+ 534 QbeGen.QVal;
|
|
|
|
|
+ 535 lTop, lBody, lEnd:
|
|
|
|
|
+ 536 QbeGen.QVal;
|
|
|
|
|
+ 537 by: INTEGER;
|
|
|
|
|
+ 538 ok: BOOLEAN; .)
|
|
|
|
|
+ 539 = "FOR" (. by := 1; .)
|
|
|
|
|
+ 540 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
|
|
+ 541 IF ~ok THEN
|
|
|
|
|
+ 542 SemError(201)
|
|
|
|
|
+ 543 ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
+ 544 SymTab.KindVar)
|
|
|
|
|
+ 545 & (SymTab.SymKind(lv) #
|
|
|
|
|
+ 546 SymTab.KindParam) THEN
|
|
|
|
|
+ 547 SemError(220); ok := FALSE
|
|
|
|
|
+ 548 ELSIF ~SymTab.IsIntFamily(
|
|
|
|
|
+ 549 SymTab.SymType(lv)) THEN
|
|
|
|
|
+ 550 SemError(220); ok := FALSE
|
|
|
|
|
+ 551 END; .)
|
|
|
|
|
+ 552 ":=" Expr<tlo, qlo> (. IF ~SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
+ 553 SemError(220); ok := FALSE
|
|
|
|
|
+ 554 END; .)
|
|
|
|
|
+ 555 "TO" Expr<thi, qhi> (. IF ~SymTab.IsIntFamily(thi) THEN
|
|
|
|
|
+ 556 SemError(220); ok := FALSE
|
|
|
|
|
+ 557 END; .)
|
|
|
|
|
+ 558 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
|
|
+ 559 SymTab.InvalidType)
|
|
|
|
|
+ 560 & ~SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
+ 561 SemError(220); ok := FALSE
|
|
|
|
|
+ 562 END;
|
|
|
|
|
+ 563 IF ~SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
+ 564 SemError(230); by := 1
|
|
|
|
|
+ 565 ELSIF by = 0 THEN
|
|
|
|
|
+ 566 SemError(220); by := 1
|
|
|
|
|
+ 567 END; .) ]
|
|
|
|
|
+ 568 "DO" (. IF ok THEN
|
|
|
|
|
+ 569 QbeGen.StoreVar(lv, qlo,
|
|
|
|
|
+ 570 FALSE) END;
|
|
|
|
|
+ 571 QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 572 QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 573 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 574 QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ 575 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
+ 576 QbeGen.NewTemp(qk);
|
|
|
|
|
+ 577 IF by > 0 THEN
|
|
|
|
|
+ 578 QbeGen.Op3("cslew", qk,
|
|
|
|
|
+ 579 qt, qhi, FALSE)
|
|
|
|
|
+ 580 ELSE QbeGen.Op3("csgew", qk,
|
|
|
|
|
+ 581 qt, qhi, FALSE)
|
|
|
|
|
+ 582 END;
|
|
|
|
|
+ 583 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
|
|
+ 584 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 585 StatSeq
|
|
|
|
|
+ 586 "END" (. IF ok THEN
|
|
|
|
|
+ 587 QbeGen.LoadVar(lv, FALSE,
|
|
|
|
|
+ 588 qt);
|
|
|
|
|
+ 589 QbeGen.IntStr(by, qb);
|
|
|
|
|
+ 590 QbeGen.NewTemp(qk);
|
|
|
|
|
+ 591 QbeGen.Op3("add", qk,
|
|
|
|
|
+ 592 qt, qb, FALSE);
|
|
|
|
|
+ 593 QbeGen.StoreVar(lv, qk,
|
|
|
|
|
+ 594 FALSE) END;
|
|
|
|
|
+ 595 QbeGen.Jmp(lTop);
|
|
|
|
|
+ 596 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 597 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
+ 598 qsel, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 599 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
|
|
+ 600 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
|
|
+ 601 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
|
|
+ 602 [ "ELSE" StatSeq ]
|
|
|
|
|
+ 603 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 604 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
+ 605 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
+ 606 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
+ 607 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
+ 608 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 609 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
|
|
+ 610 = (. QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 611 QbeGen.NewLabel(lAfter); .)
|
|
|
|
|
+ 612 CaseLabel<tsel, qsel, lBody>
|
|
|
|
|
+ 613 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
|
|
+ 614 ":" (. QbeGen.Jmp(lAfter);
|
|
|
|
|
+ 615 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 616 StatSeq (. QbeGen.Jmp(lEnd);
|
|
|
|
|
+ 617 QbeGen.EmitLabel(lAfter); .) .
|
|
|
|
|
+ 618 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 619 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
+ 620 q2, q3, qc, qd, qe:
|
|
|
|
|
+ 621 QbeGen.QVal;
|
|
|
|
|
+ 622 lNext: QbeGen.QVal; .)
|
|
|
|
|
+ 623 = Expr<t2, q2> (. IF (t2 #
|
|
|
|
|
+ 624 SymTab.InvalidType)
|
|
|
|
|
+ 625 & (tsel #
|
|
|
|
|
+ 626 SymTab.InvalidType)
|
|
|
|
|
+ 627 & ~SymTab.EqCheck(t2,
|
|
|
|
|
+ 628 tsel) THEN
|
|
|
|
|
+ 629 SemError(213) END;
|
|
|
|
|
+ 630 IF ~QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 631 SemError(230);
|
|
|
|
|
+ 632 QbeGen.CopyOp("0", q2)
|
|
|
|
|
+ 633 END;
|
|
|
|
|
+ 634 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 635 QbeGen.Cmp(SymTab.OpEq,
|
|
|
|
|
+ 636 qsel, q2, qc, FALSE);
|
|
|
|
|
+ 637 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
|
|
+ 638 QbeGen.EmitLabel(lNext); .)
|
|
|
|
|
+ 639 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
|
|
+ 640 SymTab.InvalidType)
|
|
|
|
|
+ 641 & (tsel #
|
|
|
|
|
+ 642 SymTab.InvalidType)
|
|
|
|
|
+ 643 & ~SymTab.EqCheck(t3,
|
|
|
|
|
+ 644 tsel) THEN
|
|
|
|
|
+ 645 SemError(213) END;
|
|
|
|
|
+ 646 IF ~QbeGen.IsImm(q3) THEN
|
|
|
|
|
+ 647 SemError(230);
|
|
|
|
|
+ 648 QbeGen.CopyOp("0", q3)
|
|
|
|
|
+ 649 END;
|
|
|
|
|
+ 650 QbeGen.Cmp(SymTab.OpGe,
|
|
|
|
|
+ 651 qsel, q2, qc, FALSE);
|
|
|
|
|
+ 652 QbeGen.Cmp(SymTab.OpLe,
|
|
|
|
|
+ 653 qsel, q3, qd, FALSE);
|
|
|
|
|
+ 654 QbeGen.NewTemp(qe);
|
|
|
|
|
+ 655 QbeGen.Op3("and", qe, qc, qd,
|
|
|
|
|
+ 656 FALSE);
|
|
|
|
|
+ 657 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 658 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
|
|
+ 659 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
|
|
+ 660 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 661 q: QbeGen.QVal;
|
|
|
|
|
+ 662 res: SymTab.TypeIndex;
|
|
|
|
|
+ 663 hadE: BOOLEAN; .)
|
|
|
|
|
+ 664 = "RETURN" (. hadE := FALSE; .)
|
|
|
|
|
+ 665 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
|
|
+ 666 (. IF ~SymTab.InProc() THEN
|
|
|
|
|
+ 667 SemError(232)
|
|
|
|
|
+ 668 ELSE res := SymTab.CurRes();
|
|
|
|
|
+ 669 IF ~hadE THEN
|
|
|
|
|
+ 670 IF res #
|
|
|
|
|
+ 671 SymTab.InvalidType THEN
|
|
|
|
|
+ 672 SemError(232) END
|
|
|
|
|
+ 673 ELSIF (res =
|
|
|
|
|
+ 674 SymTab.InvalidType)
|
|
|
|
|
+ 675 OR (t #
|
|
|
|
|
+ 676 SymTab.InvalidType)
|
|
|
|
|
+ 677 & ~SymTab.Assignable(t,
|
|
|
|
|
+ 678 res) THEN
|
|
|
|
|
+ 679 SemError(232)
|
|
|
|
|
+ 680 END
|
|
|
|
|
+ 681 END; .) .
|
|
|
|
|
+ 682 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
+ 683 VAR q: QbeGen.QVal; VAR qn: SymTab.Name>
|
|
|
|
|
+ 684 (. VAR n: SymTab.Name;
|
|
|
|
|
+ 685 cls: INTEGER; .)
|
|
|
|
|
+ 686 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
|
|
|
|
|
+ 687 IF ~SymTab.Lookup(n) THEN
|
|
|
|
|
+ 688 SemError(201);
|
|
|
|
|
+ 689 t := SymTab.InvalidType;
|
|
|
|
|
+ 690 k := -1;
|
|
|
|
|
+ 691 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 692 ELSE
|
|
|
|
|
+ 693 t := SymTab.SymType(n);
|
|
|
|
|
+ 694 k := SymTab.SymKind(n);
|
|
|
|
|
+ 695 IF k = SymTab.KindConst THEN
|
|
|
|
|
+ 696 IF SymTab.Equal(n,
|
|
|
|
|
+ 697 "TRUE") THEN
|
|
|
|
|
+ 698 t := SymTab.BoolType();
|
|
|
|
|
+ 699 QbeGen.CopyOp("1", q)
|
|
|
|
|
+ 700 ELSIF SymTab.Equal(n,
|
|
|
|
|
+ 701 "FALSE") THEN
|
|
|
|
|
+ 702 t := SymTab.BoolType();
|
|
|
|
|
+ 703 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 704 ELSE
|
|
|
|
|
+ 705 cls :=
|
|
|
|
|
+ 706 SymTab.ClassOf(t);
|
|
|
|
|
+ 707 IF (t #
|
|
|
|
|
+ 708 SymTab.InvalidType)
|
|
|
|
|
+ 709 & ((cls = SymTab.ClInt)
|
|
|
|
|
+ 710 OR (cls
|
|
|
|
|
+ 711 = SymTab.ClChar)
|
|
|
|
|
+ 712 OR (cls
|
|
|
|
|
+ 713 = SymTab.ClReal)) THEN
|
|
|
|
|
+ 714 QbeGen.LoadVar(n,
|
|
|
|
|
+ 715 cls = SymTab.ClReal, q)
|
|
|
|
|
+ 716 ELSE
|
|
|
|
|
+ 717 IF t #
|
|
|
|
|
+ 718 SymTab.InvalidType THEN
|
|
|
|
|
+ 719 SemError(230)
|
|
|
|
|
+ 720 END;
|
|
|
|
|
+ 721 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 722 END
|
|
|
|
|
+ 723 END
|
|
|
|
|
+ 724 ELSIF (k = SymTab.KindVar)
|
|
|
|
|
+ 725 OR (k = SymTab.KindParam) THEN
|
|
|
|
|
+ 726 cls :=
|
|
|
|
|
+ 727 SymTab.ClassOf(t);
|
|
|
|
|
+ 728 IF (cls = SymTab.ClInt)
|
|
|
|
|
+ 729 OR (cls = SymTab.ClBool)
|
|
|
|
|
+ 730 OR (cls = SymTab.ClChar)
|
|
|
|
|
+ 731 OR (cls
|
|
|
|
|
+ 732 = SymTab.ClReal) THEN
|
|
|
|
|
+ 733 QbeGen.LoadVar(n,
|
|
|
|
|
+ 734 cls = SymTab.ClReal, q)
|
|
|
|
|
+ 735 ELSE SemError(230);
|
|
|
|
|
+ 736 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 737 END
|
|
|
|
|
+ 738 ELSE QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 739 IF (k = SymTab.KindImport)
|
|
|
|
|
+ 740 OR (k = SymTab.KindProc)
|
|
|
|
|
+ 741 OR (k
|
|
|
|
|
+ 742 = SymTab.KindField) THEN
|
|
|
|
|
+ 743 SemError(230)
|
|
|
|
|
+ 744 END
|
|
|
|
|
+ 745 END
|
|
|
|
|
+ 746 END; .) .
|
|
|
|
|
+ 747 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 748 (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ 749 op: INTEGER;
|
|
|
|
|
+ 750 q2, qt: QbeGen.QVal;
|
|
|
|
|
+ 751 isR: BOOLEAN; .)
|
|
|
|
|
+ 752 = SimExpr<t, q>
|
|
|
|
|
+ 753 [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
+ 754 (. IF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
+ 755 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 756 t := SymTab.BoolType()
|
|
|
|
|
+ 757 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
+ 758 isR := FALSE END;
|
|
|
|
|
+ 759 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 760 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
|
|
+ 761 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 762 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 763 END; .) ] .
|
|
|
|
|
+ 764 Rel<VAR op: INTEGER>
|
|
|
|
|
+ 765 = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
+ 766 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
+ 767 | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
+ 768 | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
+ 769 | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
+ 770 | ">=" (. op := SymTab.OpGe; .) .
|
|
|
|
|
+ 771 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 772 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
|
|
+ 773 op: INTEGER;
|
|
|
|
|
+ 774 q2, qt: QbeGen.QVal;
|
|
|
|
|
+ 775 neg, isR: BOOLEAN; .)
|
|
|
|
|
+ 776 = (. neg := FALSE; .)
|
|
|
|
|
+ 777 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
|
|
+ 778 Term<t, q> (. IF neg THEN
|
|
|
|
|
+ 779 IF QbeGen.IsImm(q) THEN
|
|
|
|
|
+ 780 QbeGen.NegFold(q, q)
|
|
|
|
|
+ 781 ELSE QbeGen.NewTemp(qt);
|
|
|
|
|
+ 782 QbeGen.NegQ(q, qt,
|
|
|
|
|
+ 783 SymTab.ClassOf(t)
|
|
|
|
|
+ 784 = SymTab.ClReal);
|
|
|
|
|
+ 785 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 786 END
|
|
|
|
|
+ 787 END; .)
|
|
|
|
|
+ 788 { AddOp<op> Term<t2, q2>
|
|
|
|
|
+ 789 (. IF op = SymTab.OpOr THEN
|
|
|
|
|
+ 790 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 791 t := SymTab.BoolType()
|
|
|
|
|
+ 792 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 793 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 794 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 795 QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
|
|
+ 796 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 797 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 798 END
|
|
|
|
|
+ 799 ELSE
|
|
|
|
|
+ 800 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
+ 801 t := res2
|
|
|
|
|
+ 802 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 803 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 804 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 805 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 806 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 807 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
|
|
+ 808 ELSE
|
|
|
|
|
+ 809 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
|
|
+ 810 END;
|
|
|
|
|
+ 811 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 812 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 813 END
|
|
|
|
|
+ 814 END; .) } .
|
|
|
|
|
+ 815 AddOp<VAR op: INTEGER>
|
|
|
|
|
+ 816 = "+" (. op := SymTab.OpAdd; .)
|
|
|
|
|
+ 817 | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
+ 818 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
|
|
+ 819 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 820 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
|
|
+ 821 op: INTEGER;
|
|
|
|
|
+ 822 q2, qt: QbeGen.QVal;
|
|
|
|
|
+ 823 isR: BOOLEAN; .)
|
|
|
|
|
+ 824 = Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
|
|
+ 825 (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ 826 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 827 t := SymTab.BoolType()
|
|
|
|
|
+ 828 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 829 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 830 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 831 QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
|
|
+ 832 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 833 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 834 END
|
|
|
|
|
+ 835 ELSE
|
|
|
|
|
+ 836 IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
+ 837 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
+ 838 res2) THEN t := res2
|
|
|
|
|
+ 839 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 840 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 841 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 842 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 843 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 844 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
|
|
+ 845 ELSIF (op = SymTab.OpDiv)
|
|
|
|
|
+ 846 OR (op = SymTab.OpSlash) THEN
|
|
|
|
|
+ 847 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
|
|
+ 848 ELSE
|
|
|
|
|
+ 849 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
|
|
+ 850 END;
|
|
|
|
|
+ 851 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 852 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 853 END
|
|
|
|
|
+ 854 END; .) } .
|
|
|
|
|
+ 855 MulOp<VAR op: INTEGER>
|
|
|
|
|
+ 856 = "*" (. op := SymTab.OpTimes; .)
|
|
|
|
|
+ 857 | "/" (. op := SymTab.OpSlash; .)
|
|
|
|
|
+ 858 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
|
|
+ 859 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
+ 860 | "AND" (. op := SymTab.OpAnd; .) .
|
|
|
|
|
+ 861 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 862 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
|
|
+ 863 et, dt, t2: SymTab.TypeIndex;
|
|
|
|
|
+ 864 dk: INTEGER;
|
|
|
|
|
+ 865 qd, q2: QbeGen.QVal;
|
|
|
|
|
+ 866 qn: SymTab.Name; .)
|
|
|
|
|
+ 867 = integer (. LexString(s);
|
|
|
|
|
+ 868 QbeGen.NormInt(s, q);
|
|
|
|
|
+ 869 t := SymTab.IntType(); .)
|
|
|
|
|
+ 870 | real (. LexString(s);
|
|
|
|
|
+ 871 QbeGen.NormReal(s, q);
|
|
|
|
|
+ 872 t := SymTab.RealType(); .)
|
|
|
|
|
+ 873 | string (. LexString(s);
|
|
|
|
|
+ 874 IF SymTab.StrLen(s) <= 3 THEN
|
|
|
|
|
+ 875 t := SymTab.CharType();
|
|
|
|
|
+ 876 QbeGen.IntStr(
|
|
|
|
|
+ 877 QbeGen.CharVal(s), q)
|
|
|
|
|
+ 878 ELSE t := SymTab.NewStr();
|
|
|
|
|
+ 879 SemError(230);
|
|
|
|
|
+ 880 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 881 END; .)
|
|
|
|
|
+ 882 | Design<dt, dk, qd, qn> (. t := dt;
|
|
|
|
|
+ 883 QbeGen.CopyOp(qd, q); .)
|
|
|
|
|
+ 884 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
|
|
+ 885 | "NOT" Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 886 t := SymTab.BoolType()
|
|
|
|
|
+ 887 ELSE SemError(212);
|
|
|
|
|
+ 888 t := SymTab.InvalidType END;
|
|
|
|
|
+ 889 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 890 QbeGen.NotQ(q2, q)
|
|
|
|
|
+ 891 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 892 END; .) .
|
|
|
|
|
+ 893 GetIdent<VAR n: SymTab.Name>
|
|
|
|
|
+ 894 = ident (. LexName(n); .) .
|
|
|
|
|
+ 895
|
|
|
|
|
+ 896 END M2.
|
|
|
|
|
+
|
|
|
|
|
+ 0 errors
|
|
|
|
|
+
|
|
|
|
|
|
|
|
Statistics:
|
|
Statistics:
|
|
|
|
|
|
|
|
- nr of terminals: 62 (limit 400)
|
|
|
|
|
- nr of non-terminals: 49 (limit 210)
|
|
|
|
|
- nr of pragmas: 0 (limit 438)
|
|
|
|
|
- nr of symbolnodes: 111 (limit 500)
|
|
|
|
|
- nr of graphnodes: 442 (limit 1500)
|
|
|
|
|
- nr of conditionsets: 5 (limit 100)
|
|
|
|
|
|
|
+ nr of terminals: 64 (limit 400)
|
|
|
|
|
+ nr of non-terminals: 57 (limit 210)
|
|
|
|
|
+ nr of pragmas: 0 (limit 436)
|
|
|
|
|
+ nr of symbolnodes: 121 (limit 500)
|
|
|
|
|
+ nr of graphnodes: 521 (limit 1500)
|
|
|
|
|
+ nr of conditionsets: 6 (limit 100)
|
|
|
nr of charactersets: 11 (limit 250)
|
|
nr of charactersets: 11 (limit 250)
|
|
|
|
|
|
|
|
|
|
|