@@ -4034,6 +4034,26 @@ impl<'a> Parser<'a> {
40344034 })
40354035 }
40364036
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+
40374057 /// Return true if the next tokens exactly `expected`
40384058 ///
40394059 /// Does not advance the current token.
@@ -4150,16 +4170,15 @@ impl<'a> Parser<'a> {
41504170 )
41514171 }
41524172
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;
41564178 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);
41624180 match prev_token.token {
4181+ Token::EOF => break,
41634182 Token::Whitespace(ref w) => match w {
41644183 Whitespace::Newline => break,
41654184 // special consideration required for single line comments since that string includes the newline
@@ -4171,18 +4190,13 @@ impl<'a> Parser<'a> {
41714190 }
41724191 _ => look_back_count += 1,
41734192 },
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+ )?,
41864200 };
41874201 }
41884202 Ok(())
@@ -16704,6 +16718,31 @@ mod tests {
1670416718 })
1670516719 }
1670616720
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+
1670716746 #[cfg(test)]
1670816747 mod test_parse_data_type {
1670916748 use crate::ast::{
0 commit comments