|
|
@@ -10,10 +10,12 @@ COMPILER M2
|
|
|
|
|
|
Semantic errors reuse the V1/V2/Test2 family: 200 duplicate,
|
|
|
201 undeclared, 202 module name mismatch, 210 bad assignment,
|
|
|
- 211 bad arithmetic, 221 not a type, 230 construct not supported
|
|
|
- in step 1 (REAL/STRING literals, non-INTEGER VAR types,
|
|
|
- non-literal CONST expressions, imported names as values).
|
|
|
- Full language arrives in later steps; the 230s mark its edge. *)
|
|
|
+ 211 bad arithmetic, 221 not a type, 230 not supported yet,
|
|
|
+ 231 opaque type outside definition.
|
|
|
+ Scalar-phase TYPEs (named, integer subrange, enum) check fully;
|
|
|
+ composite forms wait for step 3. Procedure headings (formals,
|
|
|
+ result, FORWARD) enter scopes now; bodies parse + check with one
|
|
|
+ 230 at END (lowering = step 4). *)
|
|
|
|
|
|
IMPORT SymTab, QbeGen;
|
|
|
|
|
|
@@ -34,6 +36,7 @@ COMMENTS FROM "//" TO lf
|
|
|
TOKENS
|
|
|
ident = letter { letter | digit } .
|
|
|
integer = digit { digit }
|
|
|
+ | digit { digit } CONTEXT("..")
|
|
|
| "0x" hexDigit { hexDigit }
|
|
|
| "0X" hexDigit { hexDigit } .
|
|
|
real = digit { digit } "." { digit }
|
|
|
@@ -51,7 +54,7 @@ PRODUCTIONS
|
|
|
= DefUnit
|
|
|
| ImplUnit
|
|
|
| ProgModule .
|
|
|
- DefUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
= "DEFINITION" "MODULE"
|
|
|
GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
IF ~SymTab.Enter(m1,
|
|
|
@@ -59,7 +62,8 @@ PRODUCTIONS
|
|
|
SemError(200) END; .)
|
|
|
";"
|
|
|
{ Import }
|
|
|
- { ConstBlock | OpaqueBlock | VarBlock }
|
|
|
+ { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
+ | ProcHeading<pn> ";" (. SymTab.PopScope; .) }
|
|
|
"END"
|
|
|
GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
SemError(202) END; .)
|
|
|
@@ -101,7 +105,8 @@ PRODUCTIONS
|
|
|
(. QbeGen.EndModule;
|
|
|
SymTab.PrintTable; .) .
|
|
|
DeclSeq
|
|
|
- = { ConstBlock | VarBlock | NestedModule ";" } .
|
|
|
+ = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
+ | NestedModule ";" } .
|
|
|
(* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
lowering waits for step 4, marked by one 230 at END. *)
|
|
|
NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
@@ -149,14 +154,72 @@ PRODUCTIONS
|
|
|
SemError(200) END; .) } .
|
|
|
(* Opaque TYPE declarations (definition modules). The targetless
|
|
|
alias resolves to InvalidType until step 4 completes it. *)
|
|
|
- OpaqueBlock
|
|
|
- = "TYPE" { OpaqueDecl ";" } .
|
|
|
- OpaqueDecl (. VAR n: SymTab.Name; .)
|
|
|
+ (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
+ Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
+ Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
+ TypeBlock<isDef: BOOLEAN>
|
|
|
+ = "TYPE" { TypeItem<isDef> ";" } .
|
|
|
+ TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
+ t: SymTab.TypeIndex; .)
|
|
|
= GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
SymTab.KindType) THEN
|
|
|
- SemError(200) END;
|
|
|
+ SemError(200) END; .)
|
|
|
+ ( "=" Type<t> (. SymTab.SetSymType(n, t); .)
|
|
|
+ | (. IF ~isDef THEN
|
|
|
+ SemError(231) END;
|
|
|
SymTab.SetSymType(n,
|
|
|
- SymTab.NewAlias()); .) .
|
|
|
+ SymTab.NewAlias()); .) ) .
|
|
|
+ Type<VAR t: SymTab.TypeIndex>
|
|
|
+ = TypeIdent<t>
|
|
|
+ | Subrange<t>
|
|
|
+ | Enum<t> .
|
|
|
+ TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ k: INTEGER; .)
|
|
|
+ = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
+ SemError(201);
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ ELSE k := SymTab.SymKind(n);
|
|
|
+ IF (k = SymTab.KindType)
|
|
|
+ OR (k = SymTab.KindPredef) THEN
|
|
|
+ t := SymTab.SymType(n)
|
|
|
+ ELSIF k = SymTab.KindImport THEN
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ ELSE SemError(221);
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ END
|
|
|
+ END; .) .
|
|
|
+ Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ qlo, qhi: QbeGen.QVal;
|
|
|
+ lo, hi: INTEGER; .)
|
|
|
+ = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ (. IF (tlo = SymTab.InvalidType)
|
|
|
+ OR (thi = SymTab.InvalidType) THEN
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ ELSIF (SymTab.ClassOf(tlo) #
|
|
|
+ SymTab.ClInt)
|
|
|
+ OR (SymTab.ClassOf(thi) #
|
|
|
+ SymTab.ClInt) THEN
|
|
|
+ SemError(230);
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
+ OR ~SymTab.ConstInt(qhi, hi)
|
|
|
+ OR (lo > hi) THEN
|
|
|
+ SemError(230);
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ END; .)
|
|
|
+ "]" .
|
|
|
+ Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ = "(" (. t := SymTab.NewEnum(); .)
|
|
|
+ GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindConst) THEN
|
|
|
+ SemError(200) END;
|
|
|
+ SymTab.SetSymType(n, t); .)
|
|
|
+ { "," GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindConst) THEN
|
|
|
+ SemError(200) END;
|
|
|
+ SymTab.SetSymType(n, t); .) }
|
|
|
+ ")" .
|
|
|
ConstBlock
|
|
|
= "CONST" { ConstDecl ";" } .
|
|
|
ConstDecl (. VAR n: SymTab.Name;
|
|
|
@@ -176,23 +239,12 @@ PRODUCTIONS
|
|
|
QbeGen.DeclConst(n, qv, t); .) .
|
|
|
VarBlock
|
|
|
= "VAR" { VarDecl ";" } .
|
|
|
- VarDecl (. VAR n, nm: SymTab.Name;
|
|
|
+ VarDecl (. VAR nm: SymTab.Name;
|
|
|
t: SymTab.TypeIndex;
|
|
|
i: CARDINAL;
|
|
|
cls: INTEGER; .)
|
|
|
= VarIdents ":"
|
|
|
- GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
- SemError(201);
|
|
|
- t := SymTab.InvalidType
|
|
|
- ELSIF (SymTab.SymKind(n) #
|
|
|
- SymTab.KindType)
|
|
|
- & (SymTab.SymKind(n) #
|
|
|
- SymTab.KindPredef) THEN
|
|
|
- SemError(221);
|
|
|
- t := SymTab.InvalidType
|
|
|
- ELSE t := SymTab.SymType(n)
|
|
|
- END;
|
|
|
- cls := SymTab.ClassOf(t);
|
|
|
+ TypeIdent<t> (. cls := SymTab.ClassOf(t);
|
|
|
IF (t # SymTab.InvalidType)
|
|
|
& (cls # SymTab.ClInt) THEN
|
|
|
SemError(230) END;
|
|
|
@@ -211,6 +263,43 @@ PRODUCTIONS
|
|
|
GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
SymTab.KindVar) THEN
|
|
|
SemError(200) END; .) } .
|
|
|
+ ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ = GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
+ SemError(200) END; .)
|
|
|
+ { "," GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
+ SemError(200) END; .) } .
|
|
|
+ (* Procedure headings enter now (scopes, params, result); bodies
|
|
|
+ parse + check with one 230 at END (lowering = step 4).
|
|
|
+ FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ tightens in step 4). *)
|
|
|
+ ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex; .)
|
|
|
+ = "PROCEDURE"
|
|
|
+ GetIdent<pn> (. IF ~SymTab.EnterProc(pn) THEN
|
|
|
+ IF ~SymTab.ReenterProc(pn) THEN
|
|
|
+ SemError(200) END
|
|
|
+ END; .)
|
|
|
+ [ FormalParams ]
|
|
|
+ [ ":" TypeIdent<t> (. SymTab.SetProcRes(t); .) ] .
|
|
|
+ FormalParams
|
|
|
+ = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ isV: BOOLEAN; .)
|
|
|
+ = (. isV := FALSE; .)
|
|
|
+ [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ ParIdents<isV> ":" TypeIdent<t> (. SymTab.FixPending(t); .) .
|
|
|
+ ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
|
+ = ProcHeading<pn> ";"
|
|
|
+ ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ SymTab.PopScope; .)
|
|
|
+ | Block<pn> (. SymTab.PopScope;
|
|
|
+ SemError(230); .) ) .
|
|
|
+ Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ = DeclSeq
|
|
|
+ [ "BEGIN"
|
|
|
+ [ StatSeq ] ]
|
|
|
+ "END"
|
|
|
+ GetIdent<m2> (. IF ~SymTab.Equal(pn, m2) THEN
|
|
|
+ SemError(202) END; .) .
|
|
|
StatSeq
|
|
|
= Statement { ";" Statement } .
|
|
|
Statement
|
|
|
@@ -221,12 +310,14 @@ PRODUCTIONS
|
|
|
qn: SymTab.Name; .)
|
|
|
= Design<dt, dk, qd, qn> ":="
|
|
|
Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
- & (dk # SymTab.KindVar) THEN
|
|
|
+ & (dk # SymTab.KindVar)
|
|
|
+ & (dk # SymTab.KindParam) THEN
|
|
|
SemError(210)
|
|
|
ELSIF ~SymTab.Assignable(et,
|
|
|
dt) THEN
|
|
|
SemError(210) END;
|
|
|
- IF (dk = SymTab.KindVar)
|
|
|
+ IF ((dk = SymTab.KindVar)
|
|
|
+ OR (dk = SymTab.KindParam))
|
|
|
& (dt # SymTab.InvalidType)
|
|
|
& (et # SymTab.InvalidType) THEN
|
|
|
QbeGen.StoreVar(qn, qe, FALSE)
|
|
|
@@ -264,23 +355,29 @@ PRODUCTIONS
|
|
|
QbeGen.LoadVar(n,
|
|
|
FALSE, q)
|
|
|
ELSE
|
|
|
+ IF t #
|
|
|
+ SymTab.InvalidType THEN
|
|
|
+ SemError(230)
|
|
|
+ END;
|
|
|
QbeGen.CopyOp("0", q)
|
|
|
END
|
|
|
END
|
|
|
- ELSIF k = SymTab.KindVar THEN
|
|
|
- cls :=
|
|
|
- SymTab.ClassOf(t);
|
|
|
- IF cls = SymTab.ClInt THEN
|
|
|
- QbeGen.LoadVar(n,
|
|
|
- FALSE, q)
|
|
|
- ELSE SemError(230);
|
|
|
- QbeGen.CopyOp("0", q)
|
|
|
- END
|
|
|
- ELSE QbeGen.CopyOp("0", q);
|
|
|
- IF k = SymTab.KindImport THEN
|
|
|
- SemError(230)
|
|
|
- END
|
|
|
- END
|
|
|
+ ELSIF (k = SymTab.KindVar)
|
|
|
+ OR (k = SymTab.KindParam) THEN
|
|
|
+ cls :=
|
|
|
+ SymTab.ClassOf(t);
|
|
|
+ IF cls = SymTab.ClInt THEN
|
|
|
+ QbeGen.LoadVar(n,
|
|
|
+ FALSE, q)
|
|
|
+ ELSE SemError(230);
|
|
|
+ QbeGen.CopyOp("0", q)
|
|
|
+ END
|
|
|
+ ELSE QbeGen.CopyOp("0", q);
|
|
|
+ IF (k = SymTab.KindImport)
|
|
|
+ OR (k = SymTab.KindProc) THEN
|
|
|
+ SemError(230)
|
|
|
+ END
|
|
|
+ END
|
|
|
END; .) .
|
|
|
Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
= SimExpr<t, q> .
|