|
|
@@ -42,21 +42,121 @@ TOKENS
|
|
|
| '"' { noQuote2 } '"' .
|
|
|
|
|
|
PRODUCTIONS
|
|
|
- M2 (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ M2
|
|
|
+ = Unit "." .
|
|
|
+ (* Units: program modules compile fully; DEFINITION and
|
|
|
+ IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
+ (each ends with one 230); same for nested local modules. *)
|
|
|
+ Unit
|
|
|
+ = DefUnit
|
|
|
+ | ImplUnit
|
|
|
+ | ProgModule .
|
|
|
+ DefUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ = "DEFINITION" "MODULE"
|
|
|
+ GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
+ IF ~SymTab.Enter(m1,
|
|
|
+ SymTab.KindModule) THEN
|
|
|
+ SemError(200) END; .)
|
|
|
+ ";"
|
|
|
+ { Import }
|
|
|
+ { ConstBlock | OpaqueBlock | VarBlock }
|
|
|
+ "END"
|
|
|
+ GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ SemError(202) END; .)
|
|
|
+ (. QbeGen.CloseModule;
|
|
|
+ SemError(230);
|
|
|
+ SymTab.PrintTable; .) .
|
|
|
+ ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ = "IMPLEMENTATION" "MODULE"
|
|
|
+ GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
+ IF ~SymTab.Enter(m1,
|
|
|
+ SymTab.KindModule) THEN
|
|
|
+ SemError(200) END; .)
|
|
|
+ ";"
|
|
|
+ { Import }
|
|
|
+ DeclSeq
|
|
|
+ [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
+ [ StatSeq ] ]
|
|
|
+ "END"
|
|
|
+ GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ SemError(202) END; .)
|
|
|
+ (. QbeGen.CloseModule;
|
|
|
+ SemError(230);
|
|
|
+ SymTab.PrintTable; .) .
|
|
|
+ ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
= "MODULE"
|
|
|
GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
IF ~SymTab.Enter(m1,
|
|
|
SymTab.KindModule) THEN
|
|
|
SemError(200) END; .)
|
|
|
+ [ Priority ]
|
|
|
";"
|
|
|
- { ConstBlock | VarBlock }
|
|
|
+ { Import }
|
|
|
+ DeclSeq
|
|
|
[ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
[ StatSeq ] ]
|
|
|
"END"
|
|
|
GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
SemError(202) END; .)
|
|
|
- "." (. QbeGen.EndModule;
|
|
|
+ (. QbeGen.EndModule;
|
|
|
SymTab.PrintTable; .) .
|
|
|
+ DeclSeq
|
|
|
+ = { ConstBlock | VarBlock | 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; .)
|
|
|
+ = "MODULE"
|
|
|
+ GetIdent<m1> (. IF ~SymTab.Enter(m1,
|
|
|
+ SymTab.KindModule) THEN
|
|
|
+ SemError(200) END;
|
|
|
+ SymTab.PushScope; .)
|
|
|
+ [ Priority ]
|
|
|
+ ";"
|
|
|
+ { Import }
|
|
|
+ [ Export ]
|
|
|
+ DeclSeq
|
|
|
+ [ "BEGIN"
|
|
|
+ [ StatSeq ] ]
|
|
|
+ "END"
|
|
|
+ GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ SemError(202) END;
|
|
|
+ SymTab.PopScope;
|
|
|
+ SemError(230); .) .
|
|
|
+ Priority
|
|
|
+ = "[" integer "]" (. SemError(230); .) .
|
|
|
+ Export (. VAR nm: SymTab.Name; .)
|
|
|
+ = "EXPORT" (* names wire up in step 4 *)
|
|
|
+ [ "QUALIFIED" ]
|
|
|
+ GetIdent<nm>
|
|
|
+ { "," GetIdent<nm> }
|
|
|
+ ";" .
|
|
|
+ Import (. VAR n: SymTab.Name; .)
|
|
|
+ = "FROM"
|
|
|
+ GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindImport) THEN
|
|
|
+ SemError(200) END; .)
|
|
|
+ "IMPORT"
|
|
|
+ ImpList ";"
|
|
|
+ | "IMPORT"
|
|
|
+ ImpList ";" .
|
|
|
+ ImpList (. VAR n: SymTab.Name; .)
|
|
|
+ = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindImport) THEN
|
|
|
+ SemError(200) END; .)
|
|
|
+ { ","
|
|
|
+ GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindImport) THEN
|
|
|
+ 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; .)
|
|
|
+ = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ SymTab.KindType) THEN
|
|
|
+ SemError(200) END;
|
|
|
+ SymTab.SetSymType(n,
|
|
|
+ SymTab.NewAlias()); .) .
|
|
|
ConstBlock
|
|
|
= "CONST" { ConstDecl ";" } .
|
|
|
ConstDecl (. VAR n: SymTab.Name;
|