fix(lexer): bare ${X:-${Y}} — extend VarRef to the balanced closing brace#174
Merged
Conversation
…race (GH #173) Found during the #95 census: the VarRef regex \$\{[^}]+\} stops at the first }, so a nested braced reference in a bare default word lexed as VarRef("${X:-${Y}") + RBrace and died as a confusing parse error, while the quoted form worked (the in-string interpolation parser hand-rolls brace matching) and ${X:-$Y} worked (no inner braces). logos regexes can't count nesting, but a callback can extend a match: the pattern now matches only the `${` opener and lex_varref walks the remainder to the balanced `}` via lex.bump(). The parser side needed nothing — find_default_separator was already ${}-nesting-aware and default words already route through parse_interpolated_string, which is why the quoted form always worked. ${#X} still lexes as VarLength (its full regex out-matches the two-character opener in logos rule selection). Depth counting stays quote-blind, matching both the old regex and the scanner's ${...} region tracking; `${}` stays an error (the old regex required one inner character); `${X:-${Y}` unbalanced is now a proper UnterminatedVarRef instead of a generic unexpected-character. Tests: token-shape + error inline tests, kernel-routed evaluation tests (single/double nesting, set-wins-over-default), and a nested example in LANGUAGE.md's `:-` section. Full gates green (4,609 tests, clippy clean, insta clean, no-default-features). Co-Authored-By: Claude Fable 5 <[email protected]>
…o review) Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #173.
The bug
Bare
${X:-${Y}}was a parse error: theVarRefregex\$\{[^}]+\}stops at the first}, so it lexed asVarRef("${X:-${Y}")+RBrace. The quoted form always worked (the in-string interpolation parser hand-rolls brace matching), as did${X:-$Y}. Found during the #95 census; pre-existing, unchanged by #172.The fix
logos regexes can't count nesting, but a callback can extend a match: the pattern is now just
\$\{andlex_varrefwalkslex.remainder()counting brace depth, extending the token to the balanced}vialex.bump(). The parser needed zero changes —find_default_separatorwas already${}-nesting-aware and default words already route throughparse_interpolated_string, which is exactly why the quoted form worked all along.Contracts preserved / clarified:
${#X}/${#u[tags]}still lex asVarLength— its full regex out-matches the two-character opener in logos rule selection.${...}region tracking (they use the identical algorithm on identical bytes, so they can't disagree on where a region ends).${}stays an error (old regex required one inner char); unbalanced${X:-${Y}is now a properunterminated variable referenceinstead of a generic unexpected-character.${a}b}closes at the first balanced}— pinned by a test.Testing & review
cargo test --all(4,610 passed), clippy--all-targets0 warnings, insta clean, no-default-features check.:-section (verified in the REPL).${a}b}) is included. CHANGELOG bullet under Unreleased/Fixed.🤖 Generated with Claude Code