xpath/
ast.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use malloc_size_of_derive::MallocSizeOf;
6use markup5ever::QualName;
7
8#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
9pub enum Expression {
10    Binary(Box<Expression>, BinaryOperator, Box<Expression>),
11    Negate(Box<Expression>),
12    Path(PathExpression),
13    /// <https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Location-Steps>
14    LocationStep(LocationStepExpression),
15    Filter(FilterExpression),
16    Literal(Literal),
17    Variable(QName),
18    ContextItem,
19    /// We only support the built-in core functions.
20    Function(CoreFunction),
21}
22
23#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
24pub enum BinaryOperator {
25    Or,
26    And,
27    Union,
28    /// `=`
29    Equal,
30    /// `!=`
31    NotEqual,
32    /// `<`
33    LessThan,
34    /// `>`
35    GreaterThan,
36    /// `<=`
37    LessThanOrEqual,
38    /// `>=`
39    GreaterThanOrEqual,
40    /// `+`
41    Add,
42    /// `-`
43    Subtract,
44    /// `*`
45    Multiply,
46    /// `div`
47    Divide,
48    /// `mod`
49    Modulo,
50}
51
52#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
53pub struct PathExpression {
54    /// Whether this is an absolute (as opposed to a relative) path expression.
55    ///
56    /// Absolute paths always start at the starting node, not the context node.
57    pub(crate) is_absolute: bool,
58    /// Whether this expression starts with `//`. If it does, then an implicit
59    /// `descendant-or-self::node()` step will be added.
60    pub(crate) has_implicit_descendant_or_self_step: bool,
61    pub(crate) steps: Vec<Expression>,
62}
63
64#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
65pub struct PredicateListExpression {
66    pub(crate) predicates: Vec<Expression>,
67}
68
69#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
70pub struct FilterExpression {
71    pub(crate) expression: Box<Expression>,
72    pub(crate) predicates: PredicateListExpression,
73}
74
75/// <https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Location-Steps>
76#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
77pub struct LocationStepExpression {
78    pub(crate) axis: Axis,
79    pub(crate) node_test: NodeTest,
80    pub(crate) predicate_list: PredicateListExpression,
81}
82
83#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
84pub(crate) enum Axis {
85    Child,
86    Descendant,
87    Attribute,
88    Self_,
89    DescendantOrSelf,
90    FollowingSibling,
91    Following,
92    Namespace,
93    Parent,
94    Ancestor,
95    PrecedingSibling,
96    Preceding,
97    AncestorOrSelf,
98}
99
100#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
101pub(crate) enum NodeTest {
102    Name(QualName),
103    Wildcard,
104    Kind(KindTest),
105}
106
107#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
108pub struct QName {
109    pub(crate) prefix: Option<String>,
110    pub(crate) local_part: String,
111}
112
113impl std::fmt::Display for QName {
114    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115        match &self.prefix {
116            Some(prefix) => write!(f, "{}:{}", prefix, self.local_part),
117            None => write!(f, "{}", self.local_part),
118        }
119    }
120}
121
122#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
123pub(crate) enum KindTest {
124    PI(Option<String>),
125    Comment,
126    Text,
127    Node,
128}
129
130#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
131pub enum Literal {
132    Integer(i64),
133    Decimal(f64),
134    String(String),
135}
136
137/// In the DOM we do not support custom functions, so we can enumerate the usable ones
138#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
139pub enum CoreFunction {
140    // Node Set Functions
141    /// last()
142    Last,
143    /// position()
144    Position,
145    /// count(node-set)
146    Count(Box<Expression>),
147    /// id(object)
148    Id(Box<Expression>),
149    /// local-name(node-set?)
150    LocalName(Option<Box<Expression>>),
151    /// namespace-uri(node-set?)
152    NamespaceUri(Option<Box<Expression>>),
153    /// name(node-set?)
154    Name(Option<Box<Expression>>),
155
156    // String Functions
157    /// string(object?)
158    String(Option<Box<Expression>>),
159    /// concat(string, string, ...)
160    Concat(Vec<Expression>),
161    /// starts-with(string, string)
162    StartsWith(Box<Expression>, Box<Expression>),
163    /// contains(string, string)
164    Contains(Box<Expression>, Box<Expression>),
165    /// substring-before(string, string)
166    SubstringBefore(Box<Expression>, Box<Expression>),
167    /// substring-after(string, string)
168    SubstringAfter(Box<Expression>, Box<Expression>),
169    /// substring(string, number, number?)
170    Substring(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
171    /// string-length(string?)
172    StringLength(Option<Box<Expression>>),
173    /// normalize-space(string?)
174    NormalizeSpace(Option<Box<Expression>>),
175    /// translate(string, string, string)
176    Translate(Box<Expression>, Box<Expression>, Box<Expression>),
177
178    // Number Functions
179    /// number(object?)
180    Number(Option<Box<Expression>>),
181    /// sum(node-set)
182    Sum(Box<Expression>),
183    /// floor(number)
184    Floor(Box<Expression>),
185    /// ceiling(number)
186    Ceiling(Box<Expression>),
187    /// round(number)
188    Round(Box<Expression>),
189
190    // Boolean Functions
191    /// boolean(object)
192    Boolean(Box<Expression>),
193    /// not(boolean)
194    Not(Box<Expression>),
195    /// true()
196    True,
197    /// false()
198    False,
199    /// lang(string)
200    Lang(Box<Expression>),
201}