revset: give higher precedence to intersection/difference operators

Just like hg revsets and major programming languages.
This commit is contained in:
Yuya Nishihara 2022-11-16 23:35:12 +09:00
parent a90c9960ba
commit 13bb53e839
2 changed files with 12 additions and 3 deletions

View file

@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`committer(needle)`, `merges()` revsets. Use `x & description(needle)`
instead.
* Adjusted precedence of revset union/intersection/difference operators.
`x | y & z` is now equivalent to `x | (y & z)`.
* Support for open commits has been dropped. The `ui.enable-open-commits` config
that was added in 0.5.0 is no longer respected. The `jj open/close` commands
have been deleted.

View file

@ -496,9 +496,10 @@ fn parse_infix_expression_rule(
workspace_ctx: Option<&RevsetWorkspaceContext>,
) -> Result<Rc<RevsetExpression>, RevsetParseError> {
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))
PrattParser::new()
.op(Op::infix(Rule::union_op, Assoc::Left))
.op(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))
@ -1847,6 +1848,11 @@ mod tests {
parse("foo+++"),
Ok(foo_symbol.children().children().children())
);
// Set operator associativity/precedence
assert_eq!(parse("x|y|z").unwrap(), parse("(x|y)|z").unwrap());
assert_eq!(parse("x&y|z").unwrap(), parse("(x&y)|z").unwrap());
assert_eq!(parse("x|y&z").unwrap(), parse("x|(y&z)").unwrap());
assert_eq!(parse("x|y~z").unwrap(), parse("x|(y~z)").unwrap());
// Parse repeated "ancestors"/"descendants"/"dag range"/"range" operators
assert_eq!(parse(":foo:"), Err(RevsetParseErrorKind::SyntaxError));
assert_eq!(parse("::foo"), Err(RevsetParseErrorKind::SyntaxError));