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