|
@@ -7,7 +7,7 @@ MODULE M2comp;
|
|
|
FROM M2compS IMPORT lst, src, errors, Error, CharAt;
|
|
FROM M2compS IMPORT lst, src, errors, Error, CharAt;
|
|
|
FROM M2compP IMPORT Parse, Successful;
|
|
FROM M2compP IMPORT Parse, Successful;
|
|
|
IMPORT
|
|
IMPORT
|
|
|
- Strings, Storage, SYSTEM, FileIO, AST, MGen;
|
|
|
|
|
|
|
+ Strings, Storage, SYSTEM, FileIO, AST, MGen, SymTab;
|
|
|
|
|
|
|
|
TYPE
|
|
TYPE
|
|
|
INT32 = FileIO.INT32 (* 32 bit integers needed *);
|
|
INT32 = FileIO.INT32 (* 32 bit integers needed *);
|
|
@@ -18,7 +18,7 @@ MODULE M2comp;
|
|
|
FROM Storage IMPORT ALLOCATE;
|
|
FROM Storage IMPORT ALLOCATE;
|
|
|
FROM SYSTEM IMPORT TSIZE;
|
|
FROM SYSTEM IMPORT TSIZE;
|
|
|
IMPORT lst, CharAt, errors, INT32;
|
|
IMPORT lst, CharAt, errors, INT32;
|
|
|
- EXPORT StoreError, PrintListing;
|
|
|
|
|
|
|
+ EXPORT StoreError, PrintListing, ResetErrors;
|
|
|
|
|
|
|
|
TYPE
|
|
TYPE
|
|
|
Err = POINTER TO ErrDesc;
|
|
Err = POINTER TO ErrDesc;
|
|
@@ -102,74 +102,79 @@ MODULE M2comp;
|
|
|
| 3: Msg("real expected")
|
|
| 3: Msg("real expected")
|
|
|
| 4: Msg("string expected")
|
|
| 4: Msg("string expected")
|
|
|
| 5: Msg("'.' expected")
|
|
| 5: Msg("'.' expected")
|
|
|
- | 6: Msg("'MODULE' expected")
|
|
|
|
|
- | 7: Msg("';' expected")
|
|
|
|
|
- | 8: Msg("'FROM' expected")
|
|
|
|
|
- | 9: Msg("'IMPORT' expected")
|
|
|
|
|
- | 10: Msg("',' expected")
|
|
|
|
|
- | 11: Msg("'BEGIN' expected")
|
|
|
|
|
- | 12: Msg("'END' expected")
|
|
|
|
|
- | 13: Msg("'CONST' expected")
|
|
|
|
|
- | 14: Msg("'TYPE' expected")
|
|
|
|
|
- | 15: Msg("'VAR' expected")
|
|
|
|
|
- | 16: Msg("'=' expected")
|
|
|
|
|
- | 17: Msg("':' expected")
|
|
|
|
|
- | 18: Msg("'PROCEDURE' expected")
|
|
|
|
|
- | 19: Msg("'(' expected")
|
|
|
|
|
- | 20: Msg("')' expected")
|
|
|
|
|
- | 21: Msg("'[' expected")
|
|
|
|
|
- | 22: Msg("']' expected")
|
|
|
|
|
- | 23: Msg("'EXPORT' expected")
|
|
|
|
|
- | 24: Msg("'QUALIFIED' expected")
|
|
|
|
|
- | 25: Msg("'ARRAY' expected")
|
|
|
|
|
- | 26: Msg("'OF' expected")
|
|
|
|
|
- | 27: Msg("'RECORD' expected")
|
|
|
|
|
- | 28: Msg("'SET' expected")
|
|
|
|
|
- | 29: Msg("'POINTER' expected")
|
|
|
|
|
- | 30: Msg("'TO' expected")
|
|
|
|
|
- | 31: Msg("'..' expected")
|
|
|
|
|
- | 32: Msg("'EXIT' expected")
|
|
|
|
|
- | 33: Msg("':=' expected")
|
|
|
|
|
- | 34: Msg("'^' expected")
|
|
|
|
|
- | 35: Msg("'IF' expected")
|
|
|
|
|
- | 36: Msg("'THEN' expected")
|
|
|
|
|
- | 37: Msg("'ELSIF' expected")
|
|
|
|
|
- | 38: Msg("'ELSE' expected")
|
|
|
|
|
- | 39: Msg("'WHILE' expected")
|
|
|
|
|
- | 40: Msg("'DO' expected")
|
|
|
|
|
- | 41: Msg("'REPEAT' expected")
|
|
|
|
|
- | 42: Msg("'UNTIL' expected")
|
|
|
|
|
- | 43: Msg("'LOOP' expected")
|
|
|
|
|
- | 44: Msg("'FOR' expected")
|
|
|
|
|
- | 45: Msg("'BY' expected")
|
|
|
|
|
- | 46: Msg("'RETURN' expected")
|
|
|
|
|
- | 47: Msg("'#' expected")
|
|
|
|
|
- | 48: Msg("'<>' expected")
|
|
|
|
|
- | 49: Msg("'<' expected")
|
|
|
|
|
- | 50: Msg("'<=' expected")
|
|
|
|
|
- | 51: Msg("'>' expected")
|
|
|
|
|
- | 52: Msg("'>=' expected")
|
|
|
|
|
- | 53: Msg("'IN' expected")
|
|
|
|
|
- | 54: Msg("'+' expected")
|
|
|
|
|
- | 55: Msg("'-' expected")
|
|
|
|
|
- | 56: Msg("'OR' expected")
|
|
|
|
|
- | 57: Msg("'*' expected")
|
|
|
|
|
- | 58: Msg("'/' expected")
|
|
|
|
|
- | 59: Msg("'DIV' expected")
|
|
|
|
|
- | 60: Msg("'MOD' expected")
|
|
|
|
|
- | 61: Msg("'AND' expected")
|
|
|
|
|
- | 62: Msg("'NOT' expected")
|
|
|
|
|
- | 63: Msg("not expected")
|
|
|
|
|
- | 64: Msg("invalid MulOp")
|
|
|
|
|
- | 65: Msg("invalid AddOp")
|
|
|
|
|
- | 66: Msg("invalid Fact")
|
|
|
|
|
- | 67: Msg("invalid Relation")
|
|
|
|
|
- | 68: Msg("invalid SimExpr")
|
|
|
|
|
- | 69: Msg("invalid AssignOrCall")
|
|
|
|
|
- | 70: Msg("invalid IndexType")
|
|
|
|
|
- | 71: Msg("invalid BoundedBase")
|
|
|
|
|
- | 72: Msg("invalid Type")
|
|
|
|
|
- | 73: Msg("invalid Declaration")
|
|
|
|
|
|
|
+ | 6: Msg("'DEFINITION' expected")
|
|
|
|
|
+ | 7: Msg("'IMPLEMENTATION' expected")
|
|
|
|
|
+ | 8: Msg("'MODULE' expected")
|
|
|
|
|
+ | 9: Msg("';' expected")
|
|
|
|
|
+ | 10: Msg("'END' expected")
|
|
|
|
|
+ | 11: Msg("'CONST' expected")
|
|
|
|
|
+ | 12: Msg("'TYPE' expected")
|
|
|
|
|
+ | 13: Msg("'VAR' expected")
|
|
|
|
|
+ | 14: Msg("'PROCEDURE' expected")
|
|
|
|
|
+ | 15: Msg("':' expected")
|
|
|
|
|
+ | 16: Msg("'BEGIN' expected")
|
|
|
|
|
+ | 17: Msg("'FROM' expected")
|
|
|
|
|
+ | 18: Msg("'IMPORT' expected")
|
|
|
|
|
+ | 19: Msg("',' expected")
|
|
|
|
|
+ | 20: Msg("'=' expected")
|
|
|
|
|
+ | 21: Msg("'(' expected")
|
|
|
|
|
+ | 22: Msg("')' expected")
|
|
|
|
|
+ | 23: Msg("'[' expected")
|
|
|
|
|
+ | 24: Msg("']' expected")
|
|
|
|
|
+ | 25: Msg("'EXPORT' expected")
|
|
|
|
|
+ | 26: Msg("'QUALIFIED' expected")
|
|
|
|
|
+ | 27: Msg("'ARRAY' expected")
|
|
|
|
|
+ | 28: Msg("'OF' expected")
|
|
|
|
|
+ | 29: Msg("'RECORD' expected")
|
|
|
|
|
+ | 30: Msg("'SET' expected")
|
|
|
|
|
+ | 31: Msg("'POINTER' expected")
|
|
|
|
|
+ | 32: Msg("'TO' expected")
|
|
|
|
|
+ | 33: Msg("'..' expected")
|
|
|
|
|
+ | 34: Msg("'EXIT' expected")
|
|
|
|
|
+ | 35: Msg("':=' expected")
|
|
|
|
|
+ | 36: Msg("'^' expected")
|
|
|
|
|
+ | 37: Msg("'IF' expected")
|
|
|
|
|
+ | 38: Msg("'THEN' expected")
|
|
|
|
|
+ | 39: Msg("'ELSIF' expected")
|
|
|
|
|
+ | 40: Msg("'ELSE' expected")
|
|
|
|
|
+ | 41: Msg("'WHILE' expected")
|
|
|
|
|
+ | 42: Msg("'DO' expected")
|
|
|
|
|
+ | 43: Msg("'REPEAT' expected")
|
|
|
|
|
+ | 44: Msg("'UNTIL' expected")
|
|
|
|
|
+ | 45: Msg("'LOOP' expected")
|
|
|
|
|
+ | 46: Msg("'FOR' expected")
|
|
|
|
|
+ | 47: Msg("'BY' expected")
|
|
|
|
|
+ | 48: Msg("'RETURN' expected")
|
|
|
|
|
+ | 49: Msg("'#' expected")
|
|
|
|
|
+ | 50: Msg("'<>' expected")
|
|
|
|
|
+ | 51: Msg("'<' expected")
|
|
|
|
|
+ | 52: Msg("'<=' expected")
|
|
|
|
|
+ | 53: Msg("'>' expected")
|
|
|
|
|
+ | 54: Msg("'>=' expected")
|
|
|
|
|
+ | 55: Msg("'IN' expected")
|
|
|
|
|
+ | 56: Msg("'+' expected")
|
|
|
|
|
+ | 57: Msg("'-' expected")
|
|
|
|
|
+ | 58: Msg("'OR' expected")
|
|
|
|
|
+ | 59: Msg("'*' expected")
|
|
|
|
|
+ | 60: Msg("'/' expected")
|
|
|
|
|
+ | 61: Msg("'DIV' expected")
|
|
|
|
|
+ | 62: Msg("'MOD' expected")
|
|
|
|
|
+ | 63: Msg("'AND' expected")
|
|
|
|
|
+ | 64: Msg("'NOT' expected")
|
|
|
|
|
+ | 65: Msg("not expected")
|
|
|
|
|
+ | 66: Msg("invalid MulOp")
|
|
|
|
|
+ | 67: Msg("invalid AddOp")
|
|
|
|
|
+ | 68: Msg("invalid Fact")
|
|
|
|
|
+ | 69: Msg("invalid Relation")
|
|
|
|
|
+ | 70: Msg("invalid SimExpr")
|
|
|
|
|
+ | 71: Msg("invalid AssignOrCall")
|
|
|
|
|
+ | 72: Msg("invalid IndexType")
|
|
|
|
|
+ | 73: Msg("invalid BoundedBase")
|
|
|
|
|
+ | 74: Msg("invalid Type")
|
|
|
|
|
+ | 75: Msg("invalid Declaration")
|
|
|
|
|
+ | 76: Msg("invalid ImplDecl")
|
|
|
|
|
+ | 77: Msg("invalid DefDecl")
|
|
|
|
|
+ | 78: Msg("invalid Unit")
|
|
|
|
|
|
|
|
(* add customized cases here *)
|
|
(* add customized cases here *)
|
|
|
| 200: Msg("duplicate identifier")
|
|
| 200: Msg("duplicate identifier")
|
|
@@ -199,6 +204,12 @@ MODULE M2comp;
|
|
|
WriteLn(lst)
|
|
WriteLn(lst)
|
|
|
END PrintErr;
|
|
END PrintErr;
|
|
|
|
|
|
|
|
|
|
+ PROCEDURE ResetErrors;
|
|
|
|
|
+ (* Drops stored errors so the next input file starts clean. *)
|
|
|
|
|
+ BEGIN
|
|
|
|
|
+ firstErr := NIL; lastErr := NIL
|
|
|
|
|
+ END ResetErrors;
|
|
|
|
|
+
|
|
|
PROCEDURE PrintListing;
|
|
PROCEDURE PrintListing;
|
|
|
(* Print a source listing with error messages *)
|
|
(* Print a source listing with error messages *)
|
|
|
VAR
|
|
VAR
|
|
@@ -264,6 +275,23 @@ MODULE M2comp;
|
|
|
sourceName, listName: ARRAY [0 .. 255] OF CHAR;
|
|
sourceName, listName: ARRAY [0 .. 255] OF CHAR;
|
|
|
failed: BOOLEAN;
|
|
failed: BOOLEAN;
|
|
|
emitOk: BOOLEAN;
|
|
emitOk: BOOLEAN;
|
|
|
|
|
+ progSeen: BOOLEAN;
|
|
|
|
|
+ uk: INTEGER;
|
|
|
|
|
+ nDefs, nImpls: CARDINAL;
|
|
|
|
|
+ i, j: CARDINAL;
|
|
|
|
|
+ found: BOOLEAN;
|
|
|
|
|
+ progRoot, sessionRoot, chain: AST.Node;
|
|
|
|
|
+ progName: SymTab.Name;
|
|
|
|
|
+ unitRoots: ARRAY [0 .. 15] OF AST.Node;
|
|
|
|
|
+ unitIsDef: ARRAY [0 .. 15] OF BOOLEAN;
|
|
|
|
|
+
|
|
|
|
|
+ PROCEDURE Fail (msg: ARRAY OF CHAR);
|
|
|
|
|
+ (* Fail-fast session abort with a one-line outcome. *)
|
|
|
|
|
+ BEGIN
|
|
|
|
|
+ FileIO.WriteString(FileIO.StdOut, msg);
|
|
|
|
|
+ FileIO.WriteLn(FileIO.StdOut);
|
|
|
|
|
+ failed := TRUE
|
|
|
|
|
+ END Fail;
|
|
|
|
|
|
|
|
BEGIN
|
|
BEGIN
|
|
|
(* check on correct parameter usage *)
|
|
(* check on correct parameter usage *)
|
|
@@ -273,12 +301,17 @@ MODULE M2comp;
|
|
|
HALT
|
|
HALT
|
|
|
END;
|
|
END;
|
|
|
|
|
|
|
|
- (* step 1: syntax only, no symbol table yet (see M2comp.atg) *)
|
|
|
|
|
|
|
+ (* step 5: one symbol table per session (not per file), so
|
|
|
|
|
+ definitions, implementations and the program share it *)
|
|
|
|
|
|
|
|
(* install error reporting procedure - Scanner.Error *)
|
|
(* install error reporting procedure - Scanner.Error *)
|
|
|
Error := StoreError;
|
|
Error := StoreError;
|
|
|
|
|
|
|
|
|
|
+ SymTab.Init();
|
|
|
failed := FALSE;
|
|
failed := FALSE;
|
|
|
|
|
+ progSeen := FALSE;
|
|
|
|
|
+ nDefs := 0;
|
|
|
|
|
+ nImpls := 0;
|
|
|
LOOP
|
|
LOOP
|
|
|
IF sourceName[0] = 0C THEN EXIT END;
|
|
IF sourceName[0] = 0C THEN EXIT END;
|
|
|
|
|
|
|
@@ -299,25 +332,22 @@ MODULE M2comp;
|
|
|
(* default Scanner.lst to screen *) lst := FileIO.StdOut;
|
|
(* default Scanner.lst to screen *) lst := FileIO.StdOut;
|
|
|
END;
|
|
END;
|
|
|
|
|
|
|
|
|
|
+ (* fresh error list per input file (M2compS.Reset already
|
|
|
|
|
+ zeroes the error count inside Parse) *)
|
|
|
|
|
+ ResetErrors;
|
|
|
|
|
+
|
|
|
(* instigate the compilation - Parser.Parse *)
|
|
(* instigate the compilation - Parser.Parse *)
|
|
|
FileIO.WriteString(FileIO.StdOut, "Parsing ");
|
|
FileIO.WriteString(FileIO.StdOut, "Parsing ");
|
|
|
FileIO.WriteString(FileIO.StdOut, sourceName);
|
|
FileIO.WriteString(FileIO.StdOut, sourceName);
|
|
|
FileIO.WriteLn(FileIO.StdOut);
|
|
FileIO.WriteLn(FileIO.StdOut);
|
|
|
Parse;
|
|
Parse;
|
|
|
|
|
|
|
|
- (* backend: emit the MC64 image while errors still reach
|
|
|
|
|
- the listing below *)
|
|
|
|
|
- IF Successful() THEN
|
|
|
|
|
- emitOk := MGen.EmitModule(AST.GetRoot())
|
|
|
|
|
- ELSE emitOk := FALSE
|
|
|
|
|
- END;
|
|
|
|
|
-
|
|
|
|
|
(* generate the source listing on lst file *)
|
|
(* generate the source listing on lst file *)
|
|
|
PrintListing;
|
|
PrintListing;
|
|
|
IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
|
|
IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
|
|
|
|
|
|
|
|
(* fail fast: later files build on this one's tables *)
|
|
(* fail fast: later files build on this one's tables *)
|
|
|
- IF NOT (Successful() & emitOk)
|
|
|
|
|
|
|
+ IF NOT Successful()
|
|
|
THEN
|
|
THEN
|
|
|
FileIO.WriteString(FileIO.StdOut, "Incorrect source");
|
|
FileIO.WriteString(FileIO.StdOut, "Incorrect source");
|
|
|
FileIO.WriteLn(FileIO.StdOut);
|
|
FileIO.WriteLn(FileIO.StdOut);
|
|
@@ -325,9 +355,88 @@ MODULE M2comp;
|
|
|
EXIT
|
|
EXIT
|
|
|
END;
|
|
END;
|
|
|
|
|
|
|
|
|
|
+ (* session order: definitions and implementations in
|
|
|
|
|
+ dependency order (the grammar enforces per-library order:
|
|
|
|
|
+ a definition precedes its implementation, an IMPORT needs
|
|
|
|
|
+ a completed implementation), then exactly one program;
|
|
|
|
|
+ remember each unit root for the single backend pass *)
|
|
|
|
|
+ uk := SymTab.UnitKind();
|
|
|
|
|
+ IF progSeen THEN
|
|
|
|
|
+ Fail("Incorrect source"); EXIT
|
|
|
|
|
+ ELSIF uk = SymTab.UnitDef THEN
|
|
|
|
|
+ IF nDefs + nImpls > 15 THEN
|
|
|
|
|
+ Fail("Incorrect source"); EXIT
|
|
|
|
|
+ END;
|
|
|
|
|
+ unitRoots[nDefs + nImpls] := AST.GetRoot();
|
|
|
|
|
+ unitIsDef[nDefs + nImpls] := TRUE;
|
|
|
|
|
+ INC(nDefs)
|
|
|
|
|
+ ELSIF uk = SymTab.UnitImpl THEN
|
|
|
|
|
+ IF nDefs + nImpls > 15 THEN
|
|
|
|
|
+ Fail("Incorrect source"); EXIT
|
|
|
|
|
+ END;
|
|
|
|
|
+ unitRoots[nDefs + nImpls] := AST.GetRoot();
|
|
|
|
|
+ unitIsDef[nDefs + nImpls] := FALSE;
|
|
|
|
|
+ INC(nImpls)
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ progSeen := TRUE;
|
|
|
|
|
+ progRoot := AST.GetRoot();
|
|
|
|
|
+ Strings.Assign(progRoot^.name, progName)
|
|
|
|
|
+ END;
|
|
|
|
|
+
|
|
|
FileIO.NextParameter(sourceName);
|
|
FileIO.NextParameter(sourceName);
|
|
|
END;
|
|
END;
|
|
|
|
|
|
|
|
|
|
+ (* a session without a program emits nothing *)
|
|
|
|
|
+ IF NOT failed & ~progSeen THEN
|
|
|
|
|
+ Fail("Incorrect source")
|
|
|
|
|
+ END;
|
|
|
|
|
+
|
|
|
|
|
+ (* merge each implementation into its definition unit, then emit
|
|
|
|
|
+ the program together with the library units in one image *)
|
|
|
|
|
+ IF NOT failed THEN
|
|
|
|
|
+ i := 0;
|
|
|
|
|
+ WHILE (i < nDefs + nImpls) & ~failed DO
|
|
|
|
|
+ IF ~unitIsDef[i] THEN
|
|
|
|
|
+ found := FALSE;
|
|
|
|
|
+ j := 0;
|
|
|
|
|
+ WHILE (j < nDefs + nImpls) & ~found DO
|
|
|
|
|
+ IF unitIsDef[j] & Strings.Equal(unitRoots[j]^.name,
|
|
|
|
|
+ unitRoots[i]^.name) THEN
|
|
|
|
|
+ found := TRUE
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ INC(j)
|
|
|
|
|
+ END
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF ~found THEN Fail("Incorrect source")
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ unitRoots[j]^.left := AST.Append(unitRoots[j]^.left,
|
|
|
|
|
+ unitRoots[i]^.left);
|
|
|
|
|
+ unitRoots[j]^.right := unitRoots[i]^.right
|
|
|
|
|
+ END
|
|
|
|
|
+ END;
|
|
|
|
|
+ INC(i)
|
|
|
|
|
+ END
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF NOT failed THEN
|
|
|
|
|
+ chain := NIL;
|
|
|
|
|
+ i := 0;
|
|
|
|
|
+ WHILE i < nDefs + nImpls DO
|
|
|
|
|
+ IF unitIsDef[i] THEN
|
|
|
|
|
+ chain := AST.Append(chain, unitRoots[i])
|
|
|
|
|
+ END;
|
|
|
|
|
+ INC(i)
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF chain = NIL THEN sessionRoot := progRoot
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ sessionRoot := AST.MkModule(progName,
|
|
|
|
|
+ AST.Append(chain, progRoot^.left), progRoot^.right)
|
|
|
|
|
+ END;
|
|
|
|
|
+ (* backend: emit the MC64 image (errors reach StdOut only;
|
|
|
|
|
+ listings are already written) *)
|
|
|
|
|
+ emitOk := MGen.EmitModule(sessionRoot);
|
|
|
|
|
+ IF NOT emitOk THEN Fail("Incorrect source") END
|
|
|
|
|
+ END;
|
|
|
|
|
+
|
|
|
(* examine the outcome *)
|
|
(* examine the outcome *)
|
|
|
IF NOT failed THEN
|
|
IF NOT failed THEN
|
|
|
FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
|
|
FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
|