pest_meta/
ast.rs

1// pest. The Elegant Parser
2// Copyright (c) 2018 Dragoș Tiselice
3//
4// Licensed under the Apache License, Version 2.0
5// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
6// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. All files in the project carrying such notice may not be copied,
8// modified, or distributed except according to those terms.
9
10//! Types for the pest's abstract syntax tree.
11
12/// A grammar rule
13#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct Rule {
15    /// The name of the rule
16    pub name: String,
17    /// The rule's type (silent, atomic, ...)
18    pub ty: RuleType,
19    /// The rule's expression
20    pub expr: Expr,
21}
22
23/// All possible rule types
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum RuleType {
26    /// The normal rule type
27    Normal,
28    /// Silent rules are just like normal rules
29    /// — when run, they function the same way —
30    /// except they do not produce pairs or tokens.
31    /// If a rule is silent, it will never appear in a parse result.
32    /// (their syntax is `_{ ... }`)
33    Silent,
34    /// atomic rule prevent implicit whitespace: inside an atomic rule,
35    /// the tilde ~ means "immediately followed by",
36    /// and repetition operators (asterisk * and plus sign +)
37    /// have no implicit separation. In addition, all other rules
38    /// called from an atomic rule are also treated as atomic.
39    /// In an atomic rule, interior matching rules are silent.
40    /// (their syntax is `@{ ... }`)
41    Atomic,
42    /// Compound atomic rules are similar to atomic rules,
43    /// but they produce inner tokens as normal.
44    /// (their syntax is `${ ... }`)
45    CompoundAtomic,
46    /// Non-atomic rules cancel the effect of atomic rules.
47    /// (their syntax is `!{ ... }`)
48    NonAtomic,
49}
50
51/// All possible rule expressions
52///
53/// # Warning: Semantic Versioning
54/// There may be non-breaking changes to the meta-grammar
55/// between minor versions. Those non-breaking changes, however,
56/// may translate into semver-breaking changes due to the additional variants
57/// propaged from the `Rule` enum. This is a known issue and will be fixed in the
58/// future (e.g. by increasing MSRV and non_exhaustive annotations).
59#[derive(Clone, Debug, Eq, PartialEq)]
60pub enum Expr {
61    /// Matches an exact string, e.g. `"a"`
62    Str(String),
63    /// Matches an exact string, case insensitively (ASCII only), e.g. `^"a"`
64    Insens(String),
65    /// Matches one character in the range, e.g. `'a'..'z'`
66    Range(String, String),
67    /// Matches the rule with the given name, e.g. `a`
68    Ident(String),
69    /// Matches a custom part of the stack, e.g. `PEEK[..]`
70    PeekSlice(i32, Option<i32>),
71    /// Positive lookahead; matches expression without making progress, e.g. `&e`
72    PosPred(Box<Expr>),
73    /// Negative lookahead; matches if expression doesn't match, without making progress, e.g. `!e`
74    NegPred(Box<Expr>),
75    /// Matches a sequence of two expressions, e.g. `e1 ~ e2`
76    Seq(Box<Expr>, Box<Expr>),
77    /// Matches either of two expressions, e.g. `e1 | e2`
78    Choice(Box<Expr>, Box<Expr>),
79    /// Optionally matches an expression, e.g. `e?`
80    Opt(Box<Expr>),
81    /// Matches an expression zero or more times, e.g. `e*`
82    Rep(Box<Expr>),
83    /// Matches an expression one or more times, e.g. `e+`
84    RepOnce(Box<Expr>),
85    /// Matches an expression an exact number of times, e.g. `e{n}`
86    RepExact(Box<Expr>, u32),
87    /// Matches an expression at least a number of times, e.g. `e{n,}`
88    RepMin(Box<Expr>, u32),
89    /// Matches an expression at most a number of times, e.g. `e{,n}`
90    RepMax(Box<Expr>, u32),
91    /// Matches an expression a number of times within a range, e.g. `e{m, n}`
92    RepMinMax(Box<Expr>, u32, u32),
93    /// Continues to match expressions until one of the strings in the `Vec` is found
94    Skip(Vec<String>),
95    /// Matches an expression and pushes it to the stack, e.g. `push(e)`
96    Push(Box<Expr>),
97}
98
99impl Expr {
100    /// Returns the iterator that steps the expression from top to bottom.
101    pub fn iter_top_down(&self) -> ExprTopDownIterator {
102        ExprTopDownIterator::new(self)
103    }
104
105    /// Applies `f` to the expression and all its children (top to bottom).
106    pub fn map_top_down<F>(self, mut f: F) -> Expr
107    where
108        F: FnMut(Expr) -> Expr,
109    {
110        fn map_internal<F>(expr: Expr, f: &mut F) -> Expr
111        where
112            F: FnMut(Expr) -> Expr,
113        {
114            let expr = f(expr);
115
116            match expr {
117                // TODO: Use box syntax when it gets stabilized.
118                Expr::PosPred(expr) => {
119                    let mapped = Box::new(map_internal(*expr, f));
120                    Expr::PosPred(mapped)
121                }
122                Expr::NegPred(expr) => {
123                    let mapped = Box::new(map_internal(*expr, f));
124                    Expr::NegPred(mapped)
125                }
126                Expr::Seq(lhs, rhs) => {
127                    let mapped_lhs = Box::new(map_internal(*lhs, f));
128                    let mapped_rhs = Box::new(map_internal(*rhs, f));
129                    Expr::Seq(mapped_lhs, mapped_rhs)
130                }
131                Expr::Choice(lhs, rhs) => {
132                    let mapped_lhs = Box::new(map_internal(*lhs, f));
133                    let mapped_rhs = Box::new(map_internal(*rhs, f));
134                    Expr::Choice(mapped_lhs, mapped_rhs)
135                }
136                Expr::Rep(expr) => {
137                    let mapped = Box::new(map_internal(*expr, f));
138                    Expr::Rep(mapped)
139                }
140                Expr::RepOnce(expr) => {
141                    let mapped = Box::new(map_internal(*expr, f));
142                    Expr::RepOnce(mapped)
143                }
144                Expr::RepExact(expr, max) => {
145                    let mapped = Box::new(map_internal(*expr, f));
146                    Expr::RepExact(mapped, max)
147                }
148                Expr::RepMin(expr, num) => {
149                    let mapped = Box::new(map_internal(*expr, f));
150                    Expr::RepMin(mapped, num)
151                }
152                Expr::RepMax(expr, num) => {
153                    let mapped = Box::new(map_internal(*expr, f));
154                    Expr::RepMax(mapped, num)
155                }
156                Expr::RepMinMax(expr, min, max) => {
157                    let mapped = Box::new(map_internal(*expr, f));
158                    Expr::RepMinMax(mapped, min, max)
159                }
160                Expr::Opt(expr) => {
161                    let mapped = Box::new(map_internal(*expr, f));
162                    Expr::Opt(mapped)
163                }
164                Expr::Push(expr) => {
165                    let mapped = Box::new(map_internal(*expr, f));
166                    Expr::Push(mapped)
167                }
168                expr => expr,
169            }
170        }
171
172        map_internal(self, &mut f)
173    }
174
175    /// Applies `f` to the expression and all its children (bottom up).
176    pub fn map_bottom_up<F>(self, mut f: F) -> Expr
177    where
178        F: FnMut(Expr) -> Expr,
179    {
180        fn map_internal<F>(expr: Expr, f: &mut F) -> Expr
181        where
182            F: FnMut(Expr) -> Expr,
183        {
184            let mapped = match expr {
185                Expr::PosPred(expr) => {
186                    // TODO: Use box syntax when it gets stabilized.
187                    let mapped = Box::new(map_internal(*expr, f));
188                    Expr::PosPred(mapped)
189                }
190                Expr::NegPred(expr) => {
191                    let mapped = Box::new(map_internal(*expr, f));
192                    Expr::NegPred(mapped)
193                }
194                Expr::Seq(lhs, rhs) => {
195                    let mapped_lhs = Box::new(map_internal(*lhs, f));
196                    let mapped_rhs = Box::new(map_internal(*rhs, f));
197                    Expr::Seq(mapped_lhs, mapped_rhs)
198                }
199                Expr::Choice(lhs, rhs) => {
200                    let mapped_lhs = Box::new(map_internal(*lhs, f));
201                    let mapped_rhs = Box::new(map_internal(*rhs, f));
202                    Expr::Choice(mapped_lhs, mapped_rhs)
203                }
204                Expr::Rep(expr) => {
205                    let mapped = Box::new(map_internal(*expr, f));
206                    Expr::Rep(mapped)
207                }
208                Expr::RepOnce(expr) => {
209                    let mapped = Box::new(map_internal(*expr, f));
210                    Expr::RepOnce(mapped)
211                }
212                Expr::RepExact(expr, num) => {
213                    let mapped = Box::new(map_internal(*expr, f));
214                    Expr::RepExact(mapped, num)
215                }
216                Expr::RepMin(expr, max) => {
217                    let mapped = Box::new(map_internal(*expr, f));
218                    Expr::RepMin(mapped, max)
219                }
220                Expr::RepMax(expr, max) => {
221                    let mapped = Box::new(map_internal(*expr, f));
222                    Expr::RepMax(mapped, max)
223                }
224                Expr::RepMinMax(expr, min, max) => {
225                    let mapped = Box::new(map_internal(*expr, f));
226                    Expr::RepMinMax(mapped, min, max)
227                }
228                Expr::Opt(expr) => {
229                    let mapped = Box::new(map_internal(*expr, f));
230                    Expr::Opt(mapped)
231                }
232                Expr::Push(expr) => {
233                    let mapped = Box::new(map_internal(*expr, f));
234                    Expr::Push(mapped)
235                }
236                expr => expr,
237            };
238
239            f(mapped)
240        }
241
242        map_internal(self, &mut f)
243    }
244}
245
246/// The top down iterator for an expression.
247pub struct ExprTopDownIterator {
248    current: Option<Expr>,
249    next: Option<Expr>,
250    right_branches: Vec<Expr>,
251}
252
253impl ExprTopDownIterator {
254    /// Constructs a top-down iterator from the expression.
255    pub fn new(expr: &Expr) -> Self {
256        let mut iter = ExprTopDownIterator {
257            current: None,
258            next: None,
259            right_branches: vec![],
260        };
261        iter.iterate_expr(expr.clone());
262        iter
263    }
264
265    fn iterate_expr(&mut self, expr: Expr) {
266        self.current = Some(expr.clone());
267        match expr {
268            Expr::Seq(lhs, rhs) => {
269                self.right_branches.push(*rhs);
270                self.next = Some(*lhs);
271            }
272            Expr::Choice(lhs, rhs) => {
273                self.right_branches.push(*rhs);
274                self.next = Some(*lhs);
275            }
276            Expr::PosPred(expr)
277            | Expr::NegPred(expr)
278            | Expr::Rep(expr)
279            | Expr::RepOnce(expr)
280            | Expr::RepExact(expr, _)
281            | Expr::RepMin(expr, _)
282            | Expr::RepMax(expr, _)
283            | Expr::RepMinMax(expr, ..)
284            | Expr::Opt(expr)
285            | Expr::Push(expr) => {
286                self.next = Some(*expr);
287            }
288            _ => {
289                self.next = None;
290            }
291        }
292    }
293}
294
295impl Iterator for ExprTopDownIterator {
296    type Item = Expr;
297
298    fn next(&mut self) -> Option<Self::Item> {
299        let result = self.current.take();
300
301        if let Some(expr) = self.next.take() {
302            self.iterate_expr(expr);
303        } else if let Some(expr) = self.right_branches.pop() {
304            self.iterate_expr(expr);
305        }
306
307        result
308    }
309}
310
311#[cfg(test)]
312mod tests {
313    use super::*;
314
315    #[test]
316    fn top_down_iterator() {
317        let expr = Expr::Choice(
318            Box::new(Expr::Str(String::from("a"))),
319            Box::new(Expr::Str(String::from("b"))),
320        );
321        let mut top_down = expr.iter_top_down();
322        assert_eq!(top_down.next(), Some(expr));
323        assert_eq!(top_down.next(), Some(Expr::Str(String::from("a"))));
324        assert_eq!(top_down.next(), Some(Expr::Str(String::from("b"))));
325        assert_eq!(top_down.next(), None);
326    }
327
328    #[test]
329    fn identity() {
330        let expr = Expr::Choice(
331            Box::new(Expr::Seq(
332                Box::new(Expr::Ident("a".to_owned())),
333                Box::new(Expr::Str("b".to_owned())),
334            )),
335            Box::new(Expr::PosPred(Box::new(Expr::NegPred(Box::new(Expr::Rep(
336                Box::new(Expr::RepOnce(Box::new(Expr::Opt(Box::new(Expr::Choice(
337                    Box::new(Expr::Insens("c".to_owned())),
338                    Box::new(Expr::Push(Box::new(Expr::Range(
339                        "'d'".to_owned(),
340                        "'e'".to_owned(),
341                    )))),
342                )))))),
343            )))))),
344        );
345
346        assert_eq!(
347            expr.clone()
348                .map_bottom_up(|expr| expr)
349                .map_top_down(|expr| expr),
350            expr
351        );
352    }
353}