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