@@ -4122,6 +4122,26 @@ impl<'a> Parser<'a> {
41224122 })
41234123 }
41244124
4125+ /// Return nth previous token, possibly whitespace
4126+ /// (or [`Token::EOF`] when before the beginning of the stream).
4127+ pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
4128+ // 0 = next token, -1 = current token, -2 = previous token
4129+ let peek_index = self.index.saturating_sub(1).saturating_sub(n);
4130+ if peek_index == 0 {
4131+ return TokenWithSpan {
4132+ token: Token::EOF,
4133+ span: Span::empty(),
4134+ };
4135+ }
4136+ self.tokens
4137+ .get(peek_index)
4138+ .cloned()
4139+ .unwrap_or(TokenWithSpan {
4140+ token: Token::EOF,
4141+ span: Span::empty(),
4142+ })
4143+ }
4144+
41254145 /// Return true if the next tokens exactly `expected`
41264146 ///
41274147 /// Does not advance the current token.
@@ -4238,16 +4258,15 @@ impl<'a> Parser<'a> {
42384258 )
42394259 }
42404260
4241- /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4242- pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4243- let mut look_back_count = 2;
4261+ /// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4262+ pub(crate) fn expect_previously_only_whitespace_until_newline(
4263+ &mut self,
4264+ ) -> Result<(), ParserError> {
4265+ let mut look_back_count = 1;
42444266 loop {
4245- let prev_index = self.index.saturating_sub(look_back_count);
4246- if prev_index == 0 {
4247- break;
4248- }
4249- let prev_token = self.token_at(prev_index);
4267+ let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
42504268 match prev_token.token {
4269+ Token::EOF => break,
42514270 Token::Whitespace(ref w) => match w {
42524271 Whitespace::Newline => break,
42534272 // special consideration required for single line comments since that string includes the newline
@@ -4259,18 +4278,13 @@ impl<'a> Parser<'a> {
42594278 }
42604279 _ => look_back_count += 1,
42614280 },
4262- _ => {
4263- let current_token = self.get_current_token();
4264- if prev_token == current_token {
4265- // if we are at the start of the statement, we can skip this check
4266- break;
4267- }
4268-
4269- self.expected(
4270- &format!("newline before current token ({})", current_token),
4271- prev_token.clone(),
4272- )?
4273- }
4281+ _ => self.expected(
4282+ &format!(
4283+ "newline before current token ({})",
4284+ self.get_current_token()
4285+ ),
4286+ prev_token.clone(),
4287+ )?,
42744288 };
42754289 }
42764290 Ok(())
@@ -17739,6 +17753,31 @@ mod tests {
1773917753 })
1774017754 }
1774117755
17756+ #[test]
17757+ fn test_peek_prev_nth_token_no_skip() {
17758+ all_dialects().run_parser_method(
17759+ "SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
17760+ |parser| {
17761+ parser.index = 1;
17762+ assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
17763+ assert_eq!(parser.index, 1);
17764+ parser.index = 7;
17765+ assert_eq!(
17766+ parser.token_at(parser.index - 1).token,
17767+ Token::Word(Word {
17768+ value: "RAISERROR".to_string(),
17769+ quote_style: None,
17770+ keyword: Keyword::RAISERROR,
17771+ })
17772+ );
17773+ assert_eq!(
17774+ parser.peek_prev_nth_token_no_skip(2),
17775+ Token::Whitespace(Whitespace::Newline)
17776+ );
17777+ },
17778+ );
17779+ }
17780+
1774217781 #[cfg(test)]
1774317782 mod test_parse_data_type {
1774417783 use crate::ast::{
0 commit comments