fix(parser): allow reserved words in argument position - #184
Merged
bartlomieju merged 2 commits intoJul 23, 2026
Merged
Conversation
Reserved words (if/for/while/etc.) were rejected everywhere a bare word could appear, not just as a command name. This meant `echo for` failed to parse even though `for` is only meaningful as a command name. Per POSIX (XCU 2.4 "Reserved Words", grammar rule 7a), a reserved word is only recognized as such in command-name position (cmd_name). Argument words (cmd_suffix, rule 7b) are always plain WORDs, and quoting a reserved word anywhere suppresses recognition entirely. Move the reserved-word check out of the generic word parser and into a new parse_command_name_arg, used only for the first word of a simple command. This shell doesn't implement compound commands, so a bare reserved word as a command name is still rejected with a clear error instead of silently becoming a nonexistent command name. Fixes denoland#148
Member
|
Can you please sign the CLA? |
Contributor
Author
|
@bartlomieju Done. LMK if you have any questions or feedback. |
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.
Fixes #148
Reserved words (
if,for,while,case, etc.) were rejected wherever a bare unquoted word could appear, not just as a command name. That meantecho forfailed to parse, even thoughforonly has any special meaning as the first word of a command.POSIX (XCU 2.4 "Reserved Words", and grammar rule 7a/7b) only recognizes a word as reserved when it's unquoted and sits in a "reserved word position" — most notably
cmd_name, the first word of a simple command. Argument words (cmd_suffix) are always plainWORDs, and quoting a reserved word anywhere, including command-name position, suppresses recognition entirely. This shell doesn't implementif/for/while/casecompound commands, so a bare reserved word as a command name is still rejected — but with a clear "Unsupported reserved word" error rather than silently becoming a nonexistent command name that fails at runtime.The fix moves the reserved-word check out of the generic word parser (which was applied to every word, argument or not) into a new
parse_command_name_arg, used only for the first word ofparse_command_args.Because the check previously lived in the shared word parser, this also loosens two positions beyond argument words that were incidentally caught by it: reserved words are now accepted as env var values (
FOO=if cmdpreviously failed with "Invalid environment variable value"; it now parses) and as redirect targets (echo hi > for,cat < in). Neither is a command name, so per POSIX neither should have been reserved-word-checked in the first place.Tested with a new
reserved_words_in_argument_positiontest covering: all reserved words as arguments (single and multiple), reserved words as arguments to arbitrary commands, env var values, word-boundary/substring cases, quoting (full and partial) in both command-name and argument position, rejection at every command-name position in a script (after;,&&,||,|, in subshells, across newlines), and case-sensitivity. Full existing test suite passes (cargo test,cargo fmt --check,cargo clippy --all-targets --all-features).This PR was prepared by an AI agent (Kiro) on behalf of @mrgrain. Human reviewed.