@@ -4463,6 +4463,26 @@ impl<'a> Parser<'a> {
44634463 self.tokens.get(self.index + n).unwrap_or(&EOF_TOKEN)
44644464 }
44654465
4466+ /// Return nth previous token, possibly whitespace
4467+ /// (or [`Token::EOF`] when before the beginning of the stream).
4468+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
4469+ // 0 = next token, -1 = current token, -2 = previous token
4470+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
4471+ if peek_index == 0 {
4472+ return TokenWithSpan {
4473+ token: Token::EOF,
4474+ span: Span::empty(),
4475+ };
4476+ }
4477+ self.tokens
4478+ .get(peek_index)
4479+ .cloned()
4480+ .unwrap_or(TokenWithSpan {
4481+ token: Token::EOF,
4482+ span: Span::empty(),
4483+ })
4484+ }
4485+
44664486 /// Return true if the next tokens exactly `expected`
44674487 ///
44684488 /// Does not advance the current token.
@@ -4579,16 +4599,15 @@ impl<'a> Parser<'a> {
45794599 )
45804600 }
45814601
4582- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4583- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4584- let mut look_back_count = 2;
4602+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4603+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4604+ &mut self,
4605+ ) -> Result<(), ParserError> {
4606+ let mut look_back_count = 1;
45854607 loop {
4586- let prev_index = self.index.saturating_sub(look_back_count);
4587- if prev_index == 0 {
4588- break;
4589- }
4590- let prev_token = self.token_at(prev_index);
4608+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
45914609 match prev_token.token {
4610+ Token::EOF => break,
45924611 Token::Whitespace(ref w) => match w {
45934612 Whitespace::Newline => break,
45944613 // special consideration required for single line comments since that string includes the newline
@@ -4600,18 +4619,13 @@ impl<'a> Parser<'a> {
46004619 }
46014620 _ => look_back_count += 1,
46024621 },
4603- _ => {
4604- let current_token = self.get_current_token();
4605- if prev_token == current_token {
4606- // if we are at the start of the statement, we can skip this check
4607- break;
4608- }
4609-
4610- self.expected(
4611- &format!("newline before current token ({})", current_token),
4612- prev_token.clone(),
4613- )?
4614- }
4622+ _ => self.expected(
4623+ &format!(
4624+ "newline before current token ({})",
4625+ self.get_current_token()
4626+ ),
4627+ prev_token.clone(),
4628+ )?,
46154629 };
46164630 }
46174631 Ok(())
@@ -20088,6 +20102,31 @@ mod tests {
2008820102 })
2008920103 }
2009020104
20105+ #[test]
20106+ fn test_peek_prev_nth_token_no_skip() {
20107+ all_dialects().run_parser_method(
20108+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
20109+ |parser| {
20110+ parser.index = 1;
20111+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
20112+ assert_eq!(parser.index, 1);
20113+ parser.index = 7;
20114+ assert_eq!(
20115+ parser.token_at(parser.index - 1).token,
20116+ Token::Word(Word {
20117+ value: "RAISERROR".to_string(),
20118+ quote_style: None,
20119+ keyword: Keyword::RAISERROR,
20120+ })
20121+ );
20122+ assert_eq!(
20123+ parser.peek_prev_nth_token_no_skip(2),
20124+ Token::Whitespace(Whitespace::Newline)
20125+ );
20126+ },
20127+ );
20128+ }
20129+
2009120130 #[cfg(test)]
2009220131 mod test_parse_data_type {
2009320132 use crate::ast::{
0 commit comments