Merge 'Return better syntax error messages' from Diego Reis

Current error messages are too "low level", e.g returning tokens in
messages. This PR improves this a bit.
Before:
```text
 turso> with t as (select * from pragma_schema_version); select c.schema_version from t as c;

  × unexpected token at SourceSpan { offset: SourceOffset(47), length: 1 }
   ╭────
 1 │ with t as (select * from pragma_schema_version); select c.schema_version from t as c;
   ·                                                ┬
   ·                                                ╰── here
   ╰────
  help: expected [TK_SELECT, TK_VALUES, TK_UPDATE, TK_DELETE, TK_INSERT, TK_REPLACE] but found TK_SEMI
```
Now:
```text
 turso> with t as (select * from pragma_schema_version); select c.schema_version from t as c;

  × unexpected token ';' at offset 47
   ╭────
 1 │ with t as (select * from pragma_schema_version);select c.schema_version from t as c;
   ·                                                ┬
   ·                                                ╰── here
   ╰────
  help: expected SELECT, VALUES, UPDATE, DELETE, INSERT, or REPLACE but found ';'
  ```
@TcMits WDYT?

Closes #3190
This commit is contained in:
Jussi Saurio
2025-10-22 10:57:54 +03:00
committed by GitHub
5 changed files with 267 additions and 56 deletions

View File

@@ -28,12 +28,17 @@ macro_rules! peek_expect {
match (TK_ID, tt.fallback_id_if_ok()) {
$(($x, TK_ID) => token,)*
_ => {
let token_text = String::from_utf8_lossy(token.value).to_string();
let offset = $parser.offset();
return Err(Error::ParseUnexpectedToken {
parsed_offset: ($parser.offset(), token_len).into(),
expected: &[
$($x,)*
],
got: tt,
token_text: token_text.clone(),
offset,
expected_display: crate::token::TokenType::format_expected_tokens(&[$($x,)*]),
})
}
}
@@ -242,10 +247,17 @@ impl<'a> Parser<'a> {
Some(token) => {
if !found_semi {
let tt = token.token_type.unwrap();
let token_text = String::from_utf8_lossy(token.value).to_string();
let offset = self.offset();
return Err(Error::ParseUnexpectedToken {
parsed_offset: (self.offset(), 1).into(),
parsed_offset: (offset, 1).into(),
expected: &[TK_SEMI],
got: tt,
token_text: token_text.clone(),
offset,
expected_display: crate::token::TokenType::format_expected_tokens(&[
TK_SEMI,
]),
});
}
@@ -1495,10 +1507,18 @@ impl<'a> Parser<'a> {
Some(self.parse_nm()?)
} else if tok.token_type == Some(TK_LP) {
if can_be_lit_str {
let token = self.peek_no_eof()?;
let token_text = String::from_utf8_lossy(token.value).to_string();
let offset = self.offset();
return Err(Error::ParseUnexpectedToken {
parsed_offset: (self.offset() - name.len(), name.len()).into(),
got: TK_STRING,
expected: &[TK_ID, TK_INDEXED, TK_JOIN_KW],
token_text: token_text.clone(),
offset,
expected_display: crate::token::TokenType::format_expected_tokens(
&[TK_ID, TK_INDEXED, TK_JOIN_KW],
),
});
} // can not be literal string in function name