@@ -4059,6 +4059,26 @@ impl<'a> Parser<'a> {
4059
4059
})
4060
4060
}
4061
4061
4062
+ /// Return nth previous token, possibly whitespace
4063
+ /// (or [`Token::EOF`] when before the beginning of the stream).
4064
+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
4065
+ // 0 = next token, -1 = current token, -2 = previous token
4066
+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
4067
+ if peek_index == 0 {
4068
+ return TokenWithSpan {
4069
+ token: Token::EOF,
4070
+ span: Span::empty(),
4071
+ };
4072
+ }
4073
+ self.tokens
4074
+ .get(peek_index)
4075
+ .cloned()
4076
+ .unwrap_or(TokenWithSpan {
4077
+ token: Token::EOF,
4078
+ span: Span::empty(),
4079
+ })
4080
+ }
4081
+
4062
4082
/// Return true if the next tokens exactly `expected`
4063
4083
///
4064
4084
/// Does not advance the current token.
@@ -4175,16 +4195,15 @@ impl<'a> Parser<'a> {
4175
4195
)
4176
4196
}
4177
4197
4178
- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4179
- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4180
- let mut look_back_count = 2;
4198
+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4199
+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4200
+ &mut self,
4201
+ ) -> Result<(), ParserError> {
4202
+ let mut look_back_count = 1;
4181
4203
loop {
4182
- let prev_index = self.index.saturating_sub(look_back_count);
4183
- if prev_index == 0 {
4184
- break;
4185
- }
4186
- let prev_token = self.token_at(prev_index);
4204
+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
4187
4205
match prev_token.token {
4206
+ Token::EOF => break,
4188
4207
Token::Whitespace(ref w) => match w {
4189
4208
Whitespace::Newline => break,
4190
4209
// special consideration required for single line comments since that string includes the newline
@@ -4196,18 +4215,13 @@ impl<'a> Parser<'a> {
4196
4215
}
4197
4216
_ => look_back_count += 1,
4198
4217
},
4199
- _ => {
4200
- let current_token = self.get_current_token();
4201
- if prev_token == current_token {
4202
- // if we are at the start of the statement, we can skip this check
4203
- break;
4204
- }
4205
-
4206
- self.expected(
4207
- &format!("newline before current token ({})", current_token),
4208
- prev_token.clone(),
4209
- )?
4210
- }
4218
+ _ => self.expected(
4219
+ &format!(
4220
+ "newline before current token ({})",
4221
+ self.get_current_token()
4222
+ ),
4223
+ prev_token.clone(),
4224
+ )?,
4211
4225
};
4212
4226
}
4213
4227
Ok(())
@@ -16802,6 +16816,31 @@ mod tests {
16802
16816
})
16803
16817
}
16804
16818
16819
+ #[test]
16820
+ fn test_peek_prev_nth_token_no_skip() {
16821
+ all_dialects().run_parser_method(
16822
+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
16823
+ |parser| {
16824
+ parser.index = 1;
16825
+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
16826
+ assert_eq!(parser.index, 1);
16827
+ parser.index = 7;
16828
+ assert_eq!(
16829
+ parser.token_at(parser.index - 1).token,
16830
+ Token::Word(Word {
16831
+ value: "RAISERROR".to_string(),
16832
+ quote_style: None,
16833
+ keyword: Keyword::RAISERROR,
16834
+ })
16835
+ );
16836
+ assert_eq!(
16837
+ parser.peek_prev_nth_token_no_skip(2),
16838
+ Token::Whitespace(Whitespace::Newline)
16839
+ );
16840
+ },
16841
+ );
16842
+ }
16843
+
16805
16844
#[cfg(test)]
16806
16845
mod test_parse_data_type {
16807
16846
use crate::ast::{
0 commit comments