Просмотр исходного кода

m2comp step 3 — AST layer with dump (25/25 tests green)

Eric Streit 3 недель назад
Родитель
Сommit
d8a76ed0f1
14 измененных файлов с 1270 добавлено и 547 удалено
  1. BIN
      M2comp
  2. 3 3
      build.sh
  3. 66 0
      docs/summary_m2comp_step3.md
  4. 13 0
      run_tests.sh
  5. 123 0
      src/AST.def
  6. 423 0
      src/AST.mod
  7. BIN
      src/AST.o
  8. 324 190
      src/M2comp.atg
  9. 1 1
      src/M2comp.lst
  10. 314 197
      src/M2compP.mod
  11. BIN
      src/M2compP.o
  12. 3 0
      src/modules.lst
  13. 0 36
      tests/ok_proc.LST
  14. 0 120
      tests/showcase.LST

+ 3 - 3
build.sh

@@ -22,17 +22,17 @@ echo "=== Deleting all o files ==="
 rm -f ./*.o
 
 echo "=== Compiling the needed modules ==="
-for m in FileIO SymTab M2compS M2compP M2comp; do
+for m in FileIO SymTab AST M2compS M2compP M2comp; do
   gm2 -fiso -c "$m.mod" || exit 1
 done
 
 echo "=== Phase 1: generating the module list ==="
 gm2 -fiso -fgen-module-list=modules.lst -o /dev/null \
-    M2compS.o M2compP.o FileIO.o SymTab.o M2comp.mod || exit 1
+    M2compS.o M2compP.o FileIO.o SymTab.o AST.o M2comp.mod || exit 1
 
 echo "=== Phase 2: compiling main module and linking using the module list ==="
 gm2 -fiso -fuse-list=modules.lst -o ../M2comp \
-    M2compS.o M2compP.o FileIO.o SymTab.o M2comp.mod || exit 1
+    M2compS.o M2compP.o FileIO.o SymTab.o AST.o M2comp.mod || exit 1
 cd ..
 
 echo "=== M2comp built ==="

+ 66 - 0
docs/summary_m2comp_step3.md

@@ -0,0 +1,66 @@
+# m2comp step 3 — AST layer (tag: `m2comp-step3`)
+
+Coco/R frontend + SymTab checks (steps 1–2) + an abstract syntax
+tree built alongside parsing, per H. Mössenböck, "How to Build
+Abstract Syntax Trees with Coco/R" (`docs/AST.pdf`): every
+nonterminal carries an output attribute returning its subtree, built
+with plain semantic actions. No codegen yet (step 4: MC64 `MGen`
+walking this tree).
+
+## What was built
+
+- `src/AST.def/.mod` — 30 node kinds in three families:
+  decls (`Module/Block/Import/ImpName/Export/Const/Type/Var/
+  Member/Param/Proc`), statements (`Assign/Call/If/While/Repeat/
+  Loop/For/Return/Exit`), expressions (`Bin/Un/Name/Int/Real/Char/
+  Str/Field/Index/Deref/CallExpr`).
+  Nodes are heap pointer records (`NEW`) with child links
+  (`left/right/extra/more`) and a sibling link (`next`) — the
+  `dsc`/`next` shape borrowed from the Oberon `SymTable`
+  (`docs/oberon-master`), while `SymTab` itself stays flat.
+  Types are stored as descriptor indices (no type subtree);
+  unary ops use `opNot/opNeg/opPos`, binary ops reuse `SymTab`
+  codes. Error-tolerant: nodes build even with `InvalidType`, so
+  rejected sources still dump. Includes `Append`, `SetChainType`
+  (identifier lists typed after the fact), `ParseInt`
+  (decimal + `H` hex), and a NIL-safe depth-capped `DumpTree`.
+- `src/M2comp.atg` — full attribution with step-2 checks untouched:
+  `MkModule/MkBlock` roots dumped by the `Module` action;
+  `ELSIF` chains attach at the deepest else (standard
+  `If(a,A,If(b,B,C))` nesting); `MkFor` carries optional BY;
+  calls share the step-2 frame machinery (`MkCall`/`MkCallExpr`
+  with pnum); designators become `Name/Field/Index/Deref` chains
+  (indices appended per bracket); literals folded
+  (`0FFH`→255, `'q'`→113, reals/strings kept as text).
+- `run_tests.sh` — new `expect_dump` assertions on tree content
+  (`Module Showcase`, `Proc Work`, `CallExpr`, `Field q`,
+  `Int 255`, `Proc P`).
+
+## Tests — 25/25
+
+19/19 accept/reject from step 2 unchanged + 6 AST content checks.
+
+## Bugs found (both fixed, both covered)
+
+- `ParseInt` detected hex only when the digit scan stopped at `H`,
+  so `0FFH` dumped as `Int 0`. Fixed by checking the trailing `H`
+  first, then hex-parsing the prefix.
+- `NEW` on `POINTER TO RECORD` needs `FROM Storage IMPORT
+  ALLOCATE` under `gm2 -fiso` (ISO rule).
+
+## Notes
+
+- Dump verified by hand on `showcase`: nested procs, recursion,
+  `p^`, `m[1,2]`, `Local.q`, `ELSIF` nesting, `LOOP/EXIT`,
+  `FOR` with/without `BY`, precedence (`Min(3,4)+(2*3-4/2)`).
+- Known simplifications for step 4: string/real literals kept as
+  text (truncated at 63 chars); record members build nodes that
+  the `Type` alternative discards (types resolve via `SymTab`).
+
+## Next
+
+Step 4: MC64 `MGen` backend — tree-walking emitter (`mc64-spec.md`
+§11 opcodes, frames §5.2, `.MC4` images runnable under `mcint`),
+reusing the `m2c` lowering as reference. `SymTab` (`ProcNum`,
+`ByNum` queries, export tables) and `AST` (pnum/typ on nodes) are
+already backend-ready.

+ 13 - 0
run_tests.sh

@@ -16,6 +16,13 @@ expect_fail() {
     fail=$((fail+1)); echo "FAIL(fail, accepted): $1"
   fi
 }
+expect_dump() {
+  if ./M2comp "$1" 2>&1 | grep -q "$2"; then
+    pass=$((pass+1)); echo "PASS(ast): $1 [$2]"
+  else
+    fail=$((fail+1)); echo "FAIL(ast): $1 [$2]"
+  fi
+}
 expect_ok tests/ok_minimal.mod
 expect_ok tests/ok_proc.mod
 expect_ok tests/showcase.mod
@@ -35,5 +42,11 @@ expect_fail tests/t_call.mod
 expect_fail tests/t_call2.mod
 expect_fail tests/t_return.mod
 expect_fail tests/t_exit.mod
+expect_dump tests/showcase.mod "Module Showcase"
+expect_dump tests/showcase.mod "Proc Work"
+expect_dump tests/showcase.mod "CallExpr"
+expect_dump tests/showcase.mod "Field q"
+expect_dump tests/showcase.mod "Int 255"
+expect_dump tests/ok_proc.mod "Proc P"
 echo "--- $pass passed, $fail failed ---"
 [ "$fail" -eq 0 ]

+ 123 - 0
src/AST.def

@@ -0,0 +1,123 @@
+DEFINITION MODULE AST;
+(* Abstract syntax tree for M2comp step 3.
+   Recipe: H. Mössenböck, "How to Build Abstract Syntax Trees with
+   Coco/R" (docs/AST.pdf) — every nonterminal builds its subtree via
+   output attributes, with plain semantic actions (no special notation).
+   Nodes are heap pointer records with child links (left/right/extra/
+   more) and a sibling link (next), mirroring the dsc/next shape of
+   the Oberon SymTable (docs/oberon-master) while SymTab itself stays
+   flat. Types are stored as descriptor indices (SymTab.TypeIndex,
+   seen here as INTEGER to keep coupling one-way); there is no
+   separate type subtree. Error-tolerant: nodes are built even when
+   the type is InvalidType, so dumps exist for rejected sources too. *)
+
+CONST
+  (* declaration nodes *)
+  nkNone = 0;
+  nkModule = 1;    (* name; left=decl chain; right=block *)
+  nkBlock = 2;     (* left=decl chain; right=stmt chain *)
+  nkImport = 3;    (* name=module ("" for plain IMPORT); left=names *)
+  nkImpName = 4;   (* name *)
+  nkExport = 5;    (* left=names *)
+  nkConst = 6;     (* name; typ; left=expr *)
+  nkTypeDecl = 7;  (* name; typ *)
+  nkVar = 8;       (* name; typ *)
+  nkMember = 9;    (* record field name; typ *)
+  nkParam = 10;    (* name; typ; op=ORD(isVar) *)
+  nkProc = 11;     (* name; typ=rettype; left=params; right=block *)
+  (* statement nodes *)
+  nkAssign = 20;   (* left=dst; right=src *)
+  nkCall = 21;     (* left=callee designator; right=actuals; num=pnum *)
+  nkIf = 22;       (* left=cond; right=then; extra=else-or-nil *)
+  nkWhile = 23;    (* left=cond; right=body *)
+  nkRepeat = 24;   (* left=body; right=cond *)
+  nkLoop = 25;     (* left=body *)
+  nkFor = 26;      (* name=control var; left=lo; right=hi;
+                      extra=by-or-nil; more=body *)
+  nkReturn = 27;   (* left=expr-or-nil *)
+  nkExit = 28;
+  (* expression nodes *)
+  nkBin = 30;      (* op=SymTab op code (OpIn for IN); left; right *)
+  nkUn = 31;       (* op=opNot/opNeg/opPos; left *)
+  nkName = 32;     (* name; typ *)
+  nkInt = 33;      (* num=value; typ *)
+  nkReal = 34;     (* text; typ *)
+  nkChar = 35;     (* num=ORD; typ *)
+  nkStr = 36;      (* text; typ *)
+  nkField = 37;    (* left=record; name=field; typ *)
+  nkIndex = 38;    (* left=array; right=index chain; typ *)
+  nkDeref = 39;    (* left; typ *)
+  nkCallExpr = 40; (* left=callee; right=actuals; num=pnum; typ=ret *)
+  (* unary operator codes (binary ones reuse SymTab op codes) *)
+  opNot = 1; opNeg = 2; opPos = 3;
+
+TYPE
+  Node = POINTER TO NodeRec;
+  NodeRec = RECORD
+    kind: INTEGER;
+    typ: INTEGER;
+    op: INTEGER;
+    num: INTEGER;
+    name: ARRAY [0 .. 63] OF CHAR;
+    text: ARRAY [0 .. 63] OF CHAR;
+    left, right, extra, more, next: Node;
+  END;
+
+PROCEDURE New (kind: INTEGER): Node;
+(* Fresh node, all links NIL, typ InvalidType (-1). *)
+
+PROCEDURE SetRoot (n: Node);
+PROCEDURE GetRoot (): Node;
+(* Module root for the driver dump. *)
+
+PROCEDURE Append (head, tail: Node): Node;
+(* NIL-safe sibling append; returns head (or tail). *)
+
+PROCEDURE SetChainType (head: Node; t: INTEGER);
+(* Assigns typ to every node of a sibling chain (VAR/FP/field
+   identifier lists whose type is parsed afterwards). *)
+
+PROCEDURE MkName (nm: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkInt (v: INTEGER; t: INTEGER): Node;
+PROCEDURE MkChar (v: INTEGER; t: INTEGER): Node;
+PROCEDURE MkReal (tx: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkStr (tx: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkBin (op: INTEGER; l, r: Node; t: INTEGER): Node;
+PROCEDURE MkUn (op: INTEGER; e: Node; t: INTEGER): Node;
+PROCEDURE MkField (rec: Node; field: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkIndex (arr, idx: Node; t: INTEGER): Node;
+PROCEDURE MkDeref (p: Node; t: INTEGER): Node;
+PROCEDURE MkCallExpr (callee, actuals: Node; pnum,
+                      t: INTEGER): Node;
+PROCEDURE MkAssign (dst, src: Node): Node;
+PROCEDURE MkCall (callee, actuals: Node; pnum: INTEGER): Node;
+PROCEDURE MkIf (c, th, el: Node): Node;
+PROCEDURE MkWhile (c, body: Node): Node;
+PROCEDURE MkRepeat (body, c: Node): Node;
+PROCEDURE MkLoop (body: Node): Node;
+PROCEDURE MkFor (nm: ARRAY OF CHAR; lo, hi, by,
+                 body: Node): Node;
+PROCEDURE MkReturn (e: Node): Node;
+PROCEDURE MkExit (): Node;
+PROCEDURE MkBlock (decls, stmts: Node): Node;
+PROCEDURE MkModule (nm: ARRAY OF CHAR; decls,
+                    body: Node): Node;
+PROCEDURE MkProc (nm: ARRAY OF CHAR; ret: INTEGER; params,
+                  body: Node): Node;
+PROCEDURE MkConst (nm: ARRAY OF CHAR; e: Node; t: INTEGER): Node;
+PROCEDURE MkTypeDecl (nm: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkVar (nm: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkMember (nm: ARRAY OF CHAR; t: INTEGER): Node;
+PROCEDURE MkParam (nm: ARRAY OF CHAR; t: INTEGER;
+                   isVar: BOOLEAN): Node;
+PROCEDURE MkImport (mod: ARRAY OF CHAR; names: Node): Node;
+PROCEDURE MkImpName (nm: ARRAY OF CHAR): Node;
+PROCEDURE MkExport (names: Node): Node;
+
+PROCEDURE ParseInt (tx: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
+(* Decimal or H-suffixed hex integer literal text to value. *)
+
+PROCEDURE DumpTree (n: Node);
+(* Indented dump of the tree to StdOut (NIL-safe, depth-capped). *)
+
+END AST.

+ 423 - 0
src/AST.mod

@@ -0,0 +1,423 @@
+IMPLEMENTATION MODULE AST;
+
+FROM STextIO IMPORT WriteString, WriteLn, WriteChar;
+FROM SWholeIO IMPORT WriteInt;
+FROM Storage IMPORT ALLOCATE;
+
+VAR
+  root: Node;
+
+PROCEDURE Copy (VAR dst: ARRAY OF CHAR; src: ARRAY OF CHAR);
+  VAR i: CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE (i < HIGH(dst)) & (src[i] # 0C) DO
+      dst[i] := src[i]; INC(i)
+    END;
+    dst[i] := 0C
+  END Copy;
+
+PROCEDURE New (kind: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    NEW(n);
+    n^.kind := kind;
+    n^.typ := -1;
+    n^.op := 0;
+    n^.num := 0;
+    n^.name[0] := 0C;
+    n^.text[0] := 0C;
+    n^.left := NIL; n^.right := NIL; n^.extra := NIL;
+    n^.more := NIL; n^.next := NIL;
+    RETURN n
+  END New;
+
+PROCEDURE SetRoot (n: Node);
+  BEGIN
+    root := n
+  END SetRoot;
+
+PROCEDURE GetRoot (): Node;
+  BEGIN
+    RETURN root
+  END GetRoot;
+
+PROCEDURE Append (head, tail: Node): Node;
+  VAR p: Node;
+  BEGIN
+    IF head = NIL THEN RETURN tail END;
+    IF tail = NIL THEN RETURN head END;
+    p := head;
+    WHILE p^.next # NIL DO p := p^.next END;
+    p^.next := tail;
+    RETURN head
+  END Append;
+
+PROCEDURE SetChainType (head: Node; t: INTEGER);
+  VAR p: Node;
+  BEGIN
+    p := head;
+    WHILE p # NIL DO p^.typ := t; p := p^.next END
+  END SetChainType;
+
+PROCEDURE MkName (nm: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkName); Copy(n^.name, nm); n^.typ := t;
+    RETURN n
+  END MkName;
+
+PROCEDURE MkInt (v: INTEGER; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkInt); n^.num := v; n^.typ := t;
+    RETURN n
+  END MkInt;
+
+PROCEDURE MkChar (v: INTEGER; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkChar); n^.num := v; n^.typ := t;
+    RETURN n
+  END MkChar;
+
+PROCEDURE MkReal (tx: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkReal); Copy(n^.text, tx); n^.typ := t;
+    RETURN n
+  END MkReal;
+
+PROCEDURE MkStr (tx: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkStr); Copy(n^.text, tx); n^.typ := t;
+    RETURN n
+  END MkStr;
+
+PROCEDURE MkBin (op: INTEGER; l, r: Node; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkBin); n^.op := op;
+    n^.left := l; n^.right := r; n^.typ := t;
+    RETURN n
+  END MkBin;
+
+PROCEDURE MkUn (op: INTEGER; e: Node; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkUn); n^.op := op;
+    n^.left := e; n^.typ := t;
+    RETURN n
+  END MkUn;
+
+PROCEDURE MkField (rec: Node; field: ARRAY OF CHAR;
+                   t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkField); n^.left := rec;
+    Copy(n^.name, field); n^.typ := t;
+    RETURN n
+  END MkField;
+
+PROCEDURE MkIndex (arr, idx: Node; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkIndex); n^.left := arr; n^.right := idx;
+    n^.typ := t;
+    RETURN n
+  END MkIndex;
+
+PROCEDURE MkDeref (p: Node; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkDeref); n^.left := p; n^.typ := t;
+    RETURN n
+  END MkDeref;
+
+PROCEDURE MkCallExpr (callee, actuals: Node; pnum,
+                      t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkCallExpr); n^.left := callee; n^.right := actuals;
+    n^.num := pnum; n^.typ := t;
+    RETURN n
+  END MkCallExpr;
+
+PROCEDURE MkAssign (dst, src: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkAssign); n^.left := dst; n^.right := src;
+    RETURN n
+  END MkAssign;
+
+PROCEDURE MkCall (callee, actuals: Node; pnum: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkCall); n^.left := callee; n^.right := actuals;
+    n^.num := pnum;
+    RETURN n
+  END MkCall;
+
+PROCEDURE MkIf (c, th, el: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkIf); n^.left := c; n^.right := th; n^.extra := el;
+    RETURN n
+  END MkIf;
+
+PROCEDURE MkWhile (c, body: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkWhile); n^.left := c; n^.right := body;
+    RETURN n
+  END MkWhile;
+
+PROCEDURE MkRepeat (body, c: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkRepeat); n^.left := body; n^.right := c;
+    RETURN n
+  END MkRepeat;
+
+PROCEDURE MkLoop (body: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkLoop); n^.left := body;
+    RETURN n
+  END MkLoop;
+
+PROCEDURE MkFor (nm: ARRAY OF CHAR; lo, hi, by,
+                 body: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkFor); Copy(n^.name, nm);
+    n^.left := lo; n^.right := hi; n^.extra := by; n^.more := body;
+    RETURN n
+  END MkFor;
+
+PROCEDURE MkReturn (e: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkReturn); n^.left := e;
+    RETURN n
+  END MkReturn;
+
+PROCEDURE MkExit (): Node;
+  BEGIN
+    RETURN New(nkExit)
+  END MkExit;
+
+PROCEDURE MkBlock (decls, stmts: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkBlock); n^.left := decls; n^.right := stmts;
+    RETURN n
+  END MkBlock;
+
+PROCEDURE MkModule (nm: ARRAY OF CHAR; decls,
+                    body: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkModule); Copy(n^.name, nm);
+    n^.left := decls; n^.right := body;
+    RETURN n
+  END MkModule;
+
+PROCEDURE MkProc (nm: ARRAY OF CHAR; ret: INTEGER; params,
+                  body: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkProc); Copy(n^.name, nm); n^.typ := ret;
+    n^.left := params; n^.right := body;
+    RETURN n
+  END MkProc;
+
+PROCEDURE MkConst (nm: ARRAY OF CHAR; e: Node; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkConst); Copy(n^.name, nm);
+    n^.left := e; n^.typ := t;
+    RETURN n
+  END MkConst;
+
+PROCEDURE MkTypeDecl (nm: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkTypeDecl); Copy(n^.name, nm); n^.typ := t;
+    RETURN n
+  END MkTypeDecl;
+
+PROCEDURE MkVar (nm: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkVar); Copy(n^.name, nm); n^.typ := t;
+    RETURN n
+  END MkVar;
+
+PROCEDURE MkMember (nm: ARRAY OF CHAR; t: INTEGER): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkMember); Copy(n^.name, nm); n^.typ := t;
+    RETURN n
+  END MkMember;
+
+PROCEDURE MkParam (nm: ARRAY OF CHAR; t: INTEGER;
+                   isVar: BOOLEAN): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkParam); Copy(n^.name, nm); n^.typ := t;
+    n^.op := ORD(isVar);
+    RETURN n
+  END MkParam;
+
+PROCEDURE MkImport (mod: ARRAY OF CHAR; names: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkImport); Copy(n^.name, mod); n^.left := names;
+    RETURN n
+  END MkImport;
+
+PROCEDURE MkImpName (nm: ARRAY OF CHAR): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkImpName); Copy(n^.name, nm);
+    RETURN n
+  END MkImpName;
+
+PROCEDURE MkExport (names: Node): Node;
+  VAR n: Node;
+  BEGIN
+    n := New(nkExport); n^.left := names;
+    RETURN n
+  END MkExport;
+
+PROCEDURE HexVal (ch: CHAR; VAR v: INTEGER): BOOLEAN;
+  BEGIN
+    IF (ch >= "0") & (ch <= "9") THEN
+      v := ORD(ch) - ORD("0"); RETURN TRUE
+    ELSIF (ch >= "A") & (ch <= "F") THEN
+      v := ORD(ch) - ORD("A") + 10; RETURN TRUE
+    ELSE RETURN FALSE
+    END
+  END HexVal;
+
+PROCEDURE ParseInt (tx: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
+(* Decimal or H-suffixed hex integer literal text to value. *)
+  VAR i, L, d: CARDINAL;
+  BEGIN
+    v := 0; i := 0;
+    L := 0;
+    WHILE tx[L] # 0C DO INC(L) END;
+    IF (L > 1) & (tx[L - 1] = "H") THEN
+      d := 0;
+      WHILE i < L - 1 DO
+        IF ~HexVal(tx[i], v) THEN RETURN FALSE END;
+        d := d * 16 + VAL(CARDINAL, v); INC(i)
+      END;
+      v := VAL(INTEGER, d);
+      RETURN TRUE
+    END;
+    d := 0;
+    WHILE (tx[i] >= "0") & (tx[i] <= "9") DO
+      d := d * 10 + VAL(CARDINAL, ORD(tx[i]) - ORD("0")); INC(i)
+    END;
+    IF tx[i] # 0C THEN RETURN FALSE END;
+    v := VAL(INTEGER, d);
+    RETURN TRUE
+  END ParseInt;
+
+PROCEDURE KindName (k: INTEGER; VAR s: ARRAY OF CHAR);
+  BEGIN
+    CASE k OF
+      nkModule : Copy(s, "Module")
+    | nkBlock : Copy(s, "Block")
+    | nkImport : Copy(s, "Import")
+    | nkImpName : Copy(s, "ImpName")
+    | nkExport : Copy(s, "Export")
+    | nkConst : Copy(s, "Const")
+    | nkTypeDecl : Copy(s, "Type")
+    | nkVar : Copy(s, "Var")
+    | nkMember : Copy(s, "Member")
+    | nkParam : Copy(s, "Param")
+    | nkProc : Copy(s, "Proc")
+    | nkAssign : Copy(s, "Assign")
+    | nkCall : Copy(s, "Call")
+    | nkIf : Copy(s, "If")
+    | nkWhile : Copy(s, "While")
+    | nkRepeat : Copy(s, "Repeat")
+    | nkLoop : Copy(s, "Loop")
+    | nkFor : Copy(s, "For")
+    | nkReturn : Copy(s, "Return")
+    | nkExit : Copy(s, "Exit")
+    | nkBin : Copy(s, "Bin")
+    | nkUn : Copy(s, "Un")
+    | nkName : Copy(s, "Name")
+    | nkInt : Copy(s, "Int")
+    | nkReal : Copy(s, "Real")
+    | nkChar : Copy(s, "Char")
+    | nkStr : Copy(s, "Str")
+    | nkField : Copy(s, "Field")
+    | nkIndex : Copy(s, "Index")
+    | nkDeref : Copy(s, "Deref")
+    | nkCallExpr : Copy(s, "CallExpr")
+    ELSE Copy(s, "?")
+    END
+  END KindName;
+
+PROCEDURE Indent (d: CARDINAL);
+  VAR i: CARDINAL;
+  BEGIN
+    i := 0;
+    WHILE i < d DO WriteString("  "); INC(i) END
+  END Indent;
+
+PROCEDURE Dump (n: Node; d: CARDINAL);
+  VAR kn: ARRAY [0 .. 15] OF CHAR;
+  BEGIN
+    IF n = NIL THEN RETURN END;
+    IF d > 64 THEN Indent(d); WriteString("..."); WriteLn; RETURN END;
+    Indent(d);
+    KindName(n^.kind, kn);
+    WriteString(kn);
+    IF n^.name[0] # 0C THEN
+      WriteChar(" "); WriteString(n^.name)
+    END;
+    IF (n^.kind = nkInt) OR (n^.kind = nkChar)
+       OR (n^.kind = nkCall) OR (n^.kind = nkCallExpr) THEN
+      WriteString(" "); WriteInt(n^.num, 1)
+    END;
+    IF (n^.kind = nkBin) OR (n^.kind = nkUn)
+       OR (n^.kind = nkParam) THEN
+      WriteString(" op="); WriteInt(n^.op, 1)
+    END;
+    IF (n^.kind = nkName) OR (n^.kind = nkVar)
+       OR (n^.kind = nkConst) OR (n^.kind = nkParam)
+       OR (n^.kind = nkTypeDecl) OR (n^.kind = nkMember)
+       OR (n^.kind = nkProc) OR (n^.kind = nkField)
+       OR (n^.kind = nkBin) OR (n^.kind = nkUn)
+       OR (n^.kind = nkInt) OR (n^.kind = nkChar)
+       OR (n^.kind = nkIndex) OR (n^.kind = nkDeref)
+       OR (n^.kind = nkCallExpr) THEN
+      WriteString(" :"); WriteInt(n^.typ, 1)
+    END;
+    IF n^.text[0] # 0C THEN
+      WriteChar(" "); WriteString(n^.text)
+    END;
+    WriteLn;
+    Dump(n^.left, d + 1);
+    Dump(n^.right, d + 1);
+    Dump(n^.extra, d + 1);
+    Dump(n^.more, d + 1);
+    IF n^.next # NIL THEN Dump(n^.next, d) END
+  END Dump;
+
+PROCEDURE DumpTree (n: Node);
+  BEGIN
+    WriteString("--- AST ---"); WriteLn;
+    Dump(n, 0)
+  END DumpTree;
+
+BEGIN
+  root := NIL
+END AST.


+ 324 - 190
src/M2comp.atg

@@ -14,7 +14,7 @@ COMPILER M2comp
    unary minus takes a Factor (3.3), abbreviated arrays (3.1),
    no octal B/C (2.1). "~" never added (2.2); "<>" still accepted. *)
 
-IMPORT SymTab;
+IMPORT SymTab, AST;
 
 CHARACTERS
   eol      = CHR(13) .
@@ -46,162 +46,215 @@ PRODUCTIONS
      the messages still name the right tokens. *)
   M2comp
     = Module "." .
-  Module                              (. VAR m1, m2: SymTab.Name; .)
-    =                                 (. SymTab.Init; .)
+  Module                              (. VAR m1, m2: SymTab.Name;
+                                           d, bd, bs, rt: AST.Node;
+                                           im: AST.Node; .)
+    =                                 (. SymTab.Init; d := NIL; .)
       "MODULE"
       GetIdent<m1>
       ";"
-      { Import }
-      Block
+      { Import<im>                    (. d := AST.Append(d, im); .) }
+      Block<bd, bs>                   (. d := AST.Append(d, bd);
+                                        rt := AST.MkModule(m1, d,
+                                          AST.MkBlock(NIL, bs));
+                                        AST.SetRoot(rt); .)
       GetIdent<m2>                    (. IF ~SymTab.Equal(m1, m2) THEN
                                          SemError(202) END;
-                                        SymTab.PrintTable; .) .
-  Import                              (. VAR n: SymTab.Name; .)
-    = [ "FROM"
-        GetIdent<n>                   (. IF ~SymTab.Enter(n,
+                                        SymTab.PrintTable;
+                                        AST.DumpTree(
+                                          AST.GetRoot()); .) .
+  Import<VAR n: AST.Node>              (. VAR mod: SymTab.Name;
+                                           h: AST.Node;
+                                           m: SymTab.Name; .)
+    =                                 (. mod[0] := 0C; .)
+      [ "FROM"
+        GetIdent<m>                   (. IF ~SymTab.Enter(m,
                                            SymTab.KindImport)
-                                         THEN SemError(200) END; .) ]
+                                         THEN SemError(200) END;
+                                        mod := m; .) ]
       "IMPORT"
-      IdentList
-      ";" .
-  IdentList                           (. VAR n: SymTab.Name; .)
+      IdentList<h>
+      ";"                             (. n := AST.MkImport(mod, h); .) .
+  IdentList<VAR h: AST.Node>          (. VAR n: SymTab.Name; .)
     = GetIdent<n>                     (. IF ~SymTab.Enter(n,
                                            SymTab.KindImport)
-                                         THEN SemError(200) END; .)
+                                         THEN SemError(200) END;
+                                        h := AST.MkImpName(n); .)
       { ","
         GetIdent<n>                   (. IF ~SymTab.Enter(n,
                                            SymTab.KindImport)
-                                         THEN SemError(200) END; .) } .
+                                         THEN SemError(200) END;
+                                        h := AST.Append(h,
+                                          AST.MkImpName(n)); .) } .
   GetIdent<VAR n: SymTab.Name>
     = ident                           (. LexName(n); .) .
-  Block
-    = { Declaration }
+  Block<VAR d: AST.Node; VAR s: AST.Node>
+                                      (. VAR dn: AST.Node; .)
+    =                                 (. d := NIL; s := NIL; .)
+      { Declaration<dn>               (. d := AST.Append(d, dn); .) }
       [ "BEGIN"
-        StatSeq ]
+        StatSeq<s> ]
       "END" .
-  Declaration
-    = "CONST"
-      { ConstDecl ";" }
-    | "TYPE"
-      { TypeDecl ";" }
-    | "VAR"
-      { VarDecl ";" }
-    | ProcDecl
+  Declaration<VAR n: AST.Node>        (. VAR cn: AST.Node; .)
+    = "CONST"                         (. n := NIL; .)
+      { ConstDecl<cn> ";"             (. n := AST.Append(n, cn); .) }
+    | "TYPE"                          (. n := NIL; .)
+      { TypeDecl<cn> ";"              (. n := AST.Append(n, cn); .) }
+    | "VAR"                           (. n := NIL; .)
+      { VarDecl<cn> ";"               (. n := AST.Append(n, cn); .) }
+    | ProcDecl<n>
       ";"
-    | ModuleDecl
+    | ModuleDecl<n>
       ";" .
-  ConstDecl                           (. VAR n: SymTab.Name;
-                                           t: SymTab.TypeIndex; .)
-    = GetIdent<n>                     (. IF ~SymTab.Enter(n,
+  ConstDecl<VAR n: AST.Node>          (. VAR nm: SymTab.Name;
+                                           t: SymTab.TypeIndex;
+                                           en: AST.Node; .)
+    = GetIdent<nm>                    (. IF ~SymTab.Enter(nm,
                                            SymTab.KindConst)
                                          THEN SemError(200) END; .)
       "="
-      ConstExpr<t>                    (. SymTab.SetSymType(n, t); .) .
-  ConstExpr<VAR t: SymTab.TypeIndex>
+      ConstExpr<t, en>                (. SymTab.SetSymType(nm, t);
+                                        n := AST.MkConst(nm, en,
+                                          t); .) .
+  ConstExpr<VAR t: SymTab.TypeIndex; VAR e: AST.Node>
                                       (. VAR vD: BOOLEAN; .)
-    = Expr<t, vD> .
-  TypeDecl                            (. VAR n: SymTab.Name;
+    = Expr<t, vD, e> .
+  TypeDecl<VAR n: AST.Node>           (. VAR nm: SymTab.Name;
                                            t0, t1: SymTab.TypeIndex; .)
-    = GetIdent<n>                     (. IF ~SymTab.Enter(n,
+    = GetIdent<nm>                    (. IF ~SymTab.Enter(nm,
                                            SymTab.KindType)
                                          THEN SemError(200) END;
                                         t0 := SymTab.NewAlias();
-                                        SymTab.SetSymType(n, t0); .)
+                                        SymTab.SetSymType(nm, t0); .)
       "="
       Type<t1>                        (. IF t1 = t0 THEN SemError(223);
                                          SymTab.SetTarget(t0,
                                            SymTab.InvalidType)
-                                       ELSE SymTab.SetTarget(t0, t1) END; .) .
-  VarDecl                             (. VAR t: SymTab.TypeIndex; .)
-    = VarIdents ":"
+                                       ELSE SymTab.SetTarget(t0, t1) END;
+                                        n := AST.MkTypeDecl(nm,
+                                          t1); .) .
+  VarDecl<VAR n: AST.Node>            (. VAR t: SymTab.TypeIndex;
+                                           h: AST.Node; .)
+    = VarIdents<h> ":"
       Type<t>                         (. IF SymTab.IsOpen(t) THEN
                                          SemError(230) END;
-                                        SymTab.FixPending(t); .) .
-  VarIdents                           (. VAR n: SymTab.Name; .)
-    = GetIdent<n>                     (. IF ~SymTab.EnterPending(n,
+                                        AST.SetChainType(h, t);
+                                        SymTab.FixPending(t);
+                                        n := h; .) .
+  VarIdents<VAR h: AST.Node>          (. VAR nm: SymTab.Name; .)
+    = GetIdent<nm>                    (. IF ~SymTab.EnterPending(nm,
                                            SymTab.KindVar)
-                                         THEN SemError(200) END; .)
+                                         THEN SemError(200) END;
+                                        h := AST.MkVar(nm,
+                                          SymTab.InvalidType); .)
       { ","
-        GetIdent<n>                   (. IF ~SymTab.EnterPending(n,
+        GetIdent<nm>                  (. IF ~SymTab.EnterPending(nm,
                                            SymTab.KindVar)
-                                         THEN SemError(200) END; .) } .
-  ProcDecl                            (. VAR m1, m2: SymTab.Name;
-                                           rt: SymTab.TypeIndex; .)
-    = "PROCEDURE"
+                                         THEN SemError(200) END;
+                                        h := AST.Append(h,
+                                          AST.MkVar(nm,
+                                          SymTab.InvalidType)); .) } .
+  ProcDecl<VAR n: AST.Node>           (. VAR m1, m2: SymTab.Name;
+                                           rt, ret: SymTab.TypeIndex;
+                                           p, bd, bs: AST.Node; .)
+    =                                 (. ret := SymTab.InvalidType;
+                                         p := NIL; .)
+      "PROCEDURE"
       GetIdent<m1>                    (. IF ~SymTab.EnterProc(m1) THEN
                                          SemError(200) END;
                                         SymTab.OpenProcScope; .)
-      [ FormalParams ]
+      [ FormalParams<p> ]
       [ ":"
-        QualIdent<rt>                 (. SymTab.SetProcRet(rt); .) ]
+        QualIdent<rt>                 (. ret := rt;
+                                        SymTab.SetProcRet(rt); .) ]
       ";"
-      Block
+      Block<bd, bs>                   (. n := AST.MkProc(m1, ret, p,
+                                          AST.MkBlock(bd, bs)); .)
       GetIdent<m2>                    (. IF ~SymTab.Equal(m1, m2) THEN
                                          SemError(202) END;
                                         SymTab.CloseProc; .) .
-  FormalParams
-    = "("
-      [ FPSection
-        { ";"
-          FPSection } ]
+  FormalParams<VAR p: AST.Node>       (. VAR ps: AST.Node; .)
+    = "("                             (. p := NIL; .)
+      [ FPSection<ps>                 (. p := AST.Append(p, ps); .)
+        { ";" FPSection<ps>           (. p := AST.Append(p, ps); .) } ]
       ")" .
-  FPSection                           (. VAR isV: BOOLEAN;
+  FPSection<VAR p: AST.Node>          (. VAR isV: BOOLEAN;
                                            t: SymTab.TypeIndex; .)
     =                                 (. isV := FALSE; .)
       [ "VAR"                         (. isV := TRUE; .) ]
-      FPIdents<isV> ":"
+      FPIdents<isV, p> ":"
       Type<t>                         (. IF SymTab.IsOpen(t) & ~isV THEN
                                          SemError(230) END;
+                                        AST.SetChainType(p, t);
                                         IF ~SymTab.FixParamPending(t) THEN
                                           SemError(200) END; .) .
-  FPIdents<isV: BOOLEAN>              (. VAR n: SymTab.Name; .)
+  FPIdents<isV: BOOLEAN; VAR p: AST.Node>
+                                      (. VAR n: SymTab.Name; .)
     = GetIdent<n>                     (. IF ~SymTab.EnterParamPending(n,
                                            isV) THEN
-                                         SemError(200) END; .)
+                                         SemError(200) END;
+                                        p := AST.MkParam(n,
+                                          SymTab.InvalidType,
+                                          isV); .)
       { ","
         GetIdent<n>                   (. IF ~SymTab.EnterParamPending(n,
                                            isV) THEN
-                                         SemError(200) END; .) } .
-  ModuleDecl                          (. VAR m1, m2: SymTab.Name; .)
+                                         SemError(200) END;
+                                        p := AST.Append(p,
+                                          AST.MkParam(n,
+                                          SymTab.InvalidType,
+                                          isV)); .) } .
+  ModuleDecl<VAR n: AST.Node>         (. VAR m1, m2: SymTab.Name;
+                                           d, bd, bs: AST.Node;
+                                           im, en: AST.Node; .)
     = "MODULE"                        (* local module, Wirth form *)
+                                      (. d := NIL; .)
       GetIdent<m1>                    (. IF ~SymTab.EnterModule(m1) THEN
                                          SemError(200) END; .)
       [ Priority ]
       ";"
-      { Import }
-      [ Export ]
-      Block
+      { Import<im>                    (. d := AST.Append(d, im); .) }
+      [ Export<en>                    (. d := AST.Append(d, en); .) ]
+      Block<bd, bs>                   (. d := AST.Append(d, bd);
+                                        n := AST.MkModule(m1, d,
+                                          AST.MkBlock(NIL, bs)); .)
       GetIdent<m2>                    (. IF ~SymTab.Equal(m1, m2) THEN
                                          SemError(202) END;
                                         IF ~SymTab.ExitModule() THEN
                                           SemError(201) END; .) .
   Priority                            (. VAR t: SymTab.TypeIndex;
-                                           vD: BOOLEAN; .)
+                                           vD: BOOLEAN;
+                                           en: AST.Node; .)
     = "["
-      Expr<t, vD>
+      Expr<t, vD, en>
       "]" .
-  Export                              (. VAR n: SymTab.Name; .)
+  Export<VAR n: AST.Node>             (. VAR nm: SymTab.Name;
+                                           h: AST.Node; .)
     = "EXPORT"
       [ "QUALIFIED" ]
-      GetIdent<n>                     (. IF ~SymTab.ModuleAddExp(n) THEN
-                                         SemError(200) END; .)
+      GetIdent<nm>                    (. IF ~SymTab.ModuleAddExp(nm) THEN
+                                         SemError(200) END;
+                                        h := AST.MkImpName(nm); .)
       { ","
-        GetIdent<n>                   (. IF ~SymTab.ModuleAddExp(n) THEN
-                                         SemError(200) END; .) }
-      ";" .
+        GetIdent<nm>                  (. IF ~SymTab.ModuleAddExp(nm) THEN
+                                         SemError(200) END;
+                                        h := AST.Append(h,
+                                          AST.MkImpName(nm)); .) }
+      ";"                             (. n := AST.MkExport(h); .) .
   Type<VAR t: SymTab.TypeIndex>
                                       (. VAR c: CARDINAL;
-                                           e, s: SymTab.TypeIndex; .)
+                                           e, s: SymTab.TypeIndex;
+                                           fh: AST.Node; .)
     = BoundedBase<t>
     | "ARRAY"                         (* abbreviated form only (3.1);
                                          nested ARRAY OF ARRAY long form
-                                         flagged in step 3 sizing *)
+                                         flagged in step 4 sizing *)
                                       (. c := 0; .)
       [ IdxList<c> ]
       "OF"
       Type<e>                         (. t := SymTab.WrapArray(e, c); .)
     | "RECORD"                        (. t := SymTab.NewRecord(); .)
-      FieldSeq<t>
+      FieldSeq<t, fh>
       "END"
     | "SET"
       "OF"
@@ -219,10 +272,11 @@ PRODUCTIONS
       Type<e>                         (. t := SymTab.NewPtr(e); .) .
   BoundedBase<VAR t: SymTab.TypeIndex>
                                       (. VAR t1, t2: SymTab.TypeIndex;
-                                           vD, vD2: BOOLEAN; .)
+                                           vD, vD2: BOOLEAN;
+                                           en: AST.Node; .)
     = QualIdent<t>
       [ "["
-        Expr<t1, vD>                  (. IF (t1 # SymTab.InvalidType)
+        Expr<t1, vD, en>              (. IF (t1 # SymTab.InvalidType)
                                          & (SymTab.ClassOf(t1) #
                                             SymTab.ClInt)
                                          & (SymTab.ClassOf(t1) #
@@ -231,7 +285,7 @@ PRODUCTIONS
                                             SymTab.ClEnum) THEN
                                          SemError(224) END; .)
         ".."
-        Expr<t2, vD2>                 (. IF (t2 # SymTab.InvalidType)
+        Expr<t2, vD2, en>             (. IF (t2 # SymTab.InvalidType)
                                          & (SymTab.ClassOf(t2) #
                                             SymTab.ClInt)
                                          & (SymTab.ClassOf(t2) #
@@ -241,7 +295,7 @@ PRODUCTIONS
                                          SemError(224) END; .)
         "]"                           (. t := SymTab.NewSub(t1); .) ]
     | "["
-      Expr<t1, vD>                    (. IF (t1 # SymTab.InvalidType)
+      Expr<t1, vD, en>                (. IF (t1 # SymTab.InvalidType)
                                          & (SymTab.ClassOf(t1) #
                                             SymTab.ClInt)
                                          & (SymTab.ClassOf(t1) #
@@ -250,7 +304,7 @@ PRODUCTIONS
                                             SymTab.ClEnum) THEN
                                          SemError(224) END; .)
       ".."
-      Expr<t2, vD2>                   (. IF (t2 # SymTab.InvalidType)
+      Expr<t2, vD2, en>               (. IF (t2 # SymTab.InvalidType)
                                          & (SymTab.ClassOf(t2) #
                                             SymTab.ClInt)
                                          & (SymTab.ClassOf(t2) #
@@ -281,19 +335,31 @@ PRODUCTIONS
                                         INC(c); .) } .
   IndexType<VAR t: SymTab.TypeIndex>
     = BoundedBase<t> .
-  FieldSeq<rt: SymTab.TypeIndex>
-    = Field<rt>
+  FieldSeq<rt: SymTab.TypeIndex; VAR h: AST.Node>
+                                      (. VAR fn: AST.Node; .)
+    = Field<rt, fn>                   (. h := fn; .)
       { ";"
-        Field<rt> } .
-  Field<rt: SymTab.TypeIndex>         (. VAR et: SymTab.TypeIndex; .)
-    = [ FieldIdents<rt> ":"
-        Type<et>                      (. SymTab.FixPendingF(rt, et); .) ] .
-  FieldIdents<rt: SymTab.TypeIndex>   (. VAR n: SymTab.Name; .)
-    = GetIdent<n>                     (. IF ~SymTab.FieldPending(rt, n)
-                                         THEN SemError(200) END; .)
+        Field<rt, fn>                 (. h := AST.Append(h, fn); .) } .
+  Field<rt: SymTab.TypeIndex; VAR n: AST.Node>
+                                      (. VAR et: SymTab.TypeIndex;
+                                           h: AST.Node; .)
+    =                                 (. n := NIL; .)
+      [ FieldIdents<rt, h> ":"
+        Type<et>                      (. AST.SetChainType(h, et);
+                                        SymTab.FixPendingF(rt, et);
+                                        n := h; .) ] .
+  FieldIdents<rt: SymTab.TypeIndex; VAR h: AST.Node>
+                                      (. VAR nm: SymTab.Name; .)
+    = GetIdent<nm>                    (. IF ~SymTab.FieldPending(rt, nm)
+                                         THEN SemError(200) END;
+                                        h := AST.MkMember(nm,
+                                          SymTab.InvalidType); .)
       { ","
-        GetIdent<n>                   (. IF ~SymTab.FieldPending(rt, n)
-                                         THEN SemError(200) END; .) } .
+        GetIdent<nm>                  (. IF ~SymTab.FieldPending(rt, nm)
+                                         THEN SemError(200) END;
+                                        h := AST.Append(h,
+                                          AST.MkMember(nm,
+                                          SymTab.InvalidType)); .) } .
   QualIdent<VAR t: SymTab.TypeIndex>
                                       (. VAR n, m: SymTab.Name;
                                            modHead: BOOLEAN; .)
@@ -339,28 +405,31 @@ PRODUCTIONS
                                           SemError(221);
                                           t := SymTab.InvalidType
                                         END; .) } .
-  StatSeq
-    = Stat
+  StatSeq<VAR s: AST.Node>            (. VAR st: AST.Node; .)
+    = Stat<st>                        (. s := st; .)
       { ";"
-        Stat } .
-  Stat
-    = [ AssignOrCall
-      | IfStat
-      | WhileStat
-      | RepeatStat
-      | LoopStat
-      | ForStat
-      | ReturnStat
+        Stat<st>                      (. s := AST.Append(s, st); .) } .
+  Stat<VAR s: AST.Node>
+    =                                 (. s := NIL; .)
+      [ AssignOrCall<s>
+      | IfStat<s>
+      | WhileStat<s>
+      | RepeatStat<s>
+      | LoopStat<s>
+      | ForStat<s>
+      | ReturnStat<s>
       | "EXIT"                        (. IF ~SymTab.InLoop() THEN
-                                         SemError(230) END; .) ] .
-  AssignOrCall                        (. VAR dt, et: SymTab.TypeIndex;
+                                         SemError(230) END;
+                                        s := AST.MkExit(); .) ] .
+  AssignOrCall<VAR s: AST.Node>       (. VAR dt, et: SymTab.TypeIndex;
                                            dk, pn: INTEGER;
                                            ev: BOOLEAN;
                                            nn: CARDINAL;
-                                           hadP: BOOLEAN; .)
-    = Designator<dt, dk, pn>
+                                           hadP: BOOLEAN;
+                                           dn, en, ah: AST.Node; .)
+    = Designator<dt, dk, pn, dn>
       ( ":="
-        Expr<et, ev>                  (. IF dt = SymTab.InvalidType THEN
+        Expr<et, ev, en>               (. IF dt = SymTab.InvalidType THEN
                                           (* cascade *)
                                         ELSIF (dk # SymTab.KindVar)
                                            & (dk # SymTab.KindParam)
@@ -369,8 +438,10 @@ PRODUCTIONS
                                           SemError(210)
                                         ELSIF ~SymTab.Assignable(et,
                                            dt) THEN
-                                          SemError(210) END; .)
+                                          SemError(210) END;
+                                        s := AST.MkAssign(dn, en); .)
       |                               (. hadP := FALSE; nn := 0;
+                                         ah := NIL;
                                          IF dk = SymTab.KindProc THEN
                                            SymTab.CallBeginNum(pn)
                                          ELSE
@@ -379,15 +450,18 @@ PRODUCTIONS
                                          IF (dk # SymTab.KindProc)
                                             & (dk # -1) THEN
                                            SemError(233) END; .)
-        [ ActParams<nn>               (. hadP := TRUE; .) ]
+        [ ActParams<ah, nn>            (. hadP := TRUE; .) ]
         (. IF ~SymTab.CallEndNum(nn) THEN
-             SemError(233) END; .) ) .
+             SemError(233) END;
+           s := AST.MkCall(dn, ah, pn); .) ) .
   Designator<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
-             VAR pn: INTEGER>         (. VAR n, m: SymTab.Name;
+             VAR pn: INTEGER; VAR dn: AST.Node>
+                                        (. VAR n, m: SymTab.Name;
                                            it, it2: SymTab.TypeIndex;
                                            iv, iv2: BOOLEAN;
                                            ek, sk, p2: INTEGER;
-                                           modHead: BOOLEAN; .)
+                                           modHead: BOOLEAN;
+                                           en, en2, ih: AST.Node; .)
     = GetIdent<n>                     (. modHead := FALSE;
                                         IF ~SymTab.Lookup(n) THEN
                                           SemError(201);
@@ -405,7 +479,8 @@ PRODUCTIONS
                                             pn := SymTab.ProcNum(n)
                                           ELSE pn := -1
                                           END
-                                        END; .)
+                                        END;
+                                        dn := AST.MkName(n, t); .)
       { "." GetIdent<m>               (. IF modHead THEN
                                           modHead := FALSE;
                                           ek := SymTab.ExpKind(n, m);
@@ -466,8 +541,9 @@ PRODUCTIONS
                                             m);
                                           k := SymTab.KindField;
                                           pn := -1
-                                        END; .)
-      | "[" Expr<it, iv>              (. IF t = SymTab.InvalidType THEN
+                                        END;
+                                        dn := AST.MkField(dn, m, t); .)
+      | "[" Expr<it, iv, en>            (. IF t = SymTab.InvalidType THEN
                                           (* cascade *)
                                         ELSIF SymTab.ClassOf(t) #
                                            SymTab.ClArray THEN
@@ -484,8 +560,9 @@ PRODUCTIONS
                                         ELSE t := SymTab.ArrayElem(
                                             t);
                                           pn := -1
-                                        END; .)
-        { "," Expr<it2, iv2>          (. IF t = SymTab.InvalidType THEN
+                                        END;
+                                        ih := en; .)
+        { "," Expr<it2, iv2, en2>        (. IF t = SymTab.InvalidType THEN
                                           (* cascade *)
                                         ELSIF SymTab.ClassOf(t) #
                                            SymTab.ClArray THEN
@@ -498,8 +575,10 @@ PRODUCTIONS
                                               it2) THEN
                                           SemError(218)
                                         ELSE t := SymTab.ArrayElem(
-                                            t) END; .) }
-        "]"
+                                            t) END;
+                                        ih := AST.Append(ih, en2); .) }
+        "]"                             (. dn := AST.MkIndex(dn, ih,
+                                          t); .)
       | "^"                           (. IF t = SymTab.InvalidType THEN
                                           (* cascade *)
                                         ELSIF SymTab.ClassOf(t) #
@@ -509,56 +588,76 @@ PRODUCTIONS
                                           k := -1; pn := -1
                                         ELSE t := SymTab.PtrBase(t);
                                           pn := -1
-                                        END; .) } .
-  ActParams<VAR n: CARDINAL>          (. VAR at: SymTab.TypeIndex;
-                                           av: BOOLEAN; .)
-    = "("                             (. n := 0; .)
-      [ Expr<at, av>                  (. IF ~SymTab.CallActual(at,
+                                        END;
+                                        dn := AST.MkDeref(dn, t); .) } .
+  ActParams<VAR h: AST.Node; VAR n: CARDINAL>
+                                      (. VAR at: SymTab.TypeIndex;
+                                           av: BOOLEAN;
+                                           ae: AST.Node; .)
+    = "("                             (. h := NIL; n := 0; .)
+      [ Expr<at, av, ae>              (. IF ~SymTab.CallActual(at,
                                            av) THEN
                                          SemError(233) END;
+                                        h := AST.Append(h, ae);
                                         n := 1; .)
-        { "," Expr<at, av>            (. IF ~SymTab.CallActual(at,
+        { "," Expr<at, av, ae>        (. IF ~SymTab.CallActual(at,
                                            av) THEN
                                          SemError(233) END;
+                                        h := AST.Append(h, ae);
                                         INC(n); .) } ]
       ")" .
-  IfStat                              (. VAR t: SymTab.TypeIndex;
-                                           vD: BOOLEAN; .)
+  IfStat<VAR s: AST.Node>             (. VAR t: SymTab.TypeIndex;
+                                           vD: BOOLEAN;
+                                           cn, th, el, p: AST.Node; .)
     = "IF"
-      Expr<t, vD>                     (. IF ~SymTab.BoolCheck(t) THEN
+      Expr<t, vD, cn>                 (. IF ~SymTab.BoolCheck(t) THEN
                                          SemError(214) END; .)
       "THEN"
-      StatSeq
+      StatSeq<th>                     (. s := AST.MkIf(cn, th, NIL); .)
       { "ELSIF"
-        Expr<t, vD>                   (. IF ~SymTab.BoolCheck(t) THEN
+        Expr<t, vD, cn>               (. IF ~SymTab.BoolCheck(t) THEN
                                          SemError(214) END; .)
         "THEN"
-        StatSeq }
+        StatSeq<th>                   (. th := AST.MkIf(cn, th, NIL);
+                                        p := s;
+                                        WHILE p^.extra # NIL DO
+                                          p := p^.extra
+                                        END;
+                                        p^.extra := th; .) }
       [ "ELSE"
-        StatSeq ]
+        StatSeq<el>                   (. p := s;
+                                        WHILE p^.extra # NIL DO
+                                          p := p^.extra
+                                        END;
+                                        p^.extra := el; .) ]
       "END" .
-  WhileStat                           (. VAR t: SymTab.TypeIndex;
-                                           vD: BOOLEAN; .)
+  WhileStat<VAR s: AST.Node>          (. VAR t: SymTab.TypeIndex;
+                                           vD: BOOLEAN;
+                                           cn, bd: AST.Node; .)
     = "WHILE"
-      Expr<t, vD>                     (. IF ~SymTab.BoolCheck(t) THEN
+      Expr<t, vD, cn>                 (. IF ~SymTab.BoolCheck(t) THEN
                                          SemError(214) END; .)
       "DO"
-      StatSeq
+      StatSeq<bd>                     (. s := AST.MkWhile(cn, bd); .)
       "END" .
-  RepeatStat                          (. VAR t: SymTab.TypeIndex;
-                                           vD: BOOLEAN; .)
+  RepeatStat<VAR s: AST.Node>         (. VAR t: SymTab.TypeIndex;
+                                           vD: BOOLEAN;
+                                           cn, bd: AST.Node; .)
     = "REPEAT"
-      StatSeq
+      StatSeq<bd>
       "UNTIL"
-      Expr<t, vD>                     (. IF ~SymTab.BoolCheck(t) THEN
-                                         SemError(214) END; .) .
-  LoopStat
+      Expr<t, vD, cn>                 (. IF ~SymTab.BoolCheck(t) THEN
+                                         SemError(214) END;
+                                        s := AST.MkRepeat(bd, cn); .) .
+  LoopStat<VAR s: AST.Node>           (. VAR bd: AST.Node; .)
     = "LOOP"                          (. SymTab.LoopEnter; .)
-      StatSeq
-      "END"                           (. SymTab.LoopExit; .) .
-  ForStat                             (. VAR n: SymTab.Name;
+      StatSeq<bd>
+      "END"                           (. SymTab.LoopExit;
+                                        s := AST.MkLoop(bd); .) .
+  ForStat<VAR s: AST.Node>            (. VAR n: SymTab.Name;
                                            lo, hi, by: SymTab.TypeIndex;
-                                           lv, lv2, lv3: BOOLEAN; .)
+                                           lv, lv2, lv3: BOOLEAN;
+                                           ln, hn, bn, bd: AST.Node; .)
     = "FOR"
       GetIdent<n>                     (. IF ~SymTab.Lookup(n) THEN
                                           SemError(201)
@@ -577,35 +676,41 @@ PRODUCTIONS
                                               SymTab.SymType(n)) THEN
                                           SemError(220) END; .)
       ":="
-      Expr<lo, lv>                    (. IF (lo # SymTab.InvalidType)
+      Expr<lo, lv, ln>                (. IF (lo # SymTab.InvalidType)
                                          & ~SymTab.IsIntFamily(lo) THEN
                                          SemError(220) END; .)
       "TO"
-      Expr<hi, lv2>                   (. IF (hi # SymTab.InvalidType)
+      Expr<hi, lv2, hn>               (. IF (hi # SymTab.InvalidType)
                                          & ~SymTab.IsIntFamily(hi) THEN
-                                         SemError(220) END; .)
+                                         SemError(220) END;
+                                        bn := NIL; .)
       [ "BY"
-        Expr<by, lv3>                 (. IF (by # SymTab.InvalidType)
+        Expr<by, lv3, bn>             (. IF (by # SymTab.InvalidType)
                                          & ~SymTab.IsIntFamily(by) THEN
                                          SemError(220) END; .) ]
       "DO"
-      StatSeq
+      StatSeq<bd>                     (. s := AST.MkFor(n, ln, hn, bn,
+                                          bd); .)
       "END" .
-  ReturnStat                          (. VAR et: SymTab.TypeIndex;
-                                           ev, hasE: BOOLEAN; .)
-    =                                 (. hasE := FALSE; .)
+  ReturnStat<VAR s: AST.Node>         (. VAR et: SymTab.TypeIndex;
+                                           ev, hasE: BOOLEAN;
+                                           en, e0: AST.Node; .)
+    =                                 (. hasE := FALSE; e0 := NIL; .)
       "RETURN"
-      [ Expr<et, ev>                  (. hasE := TRUE; .) ]
+      [ Expr<et, ev, en>              (. hasE := TRUE; e0 := en; .) ]
       (. IF ~SymTab.InProc() THEN SemError(232)
          ELSIF SymTab.InFunction() & ~hasE THEN SemError(232)
          ELSIF ~SymTab.InFunction() & hasE THEN
-           SemError(232) END; .) .
-  Expr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN>
+           SemError(232) END;
+        s := AST.MkReturn(e0); .) .
+  Expr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
+       VAR e: AST.Node>
                                       (. VAR t2: SymTab.TypeIndex;
                                            v2: BOOLEAN;
-                                           op: INTEGER; .)
-    = SimExpr<t, v>
-      [ Relation<op> SimExpr<t2, v2>
+                                           op: INTEGER;
+                                           e2: AST.Node; .)
+    = SimExpr<t, v, e>
+      [ Relation<op> SimExpr<t2, v2, e2>
         (. v := FALSE;
            IF op = SymTab.OpIn THEN
              IF SymTab.InCheck(t, t2) THEN
@@ -615,7 +720,8 @@ PRODUCTIONS
              IF SymTab.RelCheck(t, t2, op) THEN
                t := SymTab.BoolType()
              ELSE SemError(213); t := SymTab.InvalidType END
-           END; .) ] .
+           END;
+           e := AST.MkBin(op, e, e2, t); .) ] .
   Relation<VAR op: INTEGER>
     = "="                             (. op := SymTab.OpEq; .)
     | "#"                             (. op := SymTab.OpNeq1; .)
@@ -625,24 +731,30 @@ PRODUCTIONS
     | ">"                             (. op := SymTab.OpGt; .)
     | ">="                            (. op := SymTab.OpGe; .)
     | "IN"                            (. op := SymTab.OpIn; .) .
-  SimExpr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN>
+  SimExpr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
+          VAR e: AST.Node>
                                       (. VAR t2, res2: SymTab.TypeIndex;
                                            v2: BOOLEAN;
-                                           op: INTEGER; .)
-    = ( "+" Term<t, v>                (. IF ~SymTab.UnaryCheck(t,
+                                           op: INTEGER;
+                                           e2: AST.Node; .)
+    = ( "+" Term<t, v, e>             (. IF ~SymTab.UnaryCheck(t,
                                            res2) THEN
                                          SemError(211);
                                          t := SymTab.InvalidType
                                        ELSE t := res2 END;
-                                        v := FALSE; .)
-      | "-" Fact<t, v>                (. IF ~SymTab.UnaryCheck(t,
+                                        v := FALSE;
+                                        e := AST.MkUn(AST.opPos,
+                                          e, t); .)
+      | "-" Fact<t, v, e>             (. IF ~SymTab.UnaryCheck(t,
                                            res2) THEN
                                          SemError(211);
                                          t := SymTab.InvalidType
                                        ELSE t := res2 END;
-                                        v := FALSE; .)
-      | Term<t, v> )
-      { AddOp<op> Term<t2, v2>
+                                        v := FALSE;
+                                        e := AST.MkUn(AST.opNeg,
+                                          e, t); .)
+      | Term<t, v, e> )
+      { AddOp<op> Term<t2, v2, e2>
         (. v := FALSE;
            IF op = SymTab.OpOr THEN
              IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
@@ -652,17 +764,20 @@ PRODUCTIONS
              IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
                t := res2
              ELSE SemError(211); t := SymTab.InvalidType END
-           END; .) } .
+           END;
+           e := AST.MkBin(op, e, e2, t); .) } .
   AddOp<VAR op: INTEGER>
     = "+"                             (. op := SymTab.OpAdd; .)
     | "-"                             (. op := SymTab.OpSub; .)
     | "OR"                            (. op := SymTab.OpOr; .) .
-  Term<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN>
+  Term<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
+       VAR e: AST.Node>
                                       (. VAR t2, res2: SymTab.TypeIndex;
                                            v2: BOOLEAN;
-                                           op: INTEGER; .)
-    = Fact<t, v>
-      { MulOp<op> Fact<t2, v2>
+                                           op: INTEGER;
+                                           e2: AST.Node; .)
+    = Fact<t, v, e>
+      { MulOp<op> Fact<t2, v2, e2>
         (. v := FALSE;
            IF op = SymTab.OpAnd THEN
              IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
@@ -673,33 +788,45 @@ PRODUCTIONS
                   (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
                   res2) THEN t := res2
              ELSE SemError(211); t := SymTab.InvalidType END
-           END; .) } .
+           END;
+           e := AST.MkBin(op, e, e2, t); .) } .
   MulOp<VAR op: INTEGER>
     = "*"                             (. op := SymTab.OpTimes; .)
     | "/"                             (. op := SymTab.OpSlash; .)
     | "DIV"                           (. op := SymTab.OpDiv; .)
     | "MOD"                           (. op := SymTab.OpMod; .)
     | "AND"                           (. op := SymTab.OpAnd; .) .
-  Fact<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN>
+  Fact<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
+       VAR e: AST.Node>
                                       (. VAR s: ARRAY [0 .. 255] OF CHAR;
                                            t2, et, dt: SymTab.TypeIndex;
                                            dk, pn: INTEGER;
                                            nn: CARDINAL;
                                            hadP, ce, pushed: BOOLEAN;
-                                           ev, v2: BOOLEAN; .)
+                                           ev, v2: BOOLEAN;
+                                           dn, ah, en: AST.Node;
+                                           iv: INTEGER;
+                                           ok: BOOLEAN; .)
     = integer                         (. LexString(s);
                                         t := SymTab.IntType();
-                                        v := FALSE; .)
+                                        v := FALSE;
+                                        ok := AST.ParseInt(s, iv);
+                                        IF ~ok THEN iv := 0 END;
+                                        e := AST.MkInt(iv, t); .)
     | real                            (. LexString(s);
                                         t := SymTab.RealType();
-                                        v := FALSE; .)
+                                        v := FALSE;
+                                        e := AST.MkReal(s, t); .)
     | string                          (. LexString(s);
                                         IF SymTab.StrLen(s) <= 3 THEN
-                                          t := SymTab.CharType()
-                                        ELSE t := SymTab.NewStr()
+                                          t := SymTab.CharType();
+                                          e := AST.MkChar(
+                                            ORD(s[1]), t)
+                                        ELSE t := SymTab.NewStr();
+                                          e := AST.MkStr(s, t)
                                         END;
                                         v := FALSE; .)
-    | Designator<dt, dk, pn>          (. hadP := FALSE; nn := 0;
+    | Designator<dt, dk, pn, dn>      (. hadP := FALSE; nn := 0;
                                         IF dk = SymTab.KindProc THEN
                                           SymTab.CallBeginNum(pn);
                                           pushed := TRUE
@@ -709,7 +836,7 @@ PRODUCTIONS
                                           SymTab.CallBeginNum(-1);
                                           pushed := TRUE
                                         END; .)
-        ActParams<nn>                 (. hadP := TRUE; .) ]
+        ActParams<ah, nn>             (. hadP := TRUE; .) ]
                                       (. IF pushed THEN
                                           ce := SymTab.CallEndNum(nn)
                                         END;
@@ -728,12 +855,15 @@ PRODUCTIONS
                                             t := SymTab.InvalidType
                                           ELSE t :=
                                             SymTab.ProcRetByNum(pn)
-                                          END
+                                          END;
+                                          e := AST.MkCallExpr(dn, ah,
+                                            pn, t)
                                         ELSE
                                           IF dk = SymTab.KindProc THEN
                                             SemError(233);
                                             t := SymTab.InvalidType;
-                                            v := FALSE
+                                            v := FALSE;
+                                            e := AST.MkName("?", t)
                                           ELSE
                                             t := dt;
                                             v := (dt #
@@ -745,13 +875,17 @@ PRODUCTIONS
                                               OR (dk =
                                                  SymTab.KindVarPar)
                                               OR (dk =
-                                                 SymTab.KindField))
+                                                 SymTab.KindField));
+                                            e := dn
                                           END
                                         END; .)
-    | "(" Expr<et, ev> ")"            (. t := et; v := FALSE; .)
-    | "NOT" Fact<t2, v2>              (. IF SymTab.BoolCheck(t2) THEN
+    | "(" Expr<et, ev, en> ")"        (. t := et; v := FALSE;
+                                        e := en; .)
+    | "NOT" Fact<t2, v2, en>          (. IF SymTab.BoolCheck(t2) THEN
                                          t := SymTab.BoolType()
                                        ELSE SemError(212);
                                          t := SymTab.InvalidType END;
-                                        v := FALSE; .) .
+                                        v := FALSE;
+                                        e := AST.MkUn(AST.opNot, en,
+                                          t); .) .
 END M2comp.

+ 1 - 1
src/M2comp.lst

@@ -21,7 +21,7 @@ Statistics:
   nr of non-terminals:    45 (limit   210)
   nr of pragmas:           0 (limit   436)
   nr of symbolnodes:     109 (limit   500)
-  nr of graphnodes:      423 (limit  1500)
+  nr of graphnodes:      457 (limit  1500)
   nr of conditionsets:     6 (limit   100)
   nr of charactersets:     9 (limit   250)
 

Разница между файлами не показана из-за своего большого размера
+ 314 - 197
src/M2compP.mod



+ 3 - 0
src/modules.lst

@@ -62,5 +62,8 @@ TermFile
 FileIO
 M2compS
 SymTab
+STextIO
+SWholeIO
+AST
 M2compP
 M2comp

+ 0 - 36
tests/ok_proc.LST

@@ -1,36 +0,0 @@
-Listing:
-
-    1  MODULE OkProc;
-    2  FROM In IMPORT x;
-    3  IMPORT y, z;
-    4  VAR
-    5    i : INTEGER;
-    6    a : ARRAY [0..9], [0..3] OF INTEGER;
-    7    r : RECORD f : INTEGER; END;
-    8  
-    9  PROCEDURE P(VAR v : INTEGER; n : CARDINAL) : BOOLEAN;
-   10  BEGIN
-   11    IF n > 0 THEN v := -v + 1 ELSE v := 0 END;
-   12    RETURN TRUE
-   13  END P;
-   14  
-   15  MODULE Local;
-   16  EXPORT q;
-   17  VAR q : INTEGER;
-   18  BEGIN
-   19    q := 1
-   20  END Local;
-   21  
-   22  BEGIN
-   23    i := 0;
-   24    WHILE i < 10 DO
-   25      i := i + 1
-   26    END;
-   27    FOR i := 1 TO 10 BY 2 DO
-   28      P(i, i)
-   29    END
-   30  END OkProc.
-
-    0 errors
-
-

+ 0 - 120
tests/showcase.LST

@@ -1,120 +0,0 @@
-Listing:
-
-    1  MODULE Showcase;
-    2  (* Exercises every syntax form of M2comp.atg step 1. *)
-    3  FROM In IMPORT x;
-    4  IMPORT w, dbg;
-    5  
-    6  CONST
-    7    N = 10;
-    8    H = 0FFH;
-    9    R = 3.14;
-   10    E = 2.0E+3;
-   11    S = "hi";
-   12    Q = 'q';
-   13    Neg = -N + 2;
-   14  
-   15  TYPE
-   16    Sub = [0 .. 9];
-   17    RS = INTEGER[1 .. N];
-   18    Vec = ARRAY [0 .. 9] OF INTEGER;
-   19    Mat = ARRAY [0 .. 9], [0 .. 3] OF REAL;
-   20    Rec = RECORD a : INTEGER; b : Vec END;
-   21    Empty = RECORD END;
-   22    Ptr = POINTER TO Rec;
-   23    St = SET OF Sub;
-   24    Boo = BOOLEAN;
-   25    Chars = ARRAY [0 .. 15] OF CHAR;
-   26  
-   27  VAR
-   28    i, j : INTEGER;
-   29    v : Vec;
-   30    m : Mat;
-   31    r : Rec;
-   32    p : Ptr;
-   33    s : St;
-   34    b : BOOLEAN;
-   35    ch : CHAR;
-   36    sa : Chars;
-   37  
-   38  PROCEDURE y(a : INTEGER; VAR s : Chars; w : INTEGER);
-   39  BEGIN
-   40    s[0] := ch;
-   41    a := a + w
-   42  END y;
-   43  
-   44  PROCEDURE z;
-   45  BEGIN
-   46  END z;
-   47  
-   48  PROCEDURE Min(a, b : INTEGER) : INTEGER;
-   49  BEGIN
-   50    IF a < b THEN RETURN a ELSE RETURN b END
-   51  END Min;
-   52  
-   53  PROCEDURE Work(VAR v : Vec; n : CARDINAL; flag : BOOLEAN);
-   54  VAR k : INTEGER;
-   55  
-   56    PROCEDURE Nested(t : INTEGER) : INTEGER;
-   57    BEGIN
-   58      RETURN t * 2
-   59    END Nested;
-   60  
-   61  BEGIN
-   62    k := +n - 1;
-   63    k := -k + 1;
-   64    v[0] := k;
-   65    v[N - 1] := Nested(k);
-   66    m[1, 2] := R;
-   67    r.a := k;
-   68    p^ := r;
-   69    s := s;
-   70    b := (k <= 0) OR (k >= N) OR NOT flag;
-   71    IF k = 0 THEN k := 1
-   72    ELSIF k # 1 THEN k := 2
-   73    ELSE k := 3
-   74    END;
-   75    WHILE k < N DO
-   76      k := k + 1
-   77    END;
-   78    REPEAT
-   79      k := k - 1
-   80    UNTIL k = 0;
-   81    LOOP
-   82      k := k + 1;
-   83      IF k > N THEN EXIT END
-   84    END;
-   85    FOR k := 1 TO N BY 2 DO
-   86      Work(v, k, flag)
-   87    END;
-   88    FOR k := N TO 1 DO
-   89      k := k DIV 2
-   90    END;
-   91    b := (k IN s) AND (H <> 0) AND (Q = Q);
-   92    j := k MOD 3;
-   93    r := r
-   94  END Work;
-   95  
-   96  MODULE Local [3];
-   97  FROM In IMPORT w;
-   98  EXPORT QUALIFIED q;
-   99  VAR q : INTEGER;
-  100  PROCEDURE Init;
-  101  BEGIN
-  102    q := 0
-  103  END Init;
-  104  BEGIN
-  105    q := 1
-  106  END Local;
-  107  
-  108  BEGIN
-  109    i := Min(3, 4) + (2 * 3 - 4 / 2);
-  110    Work(v, N, TRUE);
-  111    Local.q := i;
-  112    y(i, sa, x);
-  113    z
-  114  END Showcase.
-
-    0 errors
-
-

Некоторые файлы не были показаны из-за большого количества измененных файлов