Skip to content

Commit 71ce50f

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 a0099b2 commit 71ce50f

1 file changed

Lines changed: 59 additions & 20 deletions

File tree

src/parser/mod.rs

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

Comments
 (0)