diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/pest_meta/src/optimizer/lister.rs | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/vendor/pest_meta/src/optimizer/lister.rs b/vendor/pest_meta/src/optimizer/lister.rs new file mode 100644 index 000000000..e19885032 --- /dev/null +++ b/vendor/pest_meta/src/optimizer/lister.rs @@ -0,0 +1,42 @@ +// 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 crate::ast::*; + +pub fn list(rule: Rule) -> Rule { + let Rule { name, ty, expr } = rule; + Rule { + name, + ty, + expr: expr.map_bottom_up(|expr| { + // TODO: Use box syntax when it gets stabilized. + match expr { + Expr::Seq(l, r) => match *l { + Expr::Rep(l) => { + let l = *l; + match l { + Expr::Seq(l1, l2) => { + // Converts `(rule ~ rest)* ~ rule` to `rule ~ (rest ~ rule)*`, + // avoiding matching the last `rule` twice. + if l1 == r { + Expr::Seq(l1, Box::new(Expr::Rep(Box::new(Expr::Seq(l2, r))))) + } else { + Expr::Seq(Box::new(Expr::Rep(Box::new(Expr::Seq(l1, l2)))), r) + } + } + expr => Expr::Seq(Box::new(Expr::Rep(Box::new(expr))), r), + } + } + expr => Expr::Seq(Box::new(expr), r), + }, + expr => expr, + } + }), + } +} |