Skip to content

Commit afe36ff

Browse files
committed
Introduce peek_prev_nth_token_no_skip helper
- and use it for `expect_previously_only_whitespace_until_newline` so that can be simplified accordingly
1 parent 3ab2d47 commit afe36ff

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

src/parser/mod.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)