# Oberon-2 validator pilot `oberon2_oberon.atg` describes Oberon-2 (Wirth/Mössenböck). It generated cleanly with Coco/R V1.53 (`CR`) but needed three repairs before GNU Modula-2 (`gm2 -fiso`) could build it and real programs would parse — all diagnosed against `voc` as oracle: 1. Duplicate `CASE` labels in the generated `statement` procedure: ident-led `assignment` vs `ProcedureCall` merged into a single `IdentTail` dispatch (`":="` vs `"("`, plus selectors). 2. The classic optional-prefix trap in `qualident`: `[ident "."]` committed on any identifier and then demanded `.`, so every `TYPE T = INTEGER` failed (same fix as the Oberon-07 pilot: `ident { "." ident }`). 3. The reference grammar has no `FOR` statement at all — added `FOR ident := ... TO ... [BY ...] DO ... END` (verified against `voc`, which accepts `BY -1`). 4. The reference `string` token used `"` quotes; Oberon strings use `'` — fixed token and `noQuote` set. 5. The designator's type-guard alternative `"(" qualident ")"` shadowed calls with non-identifier arguments (`f(1)` failed while `f(i)` parsed as a guard); merged to `"(" [ ExpList ] ")"`. 6. Type-bound procedures gained their receiver: `PROCEDURE [(VAR) v: T] [Name*] ...` (verified against `voc`). Two benign LL(1) warning families remain (dangling-`ELSE`-style, loop-exit greediness — both resolve correctly). Oberon-2 facts confirmed by probe (validator matches `voc`): no enumerations, `WITH` only in guarded-pointer form, `CASE` with `|` separators and `ELSE`, `LOOP`/`EXIT`, `RETURN` with optional value, `&`/`~`/`OR`, `IN`/`IS`, sets with `..` ranges, `NIL`, `NEW` (no dispose), `DIV`/`MOD`, `IMPORT` lists, `FORWARD` (`PROCEDURE ^ name`) declarations. Note: the reference `Grammars/Voc/voc_oberon.atg` is byte-identical to the Oberon-2 grammar (modulo its header comment), and `Grammars/Oberon-grammar/original_oberon.atg` differs only in its tags line — this single validator covers all three. ## Build ```sh ./build.sh # -> build/O2 (build/ is git-ignored) ``` Needs `CR` (Coco/R), `gm2 -fiso`, the `parser.frm`/`scanner.frm` frames and `FileIO.def/.mod` — all resolved from the environment with sensible defaults (`CRFRAMES`, `M2LIB`, `CR`, `GM2`). ## Differential results (O2 vs `voc`) Accept battery (22 cases: all statements, `FOR`/`BY`, `CASE`/`ELSE`, `LOOP`/`EXIT`, guarded `WITH`, `NEW`/deref, `ORD`, floats, strings, `Out` calls, `RETURN`) + `tests/deep.Mod` (records, pointers, multi-dim arrays, nested routines, type-bound procedures, all statements): **0 false positives**. Broken mutants (9): **0 missed**, positions close. (`i := 1` without `;` is accepted by `voc` too — separator leniency, correctly skipped.)