Skip to content

parser: BREAK/CONTINUE tokens reserved in lexer but no production rule uses them #459

@hyperpolymath

Description

@hyperpolymath

Surfaced by

hyperpolymath/standards#284.

Behaviour

`BREAK` and `CONTINUE` are reserved tokens in `lib/parser.mly` but no production rule consumes them. Any use in source produces a syntax error.

```affine
while x < n {
if done { break } // syntax error: BREAK
...
}
```

Why this hurts

Early-exit control flow is idiomatic in TS / JS / Rust. Ports of stream-processing code (line-by-line scans, find-first-match) have to restructure into:

  • Combined-guard `while` (`while running && i < n`)
  • Sentinel-boolean (`mut done := false; while !done && i < n { ... done := true; ... }`)
  • Early `return` from a helper function

All three were used in standards#284 (`s_trim` inner loops, `strip_leading_dot_slash`). Every loop-heavy TS port hits this.

Proposed fix

Add minimal `break` / `continue` to the parser + AST + lowerer:

  1. `Ast.expr` gains `Break` / `Continue` constructors (or use the existing exception-style `Throw` infrastructure if that's the chosen lowering).
  2. `Parser.mly` adds `BREAK` and `CONTINUE` as expression productions allowed inside `while` / `for` bodies.
  3. `Typecheck` checks the construct is lexically inside a loop.
  4. Lowering emits the matching JS/Deno construct (or compiles to a flag-and-test if the backend forbids early exits).

Acceptance

  • `while \<cond\> { ...; break; ... }` parses + type-checks
  • `while \<cond\> { ...; continue; ... }` parses + type-checks
  • Loop-context check rejects top-level `break`
  • At least one example in `examples/` exercises both
  • Test fixture in `test/test_loops.ml` (or wherever loop tests live)

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions