@@ -3949,6 +3949,26 @@ impl<'a> Parser<'a> {
39493949 })
39503950 }
39513951
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+
39523972 /// Return true if the next tokens exactly `expected`
39533973 ///
39543974 /// Does not advance the current token.
@@ -4065,16 +4085,15 @@ impl<'a> Parser<'a> {
40654085 )
40664086 }
40674087
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;
40714093 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);
40774095 match prev_token.token {
4096+ Token::EOF => break,
40784097 Token::Whitespace(ref w) => match w {
40794098 Whitespace::Newline => break,
40804099 // special consideration required for single line comments since that string includes the newline
@@ -4086,18 +4105,13 @@ impl<'a> Parser<'a> {
40864105 }
40874106 _ => look_back_count += 1,
40884107 },
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+ )?,
41014115 };
41024116 }
41034117 Ok(())
@@ -15540,6 +15554,31 @@ mod tests {
1554015554 })
1554115555 }
1554215556
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+
1554315582 #[cfg(test)]
1554415583 mod test_parse_data_type {
1554515584 use crate::ast::{
0 commit comments