diff --git a/CHANGELOG.md b/CHANGELOG.md index 6abd92b3..ed76c074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - **aiken-lang**: assignment and clause guard are now always formatted on a new line - **aiken-lang**: unused let-bindings are now fully removed from generated code and discarded unused let-binding now raise a warning - **aiken-lang**: support multi-clause patterns (only as a syntactic sugar) +- **aiken-lang**: fix lexer panic when parsing too large (> u32) tuple-indexes ## [v0.0.29] - 2023-MM-DD diff --git a/crates/aiken-lang/src/parser.rs b/crates/aiken-lang/src/parser.rs index 3a107ebc..e10fb1f5 100644 --- a/crates/aiken-lang/src/parser.rs +++ b/crates/aiken-lang/src/parser.rs @@ -1110,7 +1110,11 @@ pub fn expr_parser( }) .validate(|index, span, emit| { if index < 1 { - emit(ParseError::invalid_tuple_index(span, index, None)); + emit(ParseError::invalid_tuple_index( + span, + index.to_string(), + None, + )); Chain::TupleIndex(0, span) } else { Chain::TupleIndex(index as usize - 1, span) diff --git a/crates/aiken-lang/src/parser/error.rs b/crates/aiken-lang/src/parser/error.rs index 929e692e..366a8c77 100644 --- a/crates/aiken-lang/src/parser/error.rs +++ b/crates/aiken-lang/src/parser/error.rs @@ -25,7 +25,7 @@ impl ParseError { self } - pub fn invalid_tuple_index(span: Span, index: u32, suffix: Option) -> Self { + pub fn invalid_tuple_index(span: Span, index: String, suffix: Option) -> Self { let hint = suffix.map(|suffix| format!("Did you mean '{index}{suffix}'?")); Self { kind: ErrorKind::InvalidTupleIndex { hint }, diff --git a/crates/aiken-lang/src/parser/lexer.rs b/crates/aiken-lang/src/parser/lexer.rs index 895533d8..3587c37f 100644 --- a/crates/aiken-lang/src/parser/lexer.rs +++ b/crates/aiken-lang/src/parser/lexer.rs @@ -10,22 +10,26 @@ pub fn lexer() -> impl Parser, Error = ParseError> { let int = text::int(10).map(|value| Token::Int { value }); let ordinal = text::int(10) - .from_str() - .unwrapped() - .then_with(|index: u32| { + .then_with(|index: String| { choice((just("st"), just("nd"), just("rd"), just("th"))) - .map(move |suffix| (index, suffix)) + .map(move |suffix| (index.to_string(), suffix)) }) - .validate(|(index, suffix), span, emit| { - let expected_suffix = Ordinal(index).suffix(); - if expected_suffix != suffix { - emit(ParseError::invalid_tuple_index( - span, - index, - Some(expected_suffix.to_string()), - )) + .validate(|(index, suffix), span, emit| match index.parse() { + Err { .. } => { + emit(ParseError::invalid_tuple_index(span, index, None)); + Token::Ordinal { index: 0 } + } + Ok(index) => { + let expected_suffix = Ordinal::(index).suffix(); + if expected_suffix != suffix { + emit(ParseError::invalid_tuple_index( + span, + index.to_string(), + Some(expected_suffix.to_string()), + )) + } + Token::Ordinal { index } } - Token::Ordinal { index } }); let op = choice(( diff --git a/crates/aiken-lang/src/tests/parser.rs b/crates/aiken-lang/src/tests/parser.rs index e723cca9..8e89d446 100644 --- a/crates/aiken-lang/src/tests/parser.rs +++ b/crates/aiken-lang/src/tests/parser.rs @@ -1864,6 +1864,15 @@ fn parse_tuple2() { ); } +#[test] +fn large_integer_constants() { + let code = indoc! {r#" + pub const my_big_int = 999999999999999999999999 + "#}; + + assert_definitions(code, vec![]) +} + #[test] fn plain_bytearray_literals() { let code = indoc! {r#"