# P4 Pascal validator pilot `p4_pascal.atg` describes Wirth's Pascal-P4 (1977) compiler input. It needed a full repair pass to build with Coco/R V1.53 (`CR`) and GNU Modula-2 (`gm2 -fiso`), all diagnosed against `fpc -Miso` as oracle: 1. Bare `;` is not a Coco/R literal — every statement separator is written `";"` (this alone was 5 of the original errors; the same applies inside `(...)` groups). 2. The `Statement` production was missing its terminating `.`. 3. `EmptyStatement = ""` is illegal — empty positions use the `[ X { ";" [ X ] } ]` list shape instead (progress-guaranteed, so the generated parser cannot hang on empty matches). 4. `ident` cannot be both a `TOKENS` class and a production (renamed the literal tokens to `pnumber`/`pstring`); `EOF` is reserved (dropped the junk line with it); the start production must match the `COMPILER` name. 5. Left-recursive `Primary "^"` rewritten as a postfix loop. 6. Undefined nonterminals filled in: element productions extracted from the `...List` wrappers (`ConstDecl`, `TypeDecl`, `VarDecl`), `ProcDecl` (nested procedures/functions), `Value`, `PointerType`, `noQuote1`, `ParList`→`ParamList`, `Stmts`→`Statements`, `CaseStatement`/`WhileStatement`/`...`→actual names, `Var`→`VarIdent`. 7. Name collisions in generated `CASE` statements fixed by merging: duplicate `for..to/downto` branches, duplicate `Type/StructType` entries (`ArrayType`/`SetType`/`ProcType` reachable twice), and ident-led `Assignment` vs `ProcCall` (single `IdentTail` dispatch on `:=` vs `(`). 8. Grammar gaps closed to oracle level: `TypeIdent` (named types — without it every `VAR x: MyType` failed), `Compound` program bodies, trailing-`;`-tolerant sections/fields/case-items, `{}` comments, subscripts/field selectors in statements and expressions, `and`/`or` words alongside P4 `&`, bare parameterless calls, statement labels + `goto` (+`LabelSection`), `and`-less `or`..., formal parameter groups (`name: type`, `var`-prefixed) for declarations (call sites keep expression lists), subrange array indices (`1..10`), const expressions as `Value`, `CASE` branches take a single statement (also fixes a `;`-separator competition), multi-routine `{ ProcDecl }` blocks. Two benign LL(1) warning families remain (dangling-`ELSE`, loop-exit `";"` greediness — both resolve correctly). Floats (`1.5E-3`), enums, subranges (`0..255`, `N..M`, dotted names) and `Label = pnumber | ident` (enum case labels; statement labels stay numeric-only or `i := 1` breaks on the `:=`) were added to oracle level afterwards. `if`/`while`/`for` branches take a single `Statement` (standard Pascal — plural branches greedily swallow the `;` separating `case` items, so `if..then begin..end;` inside a `case` branch broke), and `begin..end` compounds are statements in their own right. The generated parser gets a strict EOF check (`IF sym # 0 THEN SynError(0)` after the start symbol in `Parse`, patched in by `build.sh` with a loud assertion): without it, the Coco/R driver never scans past the program's final `.`, silently ignoring trailing garbage — and worse, masking any failure that leaves a `.` behind. This makes the validator marginally stricter than `fpc`, which accepts trailing junk after `END.` — degenerate input only, documented here. ## Build ```sh ./build.sh # -> build/P4 (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 (P4 vs `fpc -Miso`) Accept battery + `tests/deep.pas` (labels/goto, nested routines with `var` params, records, enums, subranges, sets, pointers, all statements, hex-free literals): **0 false positives**. Broken mutants: **0 missed**, positions close. P4-era shapes (`&`, `#`, `unit` sections, `return`) are accepted leniently although `fpc -Miso` rejects them (direction is accept-more, so these can only ever be missed rejections, never false positives).