Skip to content

fix(parser): allow reserved words in argument position - #184

Merged
bartlomieju merged 2 commits into
denoland:mainfrom
mrgrain:mrgrain/fix/parser/reserved-words-in-argument-position
Jul 23, 2026
Merged

fix(parser): allow reserved words in argument position#184
bartlomieju merged 2 commits into
denoland:mainfrom
mrgrain:mrgrain/fix/parser/reserved-words-in-argument-position

Conversation

@mrgrain

@mrgrain mrgrain commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

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 meant echo for failed to parse, even though for only 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 plain WORDs, and quoting a reserved word anywhere, including command-name position, suppresses recognition entirely. This shell doesn't implement if/for/while/case compound 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 of parse_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 cmd previously 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_position test 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.

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
@CLAassistant

CLAassistant commented Jul 8, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@bartlomieju

Copy link
Copy Markdown
Member

Can you please sign the CLA?

@mrgrain

mrgrain commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@bartlomieju Done. LMK if you have any questions or feedback.

@bartlomieju bartlomieju left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@bartlomieju
bartlomieju merged commit 545f1aa into denoland:main Jul 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow reserved words in argument positions

3 participants