Go to file T
Code
.github ci: the receiver's comment names the v0.2.34 dispatch
ci ci/tiers-test.py: the wiring's own proof (triggers, concurrency, verdict, notify's issue)
docs highlight: retain plain prelude functions
queries highlight: retain plain prelude functions
script Revert "plant: the floor's default reads 2000 (the corpus gate must go red in CI)" — seen red in run 39686699390
src Revert "plant: the #27 fix removed, grammar.js and src/ at trunk's (the highlight test must go red in CI)" — seen red in run 39687533402
test Revert "plant: corrupt the 0.2.35 corpus witness"
.gitattributes grammar: the independent reading of spec/01-grammar.md — items, expressions, f-strings, regions, rows; newline terminators per [gram.lex.newline]; scanner owns """ and raw fences; src/ committed per ecosystem convention
.gitignore build: npm scaffold — tree-sitter-cli pinned, lockfile committed for npm ci
CHANGELOG.md changelog: tl31
LICENSE license: GPL-3.0-or-later (D41 as amended); the scaffold gate follows
README.md docs: spec-findings-tl01, the v0.2.11 re-vendor measured
grammar.js Revert "plant: the #27 fix removed, grammar.js and src/ at trunk's (the highlight test must go red in CI)" — seen red in run 39687533402
package-lock.json build: npm scaffold — tree-sitter-cli pinned, lockfile committed for npm ci
package.json build: npm scaffold — tree-sitter-cli pinned, lockfile committed for npm ci
tree-sitter.json grammar: the independent reading of spec/01-grammar.md — items, expressions, f-strings, regions, rows; newline terminators per [gram.lex.newline]; scanner owns """ and raw fences; src/ committed per ecosystem convention

tree-sitter-wolf

The tree-sitter grammar for wolf (.lu files), for editor and GitHub syntax highlighting. It was written from the specification alone: spec/01-grammar.md and its [gram.*] anchors in wolf-lang are the source of truth, and the compiler's parser was deliberately not consulted. The grammar exists for highlighting. The parsers that decide what a wolf program means are the compiler's and the interpreter's.

What's here:

  • grammar.js: items, expressions with the §3.2 precedence climb, [] generics, regions, traits and dyn, closures, match row patterns and struct patterns ([gram.pat.struct]), char literals ([gram.lex.char], D58), D63 binder comma groups, postfix ? and !T error rows, call-site f(mut x), region caps ([mem.region.cap.1]), the contextual then and the bare if ([gram.expr.if], s151), the alias bound trait Num = Add + Sub (s155), literal range patterns ([gram.pat.range], s147), and Go-style newline termination ([gram.lex.newline]). Blocks take newline termination literally, because expr_stmt ::= expr TERM is what stops D69's refused struct literal from being re-read as a bare block.
  • src/scanner.c: an external scanner for """ multiline strings (a lone " or "" is content, and the literal ends at the next """), for raw-string # fences, and for the one terminator decision that needs to read past trivia: a newline whose next token is else inserts no terminator ([gram.lex.newline], wolf-lang#276), so a line beginning else continues the statement above it.
  • Every plain string literal is an f-string ([gram.lex.str]), so {expr} inside any string is a real expression subtree, including nested strings, format specs and {n:>{w}}.
  • queries/: highlights.scm, locals.scm and injections.scm with standard capture names. C is injected into unsafe c bodies and regex into re"…" literals.
  • test/corpus/: the grammar's own reviewed test suite. script/parse-wolf-corpus.sh parses wolf-lang's full corpus in CI and requires zero ERROR nodes; the corpus's own parse-tier counter-examples are excluded by directive.

src/parser.c is committed, following ecosystem convention: Helix's hx -g build and Zed's extension builder compile it from this repo without running tree-sitter generate. CI checks that the committed parser matches grammar.js.

Where highlighting benefits from tolerance, the grammar accepts a superset of the language. Constructs the compiler rejects with a diagnostic (comparison chaining, E0003; detached moded receivers, E0210; empty statements, E0002) still parse here. The grammar accepts everything the spec accepts; if a valid construct fails to parse, that is a grammar bug or a filed spec finding.

A tree-sitter grammar cannot refuse input, so lexer-level rules are encoded only where the token boundary happens to expose them. \u{…} is the worked example. UNI_ESC bounds the escape at one to six hex digits, and because nothing else starts with ', seven digits leave an ERROR in a char literal exactly where wolfc reports E0101. Inside "…" there is no such boundary, so the refusal becomes a node: since v0.2.2 made the string escape set a production of its own (STR_ESC), everything outside that set lexes as invalid_escape, painted @error. That keeps the tree's shape (one escape token where one escape stands) where the alternatives would not. A bounded permissive token made "\u{0000041}" re-enter interpolation mode and grow a fake (interpolation (integer_literal)), and an ERROR node would discard the rest of an otherwise valid literal. docs/spec-findings-le04.md records the measurement and docs/spec-findings-le05.md the node.

The parser-level separator rule is encoded the same way, and there the boundary is visible. D67 and D69 require the comma between pattern members, struct-literal fields, closure parameters and capture-list names, so Point { x .. }, Point { x y }, fn(a b) and unsafe c [a b] each leave an ERROR node at the missing separator with the enclosing node intact.

Licensed under GPL-3.0-or-later.