mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-29 02:14:07 +00:00
Refactor advancing token to avoid duplication, avoid borrow checker issues (#1618)
Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
This commit is contained in:
parent
7dbf31b587
commit
6daa4b059c
1 changed files with 73 additions and 33 deletions
|
@ -1315,7 +1315,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let dialect = self.dialect;
|
let dialect = self.dialect;
|
||||||
|
|
||||||
let (next_token, next_token_index) = self.next_token_ref_with_index();
|
self.advance_token();
|
||||||
|
let next_token_index = self.get_current_index();
|
||||||
|
let next_token = self.get_current_token();
|
||||||
let span = next_token.span;
|
let span = next_token.span;
|
||||||
let expr = match &next_token.token {
|
let expr = match &next_token.token {
|
||||||
Token::Word(w) => {
|
Token::Word(w) => {
|
||||||
|
@ -2953,7 +2955,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let dialect = self.dialect;
|
let dialect = self.dialect;
|
||||||
|
|
||||||
let (tok, tok_index) = self.next_token_ref_with_index();
|
self.advance_token();
|
||||||
|
let tok = self.get_current_token();
|
||||||
|
let tok_index = self.get_current_index();
|
||||||
let span = tok.span;
|
let span = tok.span;
|
||||||
let regular_binary_operator = match &tok.token {
|
let regular_binary_operator = match &tok.token {
|
||||||
Token::Spaceship => Some(BinaryOperator::Spaceship),
|
Token::Spaceship => Some(BinaryOperator::Spaceship),
|
||||||
|
@ -3033,7 +3037,8 @@ impl<'a> Parser<'a> {
|
||||||
// See https://www.postgresql.org/docs/current/sql-createoperator.html
|
// See https://www.postgresql.org/docs/current/sql-createoperator.html
|
||||||
let mut idents = vec![];
|
let mut idents = vec![];
|
||||||
loop {
|
loop {
|
||||||
idents.push(self.next_token_ref().to_string());
|
self.advance_token();
|
||||||
|
idents.push(self.get_current_token().to_string());
|
||||||
if !self.consume_token(&Token::Period) {
|
if !self.consume_token(&Token::Period) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3480,6 +3485,8 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Return the first non-whitespace token that has not yet been processed
|
/// Return the first non-whitespace token that has not yet been processed
|
||||||
/// or Token::EOF
|
/// or Token::EOF
|
||||||
|
///
|
||||||
|
/// See [`Self::peek_token_ref`] to avoid the copy.
|
||||||
pub fn peek_token(&self) -> TokenWithSpan {
|
pub fn peek_token(&self) -> TokenWithSpan {
|
||||||
self.peek_nth_token(0)
|
self.peek_nth_token(0)
|
||||||
}
|
}
|
||||||
|
@ -3594,21 +3601,31 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Advances to the next non-whitespace token and returns a copy.
|
/// Advances to the next non-whitespace token and returns a copy.
|
||||||
///
|
///
|
||||||
/// See [`Self::next_token_ref`] to avoid the copy.
|
/// Please use [`Self::advance_token`] and [`Self::get_current_token`] to
|
||||||
|
/// avoid the copy.
|
||||||
pub fn next_token(&mut self) -> TokenWithSpan {
|
pub fn next_token(&mut self) -> TokenWithSpan {
|
||||||
self.next_token_ref().clone()
|
self.advance_token();
|
||||||
|
self.get_current_token().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_token_ref(&mut self) -> &TokenWithSpan {
|
/// Returns the index of the current token
|
||||||
self.next_token_ref_with_index().0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the first non-whitespace token that has not yet been processed
|
|
||||||
/// and that tokens index and advances the tokens
|
|
||||||
///
|
///
|
||||||
/// # Notes:
|
/// This can be used with APIs that expect an index, such as
|
||||||
/// OK to call repeatedly after reaching EOF.
|
/// [`Self::token_at`]
|
||||||
pub fn next_token_ref_with_index(&mut self) -> (&TokenWithSpan, usize) {
|
pub fn get_current_index(&self) -> usize {
|
||||||
|
self.index.saturating_sub(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the next unprocessed token, possibly whitespace.
|
||||||
|
pub fn next_token_no_skip(&mut self) -> Option<&TokenWithSpan> {
|
||||||
|
self.index += 1;
|
||||||
|
self.tokens.get(self.index - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Advances the current token to the next non-whitespace token
|
||||||
|
///
|
||||||
|
/// See [`Self::get_current_token`] to get the current token after advancing
|
||||||
|
pub fn advance_token(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
match self.tokens.get(self.index - 1) {
|
match self.tokens.get(self.index - 1) {
|
||||||
|
@ -3616,25 +3633,38 @@ impl<'a> Parser<'a> {
|
||||||
token: Token::Whitespace(_),
|
token: Token::Whitespace(_),
|
||||||
span: _,
|
span: _,
|
||||||
}) => continue,
|
}) => continue,
|
||||||
token => return (token.unwrap_or(&EOF_TOKEN), self.index - 1),
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the current token
|
/// Returns a reference to the current token
|
||||||
pub fn current_token(&self) -> &TokenWithSpan {
|
///
|
||||||
self.tokens.get(self.index - 1).unwrap_or(&EOF_TOKEN)
|
/// Does not advance the current token.
|
||||||
|
pub fn get_current_token(&self) -> &TokenWithSpan {
|
||||||
|
self.token_at(self.index.saturating_sub(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the first unprocessed token, possibly whitespace.
|
/// Returns a reference to the previous token
|
||||||
pub fn next_token_no_skip(&mut self) -> Option<&TokenWithSpan> {
|
///
|
||||||
self.index += 1;
|
/// Does not advance the current token.
|
||||||
self.tokens.get(self.index - 1)
|
pub fn get_previous_token(&self) -> &TokenWithSpan {
|
||||||
|
self.token_at(self.index.saturating_sub(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push back the last one non-whitespace token. Must be called after
|
/// Returns a reference to the next token
|
||||||
/// `next_token()`, otherwise might panic. OK to call after
|
///
|
||||||
/// `next_token()` indicates an EOF.
|
/// Does not advance the current token.
|
||||||
|
pub fn get_next_token(&self) -> &TokenWithSpan {
|
||||||
|
self.token_at(self.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seek back the last one non-whitespace token.
|
||||||
|
///
|
||||||
|
/// Must be called after `next_token()`, otherwise might panic. OK to call
|
||||||
|
/// after `next_token()` indicates an EOF.
|
||||||
|
///
|
||||||
|
// TODO rename to backup_token and deprecate prev_token?
|
||||||
pub fn prev_token(&mut self) {
|
pub fn prev_token(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
assert!(self.index > 0);
|
assert!(self.index > 0);
|
||||||
|
@ -3680,22 +3710,30 @@ impl<'a> Parser<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn parse_keyword(&mut self, expected: Keyword) -> bool {
|
pub fn parse_keyword(&mut self, expected: Keyword) -> bool {
|
||||||
if self.peek_keyword(expected) {
|
if self.peek_keyword(expected) {
|
||||||
self.next_token_ref();
|
self.advance_token();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the current token is the `expected` keyword, consume it and returns
|
||||||
|
///
|
||||||
|
/// See [`Self::parse_keyword_token_ref`] to avoid the copy.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn parse_keyword_token(&mut self, expected: Keyword) -> Option<TokenWithSpan> {
|
pub fn parse_keyword_token(&mut self, expected: Keyword) -> Option<TokenWithSpan> {
|
||||||
self.parse_keyword_token_ref(expected).cloned()
|
self.parse_keyword_token_ref(expected).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the current token is the `expected` keyword, consume it and returns a reference to the next token.
|
||||||
|
///
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn parse_keyword_token_ref(&mut self, expected: Keyword) -> Option<&TokenWithSpan> {
|
pub fn parse_keyword_token_ref(&mut self, expected: Keyword) -> Option<&TokenWithSpan> {
|
||||||
match &self.peek_token_ref().token {
|
match &self.peek_token_ref().token {
|
||||||
Token::Word(w) if expected == w.keyword => Some(self.next_token_ref()),
|
Token::Word(w) if expected == w.keyword => {
|
||||||
|
self.advance_token();
|
||||||
|
Some(self.get_current_token())
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3722,7 +3760,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
// consume all tokens
|
// consume all tokens
|
||||||
for _ in 0..(tokens.len() + 1) {
|
for _ in 0..(tokens.len() + 1) {
|
||||||
self.next_token_ref();
|
self.advance_token();
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -3758,7 +3796,7 @@ impl<'a> Parser<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|keyword| **keyword == w.keyword)
|
.find(|keyword| **keyword == w.keyword)
|
||||||
.map(|keyword| {
|
.map(|keyword| {
|
||||||
self.next_token_ref();
|
self.advance_token();
|
||||||
*keyword
|
*keyword
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3813,10 +3851,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the next token if it matches the expected token, otherwise return false
|
/// Consume the next token if it matches the expected token, otherwise return false
|
||||||
|
///
|
||||||
|
/// See [Self::advance_token] to consume the token unconditionally
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn consume_token(&mut self, expected: &Token) -> bool {
|
pub fn consume_token(&mut self, expected: &Token) -> bool {
|
||||||
if self.peek_token_ref() == expected {
|
if self.peek_token_ref() == expected {
|
||||||
self.next_token_ref();
|
self.advance_token();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -8338,9 +8378,9 @@ impl<'a> Parser<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<(DataType, MatchedTrailingBracket), ParserError> {
|
) -> Result<(DataType, MatchedTrailingBracket), ParserError> {
|
||||||
let dialect = self.dialect;
|
let dialect = self.dialect;
|
||||||
let (next_token, next_token_index) = self.next_token_ref_with_index();
|
self.advance_token();
|
||||||
let _ = next_token; // release ref
|
let next_token = self.get_current_token();
|
||||||
let next_token = self.current_token();
|
let next_token_index = self.get_current_index();
|
||||||
|
|
||||||
let mut trailing_bracket: MatchedTrailingBracket = false.into();
|
let mut trailing_bracket: MatchedTrailingBracket = false.into();
|
||||||
let mut data = match &next_token.token {
|
let mut data = match &next_token.token {
|
||||||
|
@ -8866,7 +8906,7 @@ impl<'a> Parser<'a> {
|
||||||
Token::EOF | Token::Eq => break,
|
Token::EOF | Token::Eq => break,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.next_token_ref();
|
self.advance_token();
|
||||||
}
|
}
|
||||||
Ok(idents)
|
Ok(idents)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue