Files
servo/components/xpath
Simon Wülker e1c418d8b2 XPath: Flatten the AST to make it more flexible (#39800)
The current XPath AST is tightly tied to the parser grammar. To address
issues like https://github.com/servo/servo/issues/39739, we'll want to
do optimization passes on the AST in the future, which requires relaxing
it's structure first.

This PR moves the AST structure into a separate module and flattens it
into a shape where most expressions are variants of the core
`Expression` enum.

This also has the nice side effect of being a net reduction in LoC and
making the AST *significantly* easier to read.

I think the difference between the old and new structure is best
explained by example.
One of our unit tests parses `concat('hello', ' ', 'world')`, and the
current AST looks like this:

```rust
Expr::Path(PathExpr {
    is_absolute: false,
    is_descendant: false,
    steps: vec![StepExpr::Filter(FilterExpr {
        primary: PrimaryExpr::Function(CoreFunction::Concat(vec![
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(
                        "hello".to_string(),
                    )),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(" ".to_string())),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
            Expr::Path(PathExpr {
                is_absolute: false,
                is_descendant: false,
                steps: vec![StepExpr::Filter(FilterExpr {
                    primary: PrimaryExpr::Literal(Literal::String(
                        "world".to_string(),
                    )),
                    predicates: PredicateListExpr { predicates: vec![] },
                })],
            }),
        ])),
        predicates: PredicateListExpr { predicates: vec![] },
    })],
}),
```
After this change, the AST looks like this:
```rust
Expression::Function(CoreFunction::Concat(vec![
    Expression::Literal(Literal::String("hello".to_string())),
    Expression::Literal(Literal::String(" ".to_string())),
    Expression::Literal(Literal::String("world".to_string())),
])),
```

Testing:  No behaviour change intended, covered by existing tests.
Part of #34527

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
2025-10-12 08:17:40 +00:00
..