Skip to content

Commit e9b63db

Browse files
committed
Avoid cloning tokens in parse_infix
1 parent c968018 commit e9b63db

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

src/parser/mod.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,8 +2739,11 @@ impl<'a> Parser<'a> {
27392739
return infix;
27402740
}
27412741

2742-
let mut tok = self.next_token();
2743-
let regular_binary_operator = match &mut tok.token {
2742+
let dialect = self.dialect;
2743+
2744+
let (tok, tok_index) = self.next_token_ref_with_index();
2745+
let span = tok.span;
2746+
let regular_binary_operator = match &tok.token {
27442747
Token::Spaceship => Some(BinaryOperator::Spaceship),
27452748
Token::DoubleEq => Some(BinaryOperator::Eq),
27462749
Token::Eq => Some(BinaryOperator::Eq),
@@ -2758,30 +2761,30 @@ impl<'a> Parser<'a> {
27582761
Token::Caret => {
27592762
// In PostgreSQL, ^ stands for the exponentiation operation,
27602763
// and # stands for XOR. See https://www.postgresql.org/docs/current/functions-math.html
2761-
if dialect_of!(self is PostgreSqlDialect) {
2764+
if dialect_is!(dialect is PostgreSqlDialect) {
27622765
Some(BinaryOperator::PGExp)
27632766
} else {
27642767
Some(BinaryOperator::BitwiseXor)
27652768
}
27662769
}
27672770
Token::Ampersand => Some(BinaryOperator::BitwiseAnd),
27682771
Token::Div => Some(BinaryOperator::Divide),
2769-
Token::DuckIntDiv if dialect_of!(self is DuckDbDialect | GenericDialect) => {
2772+
Token::DuckIntDiv if dialect_is!(dialect is DuckDbDialect | GenericDialect) => {
27702773
Some(BinaryOperator::DuckIntegerDivide)
27712774
}
2772-
Token::ShiftLeft if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) => {
2775+
Token::ShiftLeft if dialect_is!(dialect is PostgreSqlDialect | DuckDbDialect | GenericDialect) => {
27732776
Some(BinaryOperator::PGBitwiseShiftLeft)
27742777
}
2775-
Token::ShiftRight if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) => {
2778+
Token::ShiftRight if dialect_is!(dialect is PostgreSqlDialect | DuckDbDialect | GenericDialect) => {
27762779
Some(BinaryOperator::PGBitwiseShiftRight)
27772780
}
2778-
Token::Sharp if dialect_of!(self is PostgreSqlDialect) => {
2781+
Token::Sharp if dialect_is!(dialect is PostgreSqlDialect) => {
27792782
Some(BinaryOperator::PGBitwiseXor)
27802783
}
2781-
Token::Overlap if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
2784+
Token::Overlap if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
27822785
Some(BinaryOperator::PGOverlap)
27832786
}
2784-
Token::CaretAt if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
2787+
Token::CaretAt if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
27852788
Some(BinaryOperator::PGStartsWith)
27862789
}
27872790
Token::Tilde => Some(BinaryOperator::PGRegexMatch),
@@ -2804,21 +2807,21 @@ impl<'a> Parser<'a> {
28042807
Token::Question => Some(BinaryOperator::Question),
28052808
Token::QuestionAnd => Some(BinaryOperator::QuestionAnd),
28062809
Token::QuestionPipe => Some(BinaryOperator::QuestionPipe),
2807-
Token::CustomBinaryOperator(s) => Some(BinaryOperator::Custom(core::mem::take(s))),
2810+
Token::CustomBinaryOperator(s) => Some(BinaryOperator::Custom(s.clone())),
28082811

28092812
Token::Word(w) => match w.keyword {
28102813
Keyword::AND => Some(BinaryOperator::And),
28112814
Keyword::OR => Some(BinaryOperator::Or),
28122815
Keyword::XOR => Some(BinaryOperator::Xor),
2813-
Keyword::OPERATOR if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
2816+
Keyword::OPERATOR if dialect_is!(dialect is PostgreSqlDialect | GenericDialect) => {
28142817
self.expect_token(&Token::LParen)?;
28152818
// there are special rules for operator names in
28162819
// postgres so we can not use 'parse_object'
28172820
// or similar.
28182821
// See https://www.postgresql.org/docs/current/sql-createoperator.html
28192822
let mut idents = vec![];
28202823
loop {
2821-
idents.push(self.next_token().to_string());
2824+
idents.push(self.next_token_ref().to_string());
28222825
if !self.consume_token(&Token::Period) {
28232826
break;
28242827
}
@@ -2831,6 +2834,7 @@ impl<'a> Parser<'a> {
28312834
_ => None,
28322835
};
28332836

2837+
let tok = self.token_at(tok_index);
28342838
if let Some(op) = regular_binary_operator {
28352839
if let Some(keyword) =
28362840
self.parse_one_of_keywords(&[Keyword::ANY, Keyword::ALL, Keyword::SOME])
@@ -2861,7 +2865,7 @@ impl<'a> Parser<'a> {
28612865
format!(
28622866
"Expected one of [=, >, <, =>, =<, !=] as comparison operator, found: {op}"
28632867
),
2864-
tok.span.start
2868+
span.start
28652869
);
28662870
};
28672871

@@ -2990,19 +2994,19 @@ impl<'a> Parser<'a> {
29902994
tok.span.start
29912995
),
29922996
}
2993-
} else if Token::DoubleColon == tok {
2997+
} else if Token::DoubleColon == *tok {
29942998
Ok(Expr::Cast {
29952999
kind: CastKind::DoubleColon,
29963000
expr: Box::new(expr),
29973001
data_type: self.parse_data_type()?,
29983002
format: None,
29993003
})
3000-
} else if Token::ExclamationMark == tok && self.dialect.supports_factorial_operator() {
3004+
} else if Token::ExclamationMark == *tok && self.dialect.supports_factorial_operator() {
30013005
Ok(Expr::UnaryOp {
30023006
op: UnaryOperator::PGPostfixFactorial,
30033007
expr: Box::new(expr),
30043008
})
3005-
} else if Token::LBracket == tok {
3009+
} else if Token::LBracket == *tok {
30063010
if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) {
30073011
self.parse_subscript(expr)
30083012
} else if dialect_of!(self is SnowflakeDialect) || self.dialect.supports_partiql() {
@@ -3011,7 +3015,7 @@ impl<'a> Parser<'a> {
30113015
} else {
30123016
self.parse_map_access(expr)
30133017
}
3014-
} else if dialect_of!(self is SnowflakeDialect | GenericDialect) && Token::Colon == tok {
3018+
} else if dialect_of!(self is SnowflakeDialect | GenericDialect) && Token::Colon == *tok {
30153019
self.prev_token();
30163020
self.parse_json_access(expr)
30173021
} else {
@@ -3282,6 +3286,12 @@ impl<'a> Parser<'a> {
32823286
self.dialect.get_next_precedence_default(self)
32833287
}
32843288

3289+
/// Return the token at the given location, or EOF if the index is beyond
3290+
/// the length of the current set of tokens.
3291+
pub fn token_at(&self, index: usize) -> &TokenWithSpan {
3292+
self.tokens.get(index).unwrap_or(&EOF_TOKEN)
3293+
}
3294+
32853295
/// Return the first non-whitespace token that has not yet been processed
32863296
/// or Token::EOF
32873297
pub fn peek_token(&self) -> TokenWithSpan {
@@ -3398,18 +3408,22 @@ impl<'a> Parser<'a> {
33983408
self.next_token_ref().clone()
33993409
}
34003410

3411+
pub fn next_token_ref(&mut self) -> &TokenWithSpan {
3412+
self.next_token_ref_with_index().0
3413+
}
3414+
34013415
/// Return the first non-whitespace token that has not yet been processed
34023416
/// (or None if reached end-of-file) and mark it as processed. OK to call
34033417
/// repeatedly after reaching EOF.
3404-
pub fn next_token_ref(&mut self) -> &TokenWithSpan {
3418+
pub fn next_token_ref_with_index(&mut self) -> (&TokenWithSpan, usize) {
34053419
loop {
34063420
self.index += 1;
34073421
match self.tokens.get(self.index - 1) {
34083422
Some(TokenWithSpan {
34093423
token: Token::Whitespace(_),
34103424
span: _,
34113425
}) => continue,
3412-
token => return token.unwrap_or(&EOF_TOKEN),
3426+
token => return (token.unwrap_or(&EOF_TOKEN), self.index),
34133427
}
34143428
}
34153429
}

0 commit comments

Comments
 (0)