pest_meta/optimizer/
unroller.rs
1use crate::ast::*;
11
12pub fn unroll(rule: Rule) -> Rule {
13 let Rule { name, ty, expr } = rule;
14 Rule {
15 name,
16 ty,
17 expr: expr.map_bottom_up(|expr| match expr {
18 #[cfg(not(feature = "grammar-extras"))]
19 Expr::RepOnce(expr) => Expr::Seq(expr.clone(), Box::new(Expr::Rep(expr))),
20 Expr::RepExact(expr, num) => (1..num + 1)
21 .map(|_| *expr.clone())
22 .rev()
23 .fold(None, |rep, expr| match rep {
24 None => Some(expr),
25 Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
26 })
27 .unwrap(),
28 Expr::RepMin(expr, min) => (1..min + 2)
29 .map(|i| {
30 if i <= min {
31 *expr.clone()
32 } else {
33 Expr::Rep(expr.clone())
34 }
35 })
36 .rev()
37 .fold(None, |rep, expr| match rep {
38 None => Some(expr),
39 Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
40 })
41 .unwrap(),
42 Expr::RepMax(expr, max) => (1..max + 1)
43 .map(|_| Expr::Opt(expr.clone()))
44 .rev()
45 .fold(None, |rep, expr| match rep {
46 None => Some(expr),
47 Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
48 })
49 .unwrap(),
50 Expr::RepMinMax(expr, min, max) => (1..max + 1)
51 .map(|i| {
52 if i <= min {
53 *expr.clone()
54 } else {
55 Expr::Opt(expr.clone())
56 }
57 })
58 .rev()
59 .fold(None, |rep, expr| match rep {
60 None => Some(expr),
61 Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
62 })
63 .unwrap(),
64 expr => expr,
65 }),
66 }
67}