m2comp-step1)Fresh m2comp/ project (distinct from m2c/ at step 11): prove the
toolchain end to end before any language work — Coco/R grammar
→ generated scanner/parser/driver → gm2 -fiso build → test runner.
Lexer and parser are FULLY Coco/R-generated; no hand-written lexer.
m2comp/src/M2comp.atg — Modula-2 program modules:
MODULE + FROM/IMPORT, CONST/TYPE/VAR, PROCEDURE (nested,
value/VAR params, function result), local MODULEs (Wirth form:
[Priority], [Export [QUALIFIED]]), statements (assign/call, IF,
WHILE, REPEAT, LOOP/EXIT, FOR/BY, RETURN), full expressions.
Only check is the MODULE/END name match (error 202).docs/, arXiv:1809.07080): unary minus
takes a Factor (§3.3: -b+c ok, bare -b*c+a rejected, parens
required); abbreviated multi-dim arrays via comma index list with
subrange-capable IndexType (§3.1 strict); no octal B/C suffixes
(§2.1); <> kept (open, §2.2); (*$ *) still comments (open, §2.3/2.4).m2comp/src/ holds ALL sources: M2comp.atg, compiler.frm
(listing driver, no SymTab/MGen yet), scanner.frm,
parser.frm, FileIO.def/.mod (copied from m2c/), generated
M2compS/M2compP/M2comp (.def/.mod), Hello.mod (gm2 smoke test).
Deleted as unnecessary: hand M2Lex (replaced by M2compS),
unused Err, empty build/.m2comp/build.sh — regenerate (CRFRAMES=src CR -m -C),
compile with gm2 -fiso, link via the two-phase module-list
workaround; produces ./M2comp (project root).m2comp/run_tests.sh — expect_ok/expect_fail on
tests/ok_minimal.mod, tests/ok_proc.mod (local module,
2-D abbreviated array, -v+1), tests/bad_mismatch.mod (202).| test | result |
|---|---|
| ok_minimal | MODULE M; BEGIN END M. accepted |
| ok_proc | imports, VAR, 2-D array, proc + local module accepted |
| bad_mismatch | END WrongName rejected (Incorrect source) |
gm2 -fiso src/Hello.mod → Hello m2comp (gm2 -fiso) verified.
M2comp keeps generated modules short
(M2compS/M2compP/M2comp, no Coco/R truncation surprises).FieldSeq = Field { ";" Field } (first field mandatory,
may be empty) — the fully-optional form made END ambiguous.ARRAY[0..63] formals (open
ARRAY OF CHAR in GetIdent); no whole-array # (name match via
Strings.Equal, hence IMPORT Strings in the .atg).SymTab (duplicate/undeclared, type checks 200/210-224,
nested-ARRAY OF ARRAY long-form flag) + MGen/MC64 backend.