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 use crate::ast::*;
11 
skip(rule: Rule) -> Rule12 pub 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                 if let Expr::Rep(expr) = expr.clone() {
38                     if let Expr::Seq(lhs, rhs) = *expr {
39                         if let (Expr::NegPred(expr), Expr::Ident(ident)) = (*lhs, *rhs) {
40                             if ident == "ANY" {
41                                 if let Some(expr) = populate_choices(*expr, vec![]) {
42                                     return expr;
43                                 }
44                             }
45                         }
46                     }
47                 };
48 
49                 expr
50             })
51         } else {
52             expr
53         },
54     }
55 }
56