@@ -4034,6 +4034,26 @@ impl<'a> Parser<'a> {
4034
4034
})
4035
4035
}
4036
4036
4037
+ /// Return nth previous token, possibly whitespace
4038
+ /// (or [`Token::EOF`] when before the beginning of the stream).
4039
+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
4040
+ // 0 = next token, -1 = current token, -2 = previous token
4041
+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
4042
+ if peek_index == 0 {
4043
+ return TokenWithSpan {
4044
+ token: Token::EOF,
4045
+ span: Span::empty(),
4046
+ };
4047
+ }
4048
+ self.tokens
4049
+ .get(peek_index)
4050
+ .cloned()
4051
+ .unwrap_or(TokenWithSpan {
4052
+ token: Token::EOF,
4053
+ span: Span::empty(),
4054
+ })
4055
+ }
4056
+
4037
4057
/// Return true if the next tokens exactly `expected`
4038
4058
///
4039
4059
/// Does not advance the current token.
@@ -4150,16 +4170,15 @@ impl<'a> Parser<'a> {
4150
4170
)
4151
4171
}
4152
4172
4153
- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4154
- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4155
- let mut look_back_count = 2;
4173
+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4174
+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4175
+ &mut self,
4176
+ ) -> Result<(), ParserError> {
4177
+ let mut look_back_count = 1;
4156
4178
loop {
4157
- let prev_index = self.index.saturating_sub(look_back_count);
4158
- if prev_index == 0 {
4159
- break;
4160
- }
4161
- let prev_token = self.token_at(prev_index);
4179
+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
4162
4180
match prev_token.token {
4181
+ Token::EOF => break,
4163
4182
Token::Whitespace(ref w) => match w {
4164
4183
Whitespace::Newline => break,
4165
4184
// special consideration required for single line comments since that string includes the newline
@@ -4171,18 +4190,13 @@ impl<'a> Parser<'a> {
4171
4190
}
4172
4191
_ => look_back_count += 1,
4173
4192
},
4174
- _ => {
4175
- let current_token = self.get_current_token();
4176
- if prev_token == current_token {
4177
- // if we are at the start of the statement, we can skip this check
4178
- break;
4179
- }
4180
-
4181
- self.expected(
4182
- &format!("newline before current token ({})", current_token),
4183
- prev_token.clone(),
4184
- )?
4185
- }
4193
+ _ => self.expected(
4194
+ &format!(
4195
+ "newline before current token ({})",
4196
+ self.get_current_token()
4197
+ ),
4198
+ prev_token.clone(),
4199
+ )?,
4186
4200
};
4187
4201
}
4188
4202
Ok(())
@@ -16704,6 +16718,31 @@ mod tests {
16704
16718
})
16705
16719
}
16706
16720
16721
+ #[test]
16722
+ fn test_peek_prev_nth_token_no_skip() {
16723
+ all_dialects().run_parser_method(
16724
+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
16725
+ |parser| {
16726
+ parser.index = 1;
16727
+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
16728
+ assert_eq!(parser.index, 1);
16729
+ parser.index = 7;
16730
+ assert_eq!(
16731
+ parser.token_at(parser.index - 1).token,
16732
+ Token::Word(Word {
16733
+ value: "RAISERROR".to_string(),
16734
+ quote_style: None,
16735
+ keyword: Keyword::RAISERROR,
16736
+ })
16737
+ );
16738
+ assert_eq!(
16739
+ parser.peek_prev_nth_token_no_skip(2),
16740
+ Token::Whitespace(Whitespace::Newline)
16741
+ );
16742
+ },
16743
+ );
16744
+ }
16745
+
16707
16746
#[cfg(test)]
16708
16747
mod test_parse_data_type {
16709
16748
use crate::ast::{
0 commit comments