Skip to content

bug: "done" cannot be used as a case pattern (treated as reserved word) #279

@chaliy

Description

@chaliy

Description

The parser treats done as a reserved word even in case pattern position, preventing it from being used as a literal pattern in case statements. In real bash, reserved words are valid as case patterns.

Reproduction

case "$status" in
  done) echo "completed" ;;
  pending) echo "waiting" ;;
esac
# Expected: matches "done" literally
# Actual: parse error — parser sees "done" as loop terminator keyword

Root Cause

In crates/bashkit/src/parser/mod.rs, case pattern parsing at line 983-1003 only accepts Word, LiteralWord, and QuotedWord tokens:

while matches!(
    &self.current_token,
    Some(tokens::Token::Word(_))
        | Some(tokens::Token::LiteralWord(_))
        | Some(tokens::Token::QuotedWord(_))
) {

But the is_keyword check at line 1492-1493 matches Word("done"):

fn is_keyword(&self, keyword: &str) -> bool {
    matches!(&self.current_token, Some(tokens::Token::Word(w)) if w == keyword)
}

And NON_COMMAND_WORDS at line 1483-1484 includes "done":

const NON_COMMAND_WORDS: &'static [&'static str] =
    &["then", "else", "elif", "fi", "do", "done", "esac", "in"];

The issue is that while the case pattern loop does accept Word tokens, the surrounding while !self.is_keyword("esac") check at line 970 doesn't interfere — but done as a Word token may be consumed elsewhere or the tokenizer may prevent it from reaching the pattern parser.

Suggested Fix

In case pattern position, all words (including reserved words like done, do, if, etc.) should be treated as literal patterns. The pattern parser should accept any word token regardless of reserved word status.

Impact

Low-Medium — Affects scripts using status strings like "done", "in", "do" as case patterns. Found in GPT eval run.

Found In

Eval run 2026-02-25 (GPT model).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions