xrust/parser/xpath/
logic.rs

1//! Logic expressions in XPath.
2
3use crate::item::Node;
4use crate::parser::combinators::list::separated_list1;
5use crate::parser::combinators::map::map;
6use crate::parser::combinators::tag::tag;
7use crate::parser::combinators::tuple::tuple3;
8use crate::parser::combinators::whitespace::xpwhitespace;
9use crate::parser::xpath::compare::comparison_expr;
10use crate::parser::{ParseError, ParseInput};
11use crate::transform::Transform;
12
13// OrExpr ::= AndExpr ('or' AndExpr)*
14pub(crate) fn or_expr<'a, N: Node + 'a>(
15) -> Box<dyn Fn(ParseInput<N>) -> Result<(ParseInput<N>, Transform<N>), ParseError> + 'a> {
16    Box::new(map(
17        separated_list1(
18            map(tuple3(xpwhitespace(), tag("or"), xpwhitespace()), |_| ()),
19            and_expr::<N>(),
20        ),
21        |mut v| {
22            if v.len() == 1 {
23                v.pop().unwrap()
24            } else {
25                Transform::Or(v)
26            }
27        },
28    ))
29}
30
31// AndExpr ::= ComparisonExpr ('and' ComparisonExpr)*
32fn and_expr<'a, N: Node + 'a>(
33) -> Box<dyn Fn(ParseInput<N>) -> Result<(ParseInput<N>, Transform<N>), ParseError> + 'a> {
34    Box::new(map(
35        separated_list1(
36            map(tuple3(xpwhitespace(), tag("and"), xpwhitespace()), |_| ()),
37            comparison_expr::<N>(),
38        ),
39        |mut v| {
40            if v.len() == 1 {
41                v.pop().unwrap()
42            } else {
43                Transform::And(v)
44            }
45        },
46    ))
47}