You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
emit-portable: no-in suppress, +-quantifier, sep/bracket fixes — javascript.ts now EMITS
A run of constructs that together take the real javascript.ts grammar through the
whole portable emitter end-to-end:
- no-`in` (suppress) context: a `for (binding in iterable)` head parses its binding
with the `in` led disabled (examples/noinjs.ts, 9/9+4/4 ×3). Threads a
suppressed-connector set consumed per led loop.
- one-or-more `+` quantifier (`x+` = `x x*`) — the last buildIR throw; with it,
javascript.ts EMITS in all three targets.
- Two latent `sep` bugs, both exposed only by the real grammar (earlier grammars
wrapped sep in opt or never tested the shapes — the aggregate passed for the wrong
reason): gen-parser's sep is `(element (delim element)*)?`, i.e. the WHOLE list is
optional (empty `f()` valid) AND a trailing delimiter is allowed. sepBy now matches.
- A NUD bracket that fails now FALLS THROUGH to the next same-first-token alternative
instead of returning null — javascript has four `new`-led NUDs.
Result: javascript.ts emits, compiles and runs in ts/go/rust, and is byte-identical to
createParser on basic JS (var/function/arrow/ternary/member-call/for-in/while/if/class/
new/template/regex/instanceof/try/switch) — 23/24 in TS, the one miss a `new a.b()`
NewTarget member-constructor CST shape. The await/yield fork (async/await) and that
new-expression edge remain. Full suite 42/42; existing gate unaffected by the shared
sep/bracket fixes.
// Self-bench: a numeric arg N times the lex+parse loop and prints ms/iteration.
400
404
if let Some(iters) = std::env::args().nth(1).and_then(|a| a.parse::<u64>().ok()) {
401
405
// black_box on the input + result so the optimizer can't elide the lex/parse.
402
-
for _ in 0..3 { let toks = lex(std::hint::black_box(&src)); let mut p = Parser { toks, pos: 0, capped: false }; std::hint::black_box(p.parse_${ir.entry}()); }
406
+
for _ in 0..3 { let toks = lex(std::hint::black_box(&src)); let mut p = Parser { toks, pos: 0, capped: false, suppress_next: Vec::new() }; std::hint::black_box(p.parse_${ir.entry}()); }
403
407
let t = std::time::Instant::now();
404
-
for _ in 0..iters { let toks = lex(std::hint::black_box(&src)); let mut p = Parser { toks, pos: 0, capped: false }; std::hint::black_box(p.parse_${ir.entry}()); }
408
+
for _ in 0..iters { let toks = lex(std::hint::black_box(&src)); let mut p = Parser { toks, pos: 0, capped: false, suppress_next: Vec::new() }; std::hint::black_box(p.parse_${ir.entry}()); }
405
409
println!("{:.4}", t.elapsed().as_secs_f64() * 1000.0 / iters as f64);
406
410
return;
407
411
}
408
412
let toks = lex(&src);
409
413
let n = toks.len();
410
-
let mut p = Parser { toks, pos: 0, capped: false };
414
+
let mut p = Parser { toks, pos: 0, capped: false, suppress_next: Vec::new() };
411
415
match p.parse_${ir.entry}() {
412
416
Some(root) if p.pos == n => { let mut out = String::new(); write_json(&root, &mut out); print!("{}", out); }
0 commit comments