syntax: allow bracket globs in array elements#1324
syntax: allow bracket globs in array elements#1324lawrence3699 wants to merge 1 commit intomvdan:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the Bash/Zsh lexer/parser to correctly treat [ in array literals as the start of an indexed assignment only when the matching ] is immediately followed by =, allowing bracket-glob array elements like "[0-9]" to parse successfully (fixes #1322).
Changes:
- Refines array-literal tokenization of
[to disambiguate bracket globs vs indexed assignments. - Removes the now-obsolete error expectation for
a=([i])and adds regression parsing coverage. - Adds file-based parse tests for both bare bracket-glob array elements and quoted-prefix + bracket-glob words.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| syntax/lexer.go | Adds lookahead (arrayIndexAssign) and gates [ tokenization in array elements on ]=. |
| syntax/parser_test.go | Removes an error-case that is now valid under the updated lexer behavior. |
| syntax/filetests_test.go | Adds regression tests ensuring bracket-glob array elements parse in Bash/Zsh. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func (p *Parser) arrayIndexAssign() bool { | ||
| rest := p.bs[p.bsp:] | ||
| depth := 1 |
There was a problem hiding this comment.
arrayIndexAssign only scans the currently buffered bytes (p.bs[p.bsp:]) and never calls fill/peek to ensure the matching ']' is present. If the ']' (and following '=') lands across a 1KiB buffer boundary (bufSize) or when parsing from slow/interactive readers, rest can be empty/partial and this will fall through to the conservative return true, causing '[' to be tokenized as an indexed assignment and potentially reintroducing the same parse error on otherwise-valid bracket globs. Consider extending the lookahead to read more when needed (similar to zshNumRange), e.g. loop calling fill while searching until you either find the matching ']' (and can check the next byte) or hit EOF / a reasonable limit.
Fixes #1322.
Array elements in Bash and Zsh can start with bracket globs, but the array-element lexer currently tokenizes every
[as the start of an indexed assignment.That makes inputs like:
matches=( "${BASE_DIR}/v${YEAR}-"[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9] )fail with
[x] must be followed by '='even though the shell accepts them.This change only keeps
[as indexed-assignment syntax in array literals when the matching]is immediately followed by=. Otherwise, it stays part of the array element word.I added regression coverage for both a bare bracket glob array element and the quoted-prefix form from the issue.
Tests:
go test ./syntax -run 'TestParseFiles/(bash|zsh)'go test ./syntax -run 'TestParseErr/(bash|zsh)'go test ./syntax -run 'TestParseConfirm/(bash|zsh)'go test ./...