@@ -4059,6 +4059,26 @@ impl<'a> Parser<'a> {
40594059 })
40604060 }
40614061
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+
40624082 /// Return true if the next tokens exactly `expected`
40634083 ///
40644084 /// Does not advance the current token.
@@ -4175,16 +4195,15 @@ impl<'a> Parser<'a> {
41754195 )
41764196 }
41774197
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;
41814203 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);
41874205 match prev_token.token {
4206+ Token::EOF => break,
41884207 Token::Whitespace(ref w) => match w {
41894208 Whitespace::Newline => break,
41904209 // special consideration required for single line comments since that string includes the newline
@@ -4196,18 +4215,13 @@ impl<'a> Parser<'a> {
41964215 }
41974216 _ => look_back_count += 1,
41984217 },
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+ )?,
42114225 };
42124226 }
42134227 Ok(())
@@ -16802,6 +16816,31 @@ mod tests {
1680216816 })
1680316817 }
1680416818
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+
1680516844 #[cfg(test)]
1680616845 mod test_parse_data_type {
1680716846 use crate::ast::{
0 commit comments