@@ -3949,6 +3949,26 @@ impl<'a> Parser<'a> {
3949
3949
})
3950
3950
}
3951
3951
3952
+ /// Return nth previous token, possibly whitespace
3953
+ /// (or [`Token::EOF`] when before the beginning of the stream).
3954
+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
3955
+ // 0 = next token, -1 = current token, -2 = previous token
3956
+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
3957
+ if peek_index == 0 {
3958
+ return TokenWithSpan {
3959
+ token: Token::EOF,
3960
+ span: Span::empty(),
3961
+ };
3962
+ }
3963
+ self.tokens
3964
+ .get(peek_index)
3965
+ .cloned()
3966
+ .unwrap_or(TokenWithSpan {
3967
+ token: Token::EOF,
3968
+ span: Span::empty(),
3969
+ })
3970
+ }
3971
+
3952
3972
/// Return true if the next tokens exactly `expected`
3953
3973
///
3954
3974
/// Does not advance the current token.
@@ -4065,16 +4085,15 @@ impl<'a> Parser<'a> {
4065
4085
)
4066
4086
}
4067
4087
4068
- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4069
- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4070
- let mut look_back_count = 2;
4088
+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4089
+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4090
+ &mut self,
4091
+ ) -> Result<(), ParserError> {
4092
+ let mut look_back_count = 1;
4071
4093
loop {
4072
- let prev_index = self.index.saturating_sub(look_back_count);
4073
- if prev_index == 0 {
4074
- break;
4075
- }
4076
- let prev_token = self.token_at(prev_index);
4094
+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
4077
4095
match prev_token.token {
4096
+ Token::EOF => break,
4078
4097
Token::Whitespace(ref w) => match w {
4079
4098
Whitespace::Newline => break,
4080
4099
// special consideration required for single line comments since that string includes the newline
@@ -4086,18 +4105,13 @@ impl<'a> Parser<'a> {
4086
4105
}
4087
4106
_ => look_back_count += 1,
4088
4107
},
4089
- _ => {
4090
- let current_token = self.get_current_token();
4091
- if prev_token == current_token {
4092
- // if we are at the start of the statement, we can skip this check
4093
- break;
4094
- }
4095
-
4096
- self.expected(
4097
- &format!("newline before current token ({})", current_token),
4098
- prev_token.clone(),
4099
- )?
4100
- }
4108
+ _ => self.expected(
4109
+ &format!(
4110
+ "newline before current token ({})",
4111
+ self.get_current_token()
4112
+ ),
4113
+ prev_token.clone(),
4114
+ )?,
4101
4115
};
4102
4116
}
4103
4117
Ok(())
@@ -15540,6 +15554,31 @@ mod tests {
15540
15554
})
15541
15555
}
15542
15556
15557
+ #[test]
15558
+ fn test_peek_prev_nth_token_no_skip() {
15559
+ all_dialects().run_parser_method(
15560
+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
15561
+ |parser| {
15562
+ parser.index = 1;
15563
+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
15564
+ assert_eq!(parser.index, 1);
15565
+ parser.index = 7;
15566
+ assert_eq!(
15567
+ parser.token_at(parser.index - 1).token,
15568
+ Token::Word(Word {
15569
+ value: "RAISERROR".to_string(),
15570
+ quote_style: None,
15571
+ keyword: Keyword::RAISERROR,
15572
+ })
15573
+ );
15574
+ assert_eq!(
15575
+ parser.peek_prev_nth_token_no_skip(2),
15576
+ Token::Whitespace(Whitespace::Newline)
15577
+ );
15578
+ },
15579
+ );
15580
+ }
15581
+
15543
15582
#[cfg(test)]
15544
15583
mod test_parse_data_type {
15545
15584
use crate::ast::{
0 commit comments