Skip to content

Commit 80591f1

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 56c1a4a commit 80591f1

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

src/parser/mod.rs

+59-20
Original file line numberDiff line numberDiff line change
@@ -3954,6 +3954,26 @@ impl<'a> Parser<'a> {
39543954
})
39553955
}
39563956

3957+
/// Return nth previous token, possibly whitespace
3958+
/// (or [`Token::EOF`] when before the beginning of the stream).
3959+
pub fn peek_prev_nth_token_no_skip(&self, n: usize) -> TokenWithSpan {
3960+
// 0 = next token, -1 = current token, -2 = previous token
3961+
let peek_index = self.index.saturating_sub(1).saturating_sub(n);
3962+
if peek_index == 0 {
3963+
return TokenWithSpan {
3964+
token: Token::EOF,
3965+
span: Span::empty(),
3966+
};
3967+
}
3968+
self.tokens
3969+
.get(peek_index)
3970+
.cloned()
3971+
.unwrap_or(TokenWithSpan {
3972+
token: Token::EOF,
3973+
span: Span::empty(),
3974+
})
3975+
}
3976+
39573977
/// Return true if the next tokens exactly `expected`
39583978
///
39593979
/// Does not advance the current token.
@@ -4070,16 +4090,15 @@ impl<'a> Parser<'a> {
40704090
)
40714091
}
40724092

4073-
/// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline
4074-
pub fn expect_previously_only_whitespace_until_newline(&mut self) -> Result<(), ParserError> {
4075-
let mut look_back_count = 2;
4093+
/// Look backwards in the token stream and expect that there was only whitespace tokens until the previous newline or beginning of string
4094+
pub(crate) fn expect_previously_only_whitespace_until_newline(
4095+
&mut self,
4096+
) -> Result<(), ParserError> {
4097+
let mut look_back_count = 1;
40764098
loop {
4077-
let prev_index = self.index.saturating_sub(look_back_count);
4078-
if prev_index == 0 {
4079-
break;
4080-
}
4081-
let prev_token = self.token_at(prev_index);
4099+
let prev_token = self.peek_prev_nth_token_no_skip(look_back_count);
40824100
match prev_token.token {
4101+
Token::EOF => break,
40834102
Token::Whitespace(ref w) => match w {
40844103
Whitespace::Newline => break,
40854104
// special consideration required for single line comments since that string includes the newline
@@ -4091,18 +4110,13 @@ impl<'a> Parser<'a> {
40914110
}
40924111
_ => look_back_count += 1,
40934112
},
4094-
_ => {
4095-
let current_token = self.get_current_token();
4096-
if prev_token == current_token {
4097-
// if we are at the start of the statement, we can skip this check
4098-
break;
4099-
}
4100-
4101-
self.expected(
4102-
&format!("newline before current token ({})", current_token),
4103-
prev_token.clone(),
4104-
)?
4105-
}
4113+
_ => self.expected(
4114+
&format!(
4115+
"newline before current token ({})",
4116+
self.get_current_token()
4117+
),
4118+
prev_token.clone(),
4119+
)?,
41064120
};
41074121
}
41084122
Ok(())
@@ -15379,6 +15393,31 @@ mod tests {
1537915393
})
1538015394
}
1538115395

15396+
#[test]
15397+
fn test_peek_prev_nth_token_no_skip() {
15398+
all_dialects().run_parser_method(
15399+
"SELECT 1;\n-- a comment\nRAISERROR('test', 16, 0);",
15400+
|parser| {
15401+
parser.index = 1;
15402+
assert_eq!(parser.peek_prev_nth_token_no_skip(0), Token::EOF);
15403+
assert_eq!(parser.index, 1);
15404+
parser.index = 7;
15405+
assert_eq!(
15406+
parser.token_at(parser.index - 1).token,
15407+
Token::Word(Word {
15408+
value: "RAISERROR".to_string(),
15409+
quote_style: None,
15410+
keyword: Keyword::RAISERROR,
15411+
})
15412+
);
15413+
assert_eq!(
15414+
parser.peek_prev_nth_token_no_skip(2),
15415+
Token::Whitespace(Whitespace::Newline)
15416+
);
15417+
},
15418+
);
15419+
}
15420+
1538215421
#[cfg(test)]
1538315422
mod test_parse_data_type {
1538415423
use crate::ast::{

0 commit comments

Comments
 (0)