@@ -3954,6 +3954,26 @@ impl<'a> Parser<'a> {
3954
3954
})
3955
3955
}
3956
3956
3957
+ /// Return nth previous token, possibly whitespace
3958
+ /// (or [`Token::EOF`] when before the beginning of the stream).
3959
+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
3960
+ // 0 = next token, -1 = current token, -2 = previous token
3961
+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
3962
+ if peek_index == 0 {
3963
+ return TokenWithSpan {
3964
+ token: Token::EOF,
3965
+ span: Span::empty(),
3966
+ };
3967
+ }
3968
+ self.tokens
3969
+ .get(peek_index)
3970
+ .cloned()
3971
+ .unwrap_or(TokenWithSpan {
3972
+ token: Token::EOF,
3973
+ span: Span::empty(),
3974
+ })
3975
+ }
3976
+
3957
3977
/// Return true if the next tokens exactly `expected`
3958
3978
///
3959
3979
/// Does not advance the current token.
@@ -4070,16 +4090,15 @@ impl<'a> Parser<'a> {
4070
4090
)
4071
4091
}
4072
4092
4073
- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4074
- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4075
- let mut look_back_count = 2;
4093
+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4094
+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4095
+ &mut self,
4096
+ ) -> Result<(), ParserError> {
4097
+ let mut look_back_count = 1;
4076
4098
loop {
4077
- let prev_index = self.index.saturating_sub(look_back_count);
4078
- if prev_index == 0 {
4079
- break;
4080
- }
4081
- let prev_token = self.token_at(prev_index);
4099
+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
4082
4100
match prev_token.token {
4101
+ Token::EOF => break,
4083
4102
Token::Whitespace(ref w) => match w {
4084
4103
Whitespace::Newline => break,
4085
4104
// special consideration required for single line comments since that string includes the newline
@@ -4091,18 +4110,13 @@ impl<'a> Parser<'a> {
4091
4110
}
4092
4111
_ => look_back_count += 1,
4093
4112
},
4094
- _ => {
4095
- let current_token = self.get_current_token();
4096
- if prev_token == current_token {
4097
- // if we are at the start of the statement, we can skip this check
4098
- break;
4099
- }
4100
-
4101
- self.expected(
4102
- &format!("newline before current token ({})", current_token),
4103
- prev_token.clone(),
4104
- )?
4105
- }
4113
+ _ => self.expected(
4114
+ &format!(
4115
+ "newline before current token ({})",
4116
+ self.get_current_token()
4117
+ ),
4118
+ prev_token.clone(),
4119
+ )?,
4106
4120
};
4107
4121
}
4108
4122
Ok(())
@@ -15379,6 +15393,31 @@ mod tests {
15379
15393
})
15380
15394
}
15381
15395
15396
+ #[test]
15397
+ fn test_peek_prev_nth_token_no_skip() {
15398
+ all_dialects().run_parser_method(
15399
+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
15400
+ |parser| {
15401
+ parser.index = 1;
15402
+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
15403
+ assert_eq!(parser.index, 1);
15404
+ parser.index = 7;
15405
+ assert_eq!(
15406
+ parser.token_at(parser.index - 1).token,
15407
+ Token::Word(Word {
15408
+ value: "RAISERROR".to_string(),
15409
+ quote_style: None,
15410
+ keyword: Keyword::RAISERROR,
15411
+ })
15412
+ );
15413
+ assert_eq!(
15414
+ parser.peek_prev_nth_token_no_skip(2),
15415
+ Token::Whitespace(Whitespace::Newline)
15416
+ );
15417
+ },
15418
+ );
15419
+ }
15420
+
15382
15421
#[cfg(test)]
15383
15422
mod test_parse_data_type {
15384
15423
use crate::ast::{
0 commit comments