Replace the pass-2 token scan in src/compiler/parser.s with a recursive
descent statement parser and a precedence-climbing expression parser
(spec 7 and 8). Every statement line is parsed in both passes: syntax
errors are reported in pass 1, name/member/access errors (the E03-S02
lookups, now driven by the parser) in pass 2. A syntax error unwinds to
the statement and skips its line. Expression nesting is bounded so the
hardware stack cannot overflow. For tests, pass 1 can record each
expression in postfix order (operands by column, then operators), which
shows precedence and associativity directly.
src/compiler/parser.s, src/common/parser.incsrc/common/diagcat.inc (appended entries), docs/diagnostics.mdtests/parser/, scripts/build-parser-test.ps1,
scripts/verify-parser-test.ps1docs/architecture.md, docs/language-spec.md (only if a decision is
needed), docs/decisions.mdplanning/claims/E03-S03.mdbuild/prec.n8 records each statement's expression in postfix order in x128
and all 15 match prec.expect (a - b - c -> a b - c -, a / b / c,
- - a, not d and d -> d not d and, d or d and d, mixed levels,
comparisons below arithmetic, groups). Mutations: making binary operators
right associative, or swapping the +/* levels, each fail the golden.forms.n8 (assignment to a
local, field, bare field, and element; call statements including chained
calls and calls as arguments; if/else nested; while; for with and without
step, negative step; return with and without a value; print of string,
char, boolean, and word; delete; new with an expression argument) and
all 7 accepted grammar fixtures parse with no diagnostics.multi_stmt.n8 gives E021 at the second print (2:11) and
line_cont.n8 gives E022 at the end of total = 1 + (3:14); both were
pending since E03-S01 and now pass as ordinary rejected fixtures.
syntax.n8 adds a = 1 a = 2 (E021) and print with no operand (E022).syntax.n8 reports 15 independent syntax errors on consecutive lines
(missing )/], not-a-statement, unassignable target, =/to
missing in for, stray )/*, else outside an if and twice in one,
an expression nested too deeply) and then a pass-2 unknown name; a
lexer error is not followed by a cascaded E022.scan_refs) is gone; its name and member lookups
are called by the parser, so all E03-S02 fixtures pass unchanged.ex_enter and fails below $60 (seen: $A7).scripts/verify-parser-test.ps1 (final run and two
mutations), scripts/build-diag-test.ps1 catalog check,
scripts/demo-write-check.ps1.src/compiler/parser.s, src/common/parser.inc,
src/common/diagcat.inc, docs/diagnostics.md, docs/architecture.md,
tests/parser/ (prec, forms, syntax fixtures, harness trace and SP
dump), scripts/build-parser-test.ps1, scripts/verify-parser-test.ps1,
scripts/demo-write-check.ps1, this claim.return is accepted in the program body (spec 7 does
not restrict it; E03-S04/E04 must define what it does there).
Parenthesized groups do not carry a member-chain type, so (x).f is not
access-checked. Literals accept postfix syntax (5.x) that E03-S04 must
reject as a type error. A bare call f() reports the name or E021, not a
dedicated message (D123). The trace hook writes without a bound; only the
test enables it.Powered by TurnKey Linux.