forked from mirrors/jj
revset: leverage PrattParser to parse infix (or set) expression
Apparently, this is new feature introduced in pest 2.4.0. It allows us to easily enforce operator precedence. I think the whole expression post-parsing can be migrated to PrattParser, but let's start small. We might want to add a weird rule to the range_expression layer in future. https://github.com/pest-parser/pest/releases/tag/v2.4.0 https://docs.rs/pest/latest/pest/pratt_parser/struct.PrattParser.html#example
This commit is contained in:
parent
1717690a64
commit
a90c9960ba
1 changed files with 17 additions and 19 deletions
|
@ -23,7 +23,9 @@ use std::sync::Arc;
|
|||
use std::{error, fmt};
|
||||
|
||||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use pest::iterators::{Pair, Pairs};
|
||||
use pest::pratt_parser::{Assoc, Op, PrattParser};
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser;
|
||||
use thiserror::Error;
|
||||
|
@ -490,27 +492,23 @@ fn parse_expression_rule(
|
|||
}
|
||||
|
||||
fn parse_infix_expression_rule(
|
||||
mut pairs: Pairs<Rule>,
|
||||
pairs: Pairs<Rule>,
|
||||
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
||||
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
||||
let mut expression1 =
|
||||
parse_range_expression_rule(pairs.next().unwrap().into_inner(), workspace_ctx)?;
|
||||
while let Some(operator) = pairs.next() {
|
||||
let expression2 =
|
||||
parse_range_expression_rule(pairs.next().unwrap().into_inner(), workspace_ctx)?;
|
||||
expression1 = match operator.as_rule() {
|
||||
Rule::union_op => expression1.union(&expression2),
|
||||
Rule::intersection_op => expression1.intersection(&expression2),
|
||||
Rule::difference_op => expression1.minus(&expression2),
|
||||
_ => {
|
||||
panic!(
|
||||
"unxpected revset infix operator rule {:?}",
|
||||
operator.as_rule()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(expression1)
|
||||
static PRATT: Lazy<PrattParser<Rule>> = Lazy::new(|| {
|
||||
PrattParser::new().op(Op::infix(Rule::union_op, Assoc::Left)
|
||||
| Op::infix(Rule::intersection_op, Assoc::Left)
|
||||
| Op::infix(Rule::difference_op, Assoc::Left))
|
||||
});
|
||||
PRATT
|
||||
.map_primary(|primary| parse_range_expression_rule(primary.into_inner(), workspace_ctx))
|
||||
.map_infix(|lhs, op, rhs| match op.as_rule() {
|
||||
Rule::union_op => Ok(lhs?.union(&rhs?)),
|
||||
Rule::intersection_op => Ok(lhs?.intersection(&rhs?)),
|
||||
Rule::difference_op => Ok(lhs?.minus(&rhs?)),
|
||||
r => panic!("unexpected infix operator rule {r:?}"),
|
||||
})
|
||||
.parse(pairs)
|
||||
}
|
||||
|
||||
fn parse_range_expression_rule(
|
||||
|
|
Loading…
Reference in a new issue