@@ -3954,6 +3954,26 @@ impl<'a> Parser<'a> {
39543954 })
39553955 }
39563956
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+
39573977 /// Return true if the next tokens exactly `expected`
39583978 ///
39593979 /// Does not advance the current token.
@@ -4070,16 +4090,15 @@ impl<'a> Parser<'a> {
40704090 )
40714091 }
40724092
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;
40764098 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);
40824100 match prev_token.token {
4101+ Token::EOF => break,
40834102 Token::Whitespace(ref w) => match w {
40844103 Whitespace::Newline => break,
40854104 // special consideration required for single line comments since that string includes the newline
@@ -4091,18 +4110,13 @@ impl<'a> Parser<'a> {
40914110 }
40924111 _ => look_back_count += 1,
40934112 },
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+ )?,
41064120 };
41074121 }
41084122 Ok(())
@@ -15379,6 +15393,31 @@ mod tests {
1537915393 })
1538015394 }
1538115395
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+
1538215421 #[cfg(test)]
1538315422 mod test_parse_data_type {
1538415423 use crate::ast::{
0 commit comments