MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / parse_infix

Method parse_infix

src/sql-parser/src/parser.rs:1277–1427  ·  view source on GitHub ↗

Parse an operator following an expression

(
        &mut self,
        expr: Expr<Raw>,
        precedence: Precedence,
    )

Source from the content-addressed store, hash-verified

1275
1276 /// Parse an operator following an expression
1277 fn parse_infix(
1278 &mut self,
1279 expr: Expr<Raw>,
1280 precedence: Precedence,
1281 ) -> Result<Expr<Raw>, ParserError> {
1282 let tok = self.next_token().unwrap(); // safe as EOF's precedence is the lowest
1283
1284 let regular_binary_operator = match &tok {
1285 Token::Op(s) => Some(Op::bare(s)),
1286 Token::Eq => Some(Op::bare("=")),
1287 Token::Star => Some(Op::bare("*")),
1288 Token::Keyword(OPERATOR) => {
1289 self.expect_token(&Token::LParen)?;
1290 let op = self.parse_operator()?;
1291 self.expect_token(&Token::RParen)?;
1292 Some(op)
1293 }
1294 _ => None,
1295 };
1296
1297 if let Some(op) = regular_binary_operator {
1298 if let Some(kw) = self.parse_one_of_keywords(ANY_ALL_KEYWORDS) {
1299 self.parse_any_all(expr, op, kw)
1300 } else {
1301 Ok(Expr::Op {
1302 op,
1303 expr1: Box::new(expr),
1304 expr2: Some(Box::new(self.parse_subexpr(precedence)?)),
1305 })
1306 }
1307 } else if let Token::Keyword(kw) = tok {
1308 match kw {
1309 IS => {
1310 let negated = self.parse_keyword(NOT);
1311 if let Some(construct) =
1312 self.parse_one_of_keywords(&[NULL, TRUE, FALSE, UNKNOWN, DISTINCT])
1313 {
1314 let construct = match construct {
1315 NULL => IsExprConstruct::Null,
1316 TRUE => IsExprConstruct::True,
1317 FALSE => IsExprConstruct::False,
1318 UNKNOWN => IsExprConstruct::Unknown,
1319 DISTINCT => {
1320 self.expect_keyword(FROM)?;
1321 // Parse the right-hand side at the precedence of
1322 // the `IS` operator we are in the middle of, not
1323 // at `Precedence::Zero`. Otherwise we greedily
1324 // pull a trailing `AND`/`OR` into the RHS and
1325 // parse `a IS DISTINCT FROM b AND c` as `a IS
1326 // DISTINCT FROM (b AND c)`. `IS DISTINCT FROM`
1327 // binds tighter than `AND`/`OR` (and looser than
1328 // comparison and arithmetic), matching
1329 // PostgreSQL.
1330 let expr = self.parse_subexpr(precedence)?;
1331 IsExprConstruct::DistinctFrom(Box::new(expr))
1332 }
1333 _ => unreachable!(),
1334 };

Callers 1

parse_subexpr_seededMethod · 0.80

Calls 15

FunctionClass · 0.85
unwrapMethod · 0.80
next_tokenMethod · 0.80
expect_tokenMethod · 0.80
parse_operatorMethod · 0.80
parse_one_of_keywordsMethod · 0.80
parse_any_allMethod · 0.80
parse_subexprMethod · 0.80
parse_keywordMethod · 0.80
expect_keywordMethod · 0.80
expectedMethod · 0.80
peek_posMethod · 0.80

Tested by

no test coverage detected