diff options
Diffstat (limited to 'vendor/pest_meta/src/optimizer/skipper.rs')
-rw-r--r-- | vendor/pest_meta/src/optimizer/skipper.rs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/vendor/pest_meta/src/optimizer/skipper.rs b/vendor/pest_meta/src/optimizer/skipper.rs new file mode 100644 index 000000000..f55edc06f --- /dev/null +++ b/vendor/pest_meta/src/optimizer/skipper.rs @@ -0,0 +1,57 @@ +// pest. The Elegant Parser +// Copyright (c) 2018 DragoČ™ Tiselice +// +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +use ast::*; + +pub fn skip(rule: Rule) -> Rule { + fn populate_choices(expr: Expr, mut choices: Vec<String>) -> Option<Expr> { + match expr { + Expr::Choice(lhs, rhs) => { + if let Expr::Str(string) = *lhs { + choices.push(string); + populate_choices(*rhs, choices) + } else { + None + } + } + Expr::Str(string) => { + choices.push(string); + Some(Expr::Skip(choices)) + } + _ => None, + } + } + + match rule { + Rule { name, ty, expr } => Rule { + name, + ty, + expr: if ty == RuleType::Atomic { + expr.map_top_down(|expr| { + // TODO: Use box syntax when it gets stabilized. + if let Expr::Rep(expr) = expr.clone() { + if let Expr::Seq(lhs, rhs) = *expr.clone() { + if let (Expr::NegPred(expr), Expr::Ident(ident)) = (*lhs, *rhs) { + if ident == "ANY" { + if let Some(expr) = populate_choices(*expr, vec![]) { + return expr; + } + } + } + } + }; + + expr + }) + } else { + expr + }, + }, + } +} |