Skip to content

Commit 1b024a4

Browse files
timfennisclaude
andauthored
🪤 fix(parser): handle EOF after augmented not without panicking (#134)
## Summary The proptest panic fuzzer (added in #133) found that token streams like `1 not` panic the parser. In `consume_binary_expression_left_associative`, when a `not` token was consumed expecting an augmented operator (e.g. `not in`, `not ==`) and the following token was missing, the error-construction path called `require_current_token().expect("there has to be a token")` — which panics on end-of-input. ## Changes - `ndc_parser/src/parser.rs`: replace the panicking `require_current_token().expect(...)` calls with a guarded match: emit `Error::text("unexpected token …")` when a current token exists, otherwise `Error::end_of_input` using the `not` token's span. - `tests/proptest/tests/panic.regressions`: persisted seed that proptest shrunk to `[2] 1 not`, so this case is locked in as a regression. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
1 parent ee5ad8f commit 1b024a4

2 files changed

Lines changed: 13 additions & 13 deletions

File tree

‎ndc_parser/src/parser.rs‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,18 @@ impl Parser {
167167

168168
while let Some(token_location) = self.consume_token_if(&extended_valid_tokens) {
169169
let (invert, operator_token_loc) = if token_location.token == Token::LogicNot {
170-
let augmented = self.consume_token_if(valid_tokens).ok_or_else(|| {
171-
Error::text(
172-
format!(
173-
"unexpected token {}",
174-
self.require_current_token()
175-
.expect("there has to be a token")
176-
.token
177-
),
178-
self.require_current_token()
179-
.expect("must have current token")
180-
.span,
181-
)
182-
})?;
170+
let augmented = match self.consume_token_if(valid_tokens) {
171+
Some(t) => t,
172+
None => {
173+
return Err(match self.peek_current_token_location() {
174+
Some(current) => Error::text(
175+
format!("unexpected token {}", current.token),
176+
current.span,
177+
),
178+
None => Error::end_of_input(token_location.span),
179+
});
180+
}
181+
};
183182
(Some(token_location), augmented)
184183
} else {
185184
(None, token_location)

‎tests/proptest/tests/panic.regressions‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
#
55
# It is recommended to check this file in to source control so that
66
# everyone who runs the test benefits from these saved cases.
7+
cc 50438352354e375bdee77e3a649ee19200ed77839b009f4ab76f4a782807be98 # shrinks to program = [2] a not

0 commit comments

Comments
 (0)