|
@@ -13,9 +13,15 @@ COMPILER M2
|
|
|
211 bad arithmetic, 221 not a type, 230 not supported yet,
|
|
211 bad arithmetic, 221 not a type, 230 not supported yet,
|
|
|
231 opaque type outside definition.
|
|
231 opaque type outside definition.
|
|
|
Scalar-phase TYPEs (named, integer subrange, enum) check fully;
|
|
Scalar-phase TYPEs (named, integer subrange, enum) check fully;
|
|
|
- composite forms wait for step 3. Procedure headings (formals,
|
|
|
|
|
|
|
+ composite forms wait for step 3. Procedure headings (formals,
|
|
|
result, FORWARD) enter scopes now; bodies parse + check with one
|
|
result, FORWARD) enter scopes now; bodies parse + check with one
|
|
|
- 230 at END (lowering = step 4). *)
|
|
|
|
|
|
|
+ 230 at END (lowering = step 4).
|
|
|
|
|
+ Statements: assignment, IF/ELSIF/ELSE, WHILE, REPEAT/UNTIL,
|
|
|
|
|
+ LOOP/EXIT (230 outside LOOP), FOR/TO/static-sign-BY, full CASE
|
|
|
|
|
+ (labels, ranges, ELSE; compare-chain), RETURN with 232 checks
|
|
|
|
|
+ (outside proc / value mismatch / missing value). WITH waits for
|
|
|
|
|
+ records (step 3). Boolean connectives are eager (or/and/xor);
|
|
|
|
|
+ relations yield 0/1 via cXXw. *)
|
|
|
|
|
|
|
|
IMPORT SymTab, QbeGen;
|
|
IMPORT SymTab, QbeGen;
|
|
|
|
|
|
|
@@ -63,7 +69,7 @@ PRODUCTIONS
|
|
|
";"
|
|
";"
|
|
|
{ Import }
|
|
{ Import }
|
|
|
{ ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
{ ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
- | ProcHeading<pn> ";" (. SymTab.PopScope; .) }
|
|
|
|
|
|
|
+ | ProcHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
"END"
|
|
"END"
|
|
|
GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
SemError(202) END; .)
|
|
SemError(202) END; .)
|
|
@@ -246,7 +252,9 @@ PRODUCTIONS
|
|
|
= VarIdents ":"
|
|
= VarIdents ":"
|
|
|
TypeIdent<t> (. cls := SymTab.ClassOf(t);
|
|
TypeIdent<t> (. cls := SymTab.ClassOf(t);
|
|
|
IF (t # SymTab.InvalidType)
|
|
IF (t # SymTab.InvalidType)
|
|
|
- & (cls # SymTab.ClInt) THEN
|
|
|
|
|
|
|
+ & (cls # SymTab.ClInt)
|
|
|
|
|
+ & (cls # SymTab.ClBool)
|
|
|
|
|
+ & (cls # SymTab.ClChar) THEN
|
|
|
SemError(230) END;
|
|
SemError(230) END;
|
|
|
i := 0;
|
|
i := 0;
|
|
|
WHILE i < SymTab.PendCount() DO
|
|
WHILE i < SymTab.PendCount() DO
|
|
@@ -290,8 +298,8 @@ PRODUCTIONS
|
|
|
ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
|
= ProcHeading<pn> ";"
|
|
= ProcHeading<pn> ";"
|
|
|
( "FORWARD" (. SymTab.MarkFwd;
|
|
( "FORWARD" (. SymTab.MarkFwd;
|
|
|
- SymTab.PopScope; .)
|
|
|
|
|
- | Block<pn> (. SymTab.PopScope;
|
|
|
|
|
|
|
+ SymTab.CloseProc; .)
|
|
|
|
|
+ | Block<pn> (. SymTab.CloseProc;
|
|
|
SemError(230); .) ) .
|
|
SemError(230); .) ) .
|
|
|
Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
= DeclSeq
|
|
= DeclSeq
|
|
@@ -302,8 +310,18 @@ PRODUCTIONS
|
|
|
SemError(202) END; .) .
|
|
SemError(202) END; .) .
|
|
|
StatSeq
|
|
StatSeq
|
|
|
= Statement { ";" Statement } .
|
|
= Statement { ";" Statement } .
|
|
|
- Statement
|
|
|
|
|
- = Assign .
|
|
|
|
|
|
|
+ Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
|
|
+ = Assign
|
|
|
|
|
+ | IfStat
|
|
|
|
|
+ | WhileStat
|
|
|
|
|
+ | RepeatStat
|
|
|
|
|
+ | LoopStat
|
|
|
|
|
+ | ForStat
|
|
|
|
|
+ | CaseStat
|
|
|
|
|
+ | ReturnStat
|
|
|
|
|
+ | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
|
|
+ QbeGen.Jmp(lx)
|
|
|
|
|
+ ELSE SemError(230) END; .) .
|
|
|
Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
|
dk: INTEGER;
|
|
dk: INTEGER;
|
|
|
qd, qe: QbeGen.QVal;
|
|
qd, qe: QbeGen.QVal;
|
|
@@ -322,8 +340,222 @@ PRODUCTIONS
|
|
|
& (et # SymTab.InvalidType) THEN
|
|
& (et # SymTab.InvalidType) THEN
|
|
|
QbeGen.StoreVar(qn, qe, FALSE)
|
|
QbeGen.StoreVar(qn, qe, FALSE)
|
|
|
END; .) .
|
|
END; .) .
|
|
|
- (* Designator, step-1 form: scalar variables and constants only.
|
|
|
|
|
- No suffixes (field/index/deref are syntax errors in step 1). *)
|
|
|
|
|
|
|
+ IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ q, lThen, lElse, lEnd:
|
|
|
|
|
+ QbeGen.QVal;
|
|
|
|
|
+ hasElse: BOOLEAN; .)
|
|
|
|
|
+ = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
+ Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ SemError(214) END;
|
|
|
|
|
+ QbeGen.NewLabel(lThen);
|
|
|
|
|
+ QbeGen.NewLabel(lElse);
|
|
|
|
|
+ QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ "THEN" StatSeq (. QbeGen.Jmp(lEnd); .)
|
|
|
|
|
+ { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ QbeGen.NewLabel(lElse); .)
|
|
|
|
|
+ Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ SemError(214) END;
|
|
|
|
|
+ QbeGen.NewLabel(lThen);
|
|
|
|
|
+ QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
|
|
+ [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ hasElse := TRUE; .)
|
|
|
|
|
+ StatSeq ]
|
|
|
|
|
+ "END" (. IF hasElse THEN
|
|
|
|
|
+ QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSE QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ END; .) .
|
|
|
|
|
+ WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ q, lTop, lBody, lEnd:
|
|
|
|
|
+ QbeGen.QVal; .)
|
|
|
|
|
+ = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ QbeGen.NewLabel(lBody);
|
|
|
|
|
+ QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ SemError(214) END;
|
|
|
|
|
+ QbeGen.Jnz(q, lBody, lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ "DO" StatSeq (. QbeGen.Jmp(lTop); .)
|
|
|
|
|
+ "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ StatSeq
|
|
|
|
|
+ "UNTIL" Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ SemError(214) END;
|
|
|
|
|
+ QbeGen.Jnz(q, lEnd, lTop);
|
|
|
|
|
+ QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.PushLoop(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ StatSeq
|
|
|
|
|
+ "END" (. QbeGen.Jmp(lTop);
|
|
|
|
|
+ QbeGen.PopLoop;
|
|
|
|
|
+ QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
+ Runtime direction would need a compare-select; the literal
|
|
|
|
|
+ sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
+ ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
+ tlo, thi, tby:
|
|
|
|
|
+ SymTab.TypeIndex;
|
|
|
|
|
+ qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
+ QbeGen.QVal;
|
|
|
|
|
+ lTop, lBody, lEnd:
|
|
|
|
|
+ QbeGen.QVal;
|
|
|
|
|
+ by: INTEGER;
|
|
|
|
|
+ ok: BOOLEAN; .)
|
|
|
|
|
+ = "FOR" (. by := 1; .)
|
|
|
|
|
+ GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
|
|
+ IF ~ok THEN
|
|
|
|
|
+ SemError(201)
|
|
|
|
|
+ ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
+ SymTab.KindVar)
|
|
|
|
|
+ & (SymTab.SymKind(lv) #
|
|
|
|
|
+ SymTab.KindParam) THEN
|
|
|
|
|
+ SemError(220); ok := FALSE
|
|
|
|
|
+ ELSIF ~SymTab.IsIntFamily(
|
|
|
|
|
+ SymTab.SymType(lv)) THEN
|
|
|
|
|
+ SemError(220); ok := FALSE
|
|
|
|
|
+ END; .)
|
|
|
|
|
+ ":=" Expr<tlo, qlo> (. IF ~SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
+ SemError(220); ok := FALSE
|
|
|
|
|
+ END; .)
|
|
|
|
|
+ "TO" Expr<thi, qhi> (. IF ~SymTab.IsIntFamily(thi) THEN
|
|
|
|
|
+ SemError(220); ok := FALSE
|
|
|
|
|
+ END; .)
|
|
|
|
|
+ [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & ~SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
+ SemError(220); ok := FALSE
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF ~SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
+ SemError(230); by := 1
|
|
|
|
|
+ ELSIF by = 0 THEN
|
|
|
|
|
+ SemError(220); by := 1
|
|
|
|
|
+ END; .) ]
|
|
|
|
|
+ "DO" (. IF ok THEN
|
|
|
|
|
+ QbeGen.StoreVar(lv, qlo,
|
|
|
|
|
+ FALSE) END;
|
|
|
|
|
+ QbeGen.NewLabel(lTop);
|
|
|
|
|
+ QbeGen.NewLabel(lBody);
|
|
|
|
|
+ QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
+ QbeGen.NewTemp(qk);
|
|
|
|
|
+ IF by > 0 THEN
|
|
|
|
|
+ QbeGen.Op3("cslew", qk,
|
|
|
|
|
+ qt, qhi, FALSE)
|
|
|
|
|
+ ELSE QbeGen.Op3("csgew", qk,
|
|
|
|
|
+ qt, qhi, FALSE)
|
|
|
|
|
+ END;
|
|
|
|
|
+ QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ StatSeq
|
|
|
|
|
+ "END" (. IF ok THEN
|
|
|
|
|
+ QbeGen.LoadVar(lv, FALSE,
|
|
|
|
|
+ qt);
|
|
|
|
|
+ QbeGen.IntStr(by, qb);
|
|
|
|
|
+ QbeGen.NewTemp(qk);
|
|
|
|
|
+ QbeGen.Op3("add", qk,
|
|
|
|
|
+ qt, qb, FALSE);
|
|
|
|
|
+ QbeGen.StoreVar(lv, qk,
|
|
|
|
|
+ FALSE) END;
|
|
|
|
|
+ QbeGen.Jmp(lTop);
|
|
|
|
|
+ QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
+ qsel, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
|
|
+ "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
|
|
+ { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
|
|
+ [ "ELSE" StatSeq ]
|
|
|
|
|
+ "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
+ with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
+ "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
+ lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
+ CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
|
|
+ = (. QbeGen.NewLabel(lBody);
|
|
|
|
|
+ QbeGen.NewLabel(lAfter); .)
|
|
|
|
|
+ CaseLabel<tsel, qsel, lBody>
|
|
|
|
|
+ { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
|
|
+ ":" (. QbeGen.Jmp(lAfter);
|
|
|
|
|
+ QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ StatSeq (. QbeGen.Jmp(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lAfter); .) .
|
|
|
|
|
+ CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
+ q2, q3, qc, qd, qe:
|
|
|
|
|
+ QbeGen.QVal;
|
|
|
|
|
+ lNext: QbeGen.QVal; .)
|
|
|
|
|
+ = Expr<t2, q2> (. IF (t2 #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & (tsel #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & ~SymTab.EqCheck(t2,
|
|
|
|
|
+ tsel) THEN
|
|
|
|
|
+ SemError(213) END;
|
|
|
|
|
+ IF ~QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ SemError(230);
|
|
|
|
|
+ QbeGen.CopyOp("0", q2)
|
|
|
|
|
+ END;
|
|
|
|
|
+ QbeGen.NewLabel(lNext);
|
|
|
|
|
+ QbeGen.Cmp(SymTab.OpEq,
|
|
|
|
|
+ qsel, q2, qc, FALSE);
|
|
|
|
|
+ QbeGen.Jnz(qc, lBody, lNext);
|
|
|
|
|
+ QbeGen.EmitLabel(lNext); .)
|
|
|
|
|
+ [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & (tsel #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & ~SymTab.EqCheck(t3,
|
|
|
|
|
+ tsel) THEN
|
|
|
|
|
+ SemError(213) END;
|
|
|
|
|
+ IF ~QbeGen.IsImm(q3) THEN
|
|
|
|
|
+ SemError(230);
|
|
|
|
|
+ QbeGen.CopyOp("0", q3)
|
|
|
|
|
+ END;
|
|
|
|
|
+ QbeGen.Cmp(SymTab.OpGe,
|
|
|
|
|
+ qsel, q2, qc, FALSE);
|
|
|
|
|
+ QbeGen.Cmp(SymTab.OpLe,
|
|
|
|
|
+ qsel, q3, qd, FALSE);
|
|
|
|
|
+ QbeGen.NewTemp(qe);
|
|
|
|
|
+ QbeGen.Op3("and", qe, qc, qd,
|
|
|
|
|
+ FALSE);
|
|
|
|
|
+ QbeGen.NewLabel(lNext);
|
|
|
|
|
+ QbeGen.Jnz(qe, lBody, lNext);
|
|
|
|
|
+ QbeGen.EmitLabel(lNext); .) ] .
|
|
|
|
|
+ ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ q: QbeGen.QVal;
|
|
|
|
|
+ res: SymTab.TypeIndex;
|
|
|
|
|
+ hadE: BOOLEAN; .)
|
|
|
|
|
+ = "RETURN" (. hadE := FALSE; .)
|
|
|
|
|
+ [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
|
|
+ (. IF ~SymTab.InProc() THEN
|
|
|
|
|
+ SemError(232)
|
|
|
|
|
+ ELSE res := SymTab.CurRes();
|
|
|
|
|
+ IF ~hadE THEN
|
|
|
|
|
+ IF res #
|
|
|
|
|
+ SymTab.InvalidType THEN
|
|
|
|
|
+ SemError(232) END
|
|
|
|
|
+ ELSIF (res =
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ OR (t #
|
|
|
|
|
+ SymTab.InvalidType)
|
|
|
|
|
+ & ~SymTab.Assignable(t,
|
|
|
|
|
+ res) THEN
|
|
|
|
|
+ SemError(232)
|
|
|
|
|
+ END
|
|
|
|
|
+ END; .) .
|
|
|
Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
VAR q: QbeGen.QVal; VAR qn: SymTab.Name>
|
|
VAR q: QbeGen.QVal; VAR qn: SymTab.Name>
|
|
|
(. VAR n: SymTab.Name;
|
|
(. VAR n: SymTab.Name;
|
|
@@ -351,7 +583,9 @@ PRODUCTIONS
|
|
|
SymTab.ClassOf(t);
|
|
SymTab.ClassOf(t);
|
|
|
IF (t #
|
|
IF (t #
|
|
|
SymTab.InvalidType)
|
|
SymTab.InvalidType)
|
|
|
- & (cls = SymTab.ClInt) THEN
|
|
|
|
|
|
|
+ & ((cls = SymTab.ClInt)
|
|
|
|
|
+ OR (cls
|
|
|
|
|
+ = SymTab.ClChar)) THEN
|
|
|
QbeGen.LoadVar(n,
|
|
QbeGen.LoadVar(n,
|
|
|
FALSE, q)
|
|
FALSE, q)
|
|
|
ELSE
|
|
ELSE
|
|
@@ -366,7 +600,9 @@ PRODUCTIONS
|
|
|
OR (k = SymTab.KindParam) THEN
|
|
OR (k = SymTab.KindParam) THEN
|
|
|
cls :=
|
|
cls :=
|
|
|
SymTab.ClassOf(t);
|
|
SymTab.ClassOf(t);
|
|
|
- IF cls = SymTab.ClInt THEN
|
|
|
|
|
|
|
+ IF (cls = SymTab.ClInt)
|
|
|
|
|
+ OR (cls = SymTab.ClBool)
|
|
|
|
|
+ OR (cls = SymTab.ClChar) THEN
|
|
|
QbeGen.LoadVar(n,
|
|
QbeGen.LoadVar(n,
|
|
|
FALSE, q)
|
|
FALSE, q)
|
|
|
ELSE SemError(230);
|
|
ELSE SemError(230);
|
|
@@ -380,7 +616,26 @@ PRODUCTIONS
|
|
|
END
|
|
END
|
|
|
END; .) .
|
|
END; .) .
|
|
|
Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- = SimExpr<t, q> .
|
|
|
|
|
|
|
+ (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ op: INTEGER;
|
|
|
|
|
+ q2, qt: QbeGen.QVal; .)
|
|
|
|
|
+ = SimExpr<t, q>
|
|
|
|
|
+ [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
+ (. IF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
+ t := SymTab.BoolType()
|
|
|
|
|
+ ELSE SemError(213); t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.Cmp(op, q, q2, qt, FALSE);
|
|
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END; .) ] .
|
|
|
|
|
+ Rel<VAR op: INTEGER>
|
|
|
|
|
+ = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
+ | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
+ | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
+ | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
+ | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
+ | ">=" (. op := SymTab.OpGe; .) .
|
|
|
SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
op: INTEGER;
|
|
@@ -397,52 +652,78 @@ PRODUCTIONS
|
|
|
END
|
|
END
|
|
|
END; .)
|
|
END; .)
|
|
|
{ AddOp<op> Term<t2, q2>
|
|
{ AddOp<op> Term<t2, q2>
|
|
|
- (. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
- t := res2
|
|
|
|
|
- ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- IF t # SymTab.InvalidType THEN
|
|
|
|
|
- QbeGen.NewTemp(qt);
|
|
|
|
|
- IF op = SymTab.OpAdd THEN
|
|
|
|
|
- QbeGen.Op3("add", qt, q, q2, FALSE)
|
|
|
|
|
- ELSE
|
|
|
|
|
- QbeGen.Op3("sub", qt, q, q2, FALSE)
|
|
|
|
|
- END;
|
|
|
|
|
- QbeGen.CopyOp(qt, q)
|
|
|
|
|
- ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
|
|
+ (. IF op = SymTab.OpOr THEN
|
|
|
|
|
+ IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ t := SymTab.BoolType()
|
|
|
|
|
+ ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.NewTemp(qt);
|
|
|
|
|
+ QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
+ t := res2
|
|
|
|
|
+ ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.NewTemp(qt);
|
|
|
|
|
+ IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ QbeGen.Op3("add", qt, q, q2, FALSE)
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ QbeGen.Op3("sub", qt, q, q2, FALSE)
|
|
|
|
|
+ END;
|
|
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END
|
|
|
END; .) } .
|
|
END; .) } .
|
|
|
AddOp<VAR op: INTEGER>
|
|
AddOp<VAR op: INTEGER>
|
|
|
= "+" (. op := SymTab.OpAdd; .)
|
|
= "+" (. op := SymTab.OpAdd; .)
|
|
|
- | "-" (. op := SymTab.OpSub; .) .
|
|
|
|
|
|
|
+ | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
+ | "OR" (. op := SymTab.OpOr; .) .
|
|
|
Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
op: INTEGER;
|
|
|
q2, qt: QbeGen.QVal; .)
|
|
q2, qt: QbeGen.QVal; .)
|
|
|
= Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
= Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
- (. IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
- (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
- res2) THEN t := res2
|
|
|
|
|
- ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- IF t # SymTab.InvalidType THEN
|
|
|
|
|
- QbeGen.NewTemp(qt);
|
|
|
|
|
- IF op = SymTab.OpTimes THEN
|
|
|
|
|
- QbeGen.Op3("mul", qt, q, q2, FALSE)
|
|
|
|
|
- ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
- QbeGen.Op3("div", qt, q, q2, FALSE)
|
|
|
|
|
- ELSE
|
|
|
|
|
- QbeGen.Op3("rem", qt, q, q2, FALSE)
|
|
|
|
|
- END;
|
|
|
|
|
- QbeGen.CopyOp(qt, q)
|
|
|
|
|
- ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
|
|
+ (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ t := SymTab.BoolType()
|
|
|
|
|
+ ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.NewTemp(qt);
|
|
|
|
|
+ QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
+ (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
+ res2) THEN t := res2
|
|
|
|
|
+ ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.NewTemp(qt);
|
|
|
|
|
+ IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ QbeGen.Op3("mul", qt, q, q2, FALSE)
|
|
|
|
|
+ ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
+ QbeGen.Op3("div", qt, q, q2, FALSE)
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ QbeGen.Op3("rem", qt, q, q2, FALSE)
|
|
|
|
|
+ END;
|
|
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END
|
|
|
END; .) } .
|
|
END; .) } .
|
|
|
MulOp<VAR op: INTEGER>
|
|
MulOp<VAR op: INTEGER>
|
|
|
= "*" (. op := SymTab.OpTimes; .)
|
|
= "*" (. op := SymTab.OpTimes; .)
|
|
|
| "DIV" (. op := SymTab.OpDiv; .)
|
|
| "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- | "MOD" (. op := SymTab.OpMod; .) .
|
|
|
|
|
|
|
+ | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
+ | "AND" (. op := SymTab.OpAnd; .) .
|
|
|
Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
(. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
(. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- et, dt: SymTab.TypeIndex;
|
|
|
|
|
|
|
+ et, dt, t2: SymTab.TypeIndex;
|
|
|
dk: INTEGER;
|
|
dk: INTEGER;
|
|
|
- qd: QbeGen.QVal;
|
|
|
|
|
|
|
+ qd, q2: QbeGen.QVal;
|
|
|
qn: SymTab.Name; .)
|
|
qn: SymTab.Name; .)
|
|
|
= integer (. LexString(s);
|
|
= integer (. LexString(s);
|
|
|
QbeGen.NormInt(s, q);
|
|
QbeGen.NormInt(s, q);
|
|
@@ -462,7 +743,15 @@ PRODUCTIONS
|
|
|
END; .)
|
|
END; .)
|
|
|
| Design<dt, dk, qd, qn> (. t := dt;
|
|
| Design<dt, dk, qd, qn> (. t := dt;
|
|
|
QbeGen.CopyOp(qd, q); .)
|
|
QbeGen.CopyOp(qd, q); .)
|
|
|
- | "(" Expr<et, q> ")" (. t := et; .) .
|
|
|
|
|
|
|
+ | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
|
|
+ | "NOT" Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ t := SymTab.BoolType()
|
|
|
|
|
+ ELSE SemError(212);
|
|
|
|
|
+ t := SymTab.InvalidType END;
|
|
|
|
|
+ IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ QbeGen.NotQ(q2, q)
|
|
|
|
|
+ ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END; .) .
|
|
|
GetIdent<VAR n: SymTab.Name>
|
|
GetIdent<VAR n: SymTab.Name>
|
|
|
= ident (. LexName(n); .) .
|
|
= ident (. LexName(n); .) .
|
|
|
|
|
|