• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
unroll(rule: Rule) -> Rule12 pub 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             Expr::RepOnce(expr) => Expr::Seq(expr.clone(), Box::new(Expr::Rep(expr))),
19             Expr::RepExact(expr, num) => (1..num + 1)
20                 .map(|_| *expr.clone())
21                 .rev()
22                 .fold(None, |rep, expr| match rep {
23                     None => Some(expr),
24                     Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
25                 })
26                 .unwrap(),
27             Expr::RepMin(expr, min) => (1..min + 2)
28                 .map(|i| {
29                     if i <= min {
30                         *expr.clone()
31                     } else {
32                         Expr::Rep(expr.clone())
33                     }
34                 })
35                 .rev()
36                 .fold(None, |rep, expr| match rep {
37                     None => Some(expr),
38                     Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
39                 })
40                 .unwrap(),
41             Expr::RepMax(expr, max) => (1..max + 1)
42                 .map(|_| Expr::Opt(expr.clone()))
43                 .rev()
44                 .fold(None, |rep, expr| match rep {
45                     None => Some(expr),
46                     Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
47                 })
48                 .unwrap(),
49             Expr::RepMinMax(expr, min, max) => (1..max + 1)
50                 .map(|i| {
51                     if i <= min {
52                         *expr.clone()
53                     } else {
54                         Expr::Opt(expr.clone())
55                     }
56                 })
57                 .rev()
58                 .fold(None, |rep, expr| match rep {
59                     None => Some(expr),
60                     Some(rep) => Some(Expr::Seq(Box::new(expr), Box::new(rep))),
61                 })
62                 .unwrap(),
63             expr => expr,
64         }),
65     }
66 }
67