pest_meta/optimizer/
skipper.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
10use crate::ast::*;
11
12pub fn skip(rule: Rule) -> Rule {
13    fn populate_choices(expr: Expr, mut choices: Vec<String>) -> Option<Expr> {
14        match expr {
15            Expr::Choice(lhs, rhs) => {
16                if let Expr::Str(string) = *lhs {
17                    choices.push(string);
18                    populate_choices(*rhs, choices)
19                } else {
20                    None
21                }
22            }
23            Expr::Str(string) => {
24                choices.push(string);
25                Some(Expr::Skip(choices))
26            }
27            _ => None,
28        }
29    }
30
31    let Rule { name, ty, expr } = rule;
32    Rule {
33        name,
34        ty,
35        expr: if ty == RuleType::Atomic {
36            expr.map_top_down(|expr| {
37                // TODO: Use box syntax when it gets stabilized.
38                if let Expr::Rep(expr) = expr.clone() {
39                    if let Expr::Seq(lhs, rhs) = *expr {
40                        if let (Expr::NegPred(expr), Expr::Ident(ident)) = (*lhs, *rhs) {
41                            if ident == "ANY" {
42                                if let Some(expr) = populate_choices(*expr, vec![]) {
43                                    return expr;
44                                }
45                            }
46                        }
47                    }
48                };
49
50                expr
51            })
52        } else {
53            expr
54        },
55    }
56}