mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 18:27:38 +00:00
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 std::{error, fmt};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use pest::iterators::{Pair, Pairs};
|
use pest::iterators::{Pair, Pairs};
|
||||||
|
use pest::pratt_parser::{Assoc, Op, PrattParser};
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
use pest_derive::Parser;
|
use pest_derive::Parser;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -490,27 +492,23 @@ fn parse_expression_rule(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_infix_expression_rule(
|
fn parse_infix_expression_rule(
|
||||||
mut pairs: Pairs<Rule>,
|
pairs: Pairs<Rule>,
|
||||||
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
||||||
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
|
||||||
let mut expression1 =
|
static PRATT: Lazy<PrattParser<Rule>> = Lazy::new(|| {
|
||||||
parse_range_expression_rule(pairs.next().unwrap().into_inner(), workspace_ctx)?;
|
PrattParser::new().op(Op::infix(Rule::union_op, Assoc::Left)
|
||||||
while let Some(operator) = pairs.next() {
|
| Op::infix(Rule::intersection_op, Assoc::Left)
|
||||||
let expression2 =
|
| Op::infix(Rule::difference_op, Assoc::Left))
|
||||||
parse_range_expression_rule(pairs.next().unwrap().into_inner(), workspace_ctx)?;
|
});
|
||||||
expression1 = match operator.as_rule() {
|
PRATT
|
||||||
Rule::union_op => expression1.union(&expression2),
|
.map_primary(|primary| parse_range_expression_rule(primary.into_inner(), workspace_ctx))
|
||||||
Rule::intersection_op => expression1.intersection(&expression2),
|
.map_infix(|lhs, op, rhs| match op.as_rule() {
|
||||||
Rule::difference_op => expression1.minus(&expression2),
|
Rule::union_op => Ok(lhs?.union(&rhs?)),
|
||||||
_ => {
|
Rule::intersection_op => Ok(lhs?.intersection(&rhs?)),
|
||||||
panic!(
|
Rule::difference_op => Ok(lhs?.minus(&rhs?)),
|
||||||
"unxpected revset infix operator rule {:?}",
|
r => panic!("unexpected infix operator rule {r:?}"),
|
||||||
operator.as_rule()
|
})
|
||||||
);
|
.parse(pairs)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(expression1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_range_expression_rule(
|
fn parse_range_expression_rule(
|
||||||
|
|
Loading…
Reference in a new issue