Coverage Report

Created: 2026-05-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pest/meta/src/optimizer/skipper.rs
Line
Count
Source
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 std::collections::HashMap;
11
12
use crate::ast::*;
13
14
0
pub fn skip(rule: Rule, map: &HashMap<String, Expr>) -> Rule {
15
0
    fn populate_choices(
16
0
        expr: Expr,
17
0
        map: &HashMap<String, Expr>,
18
0
        mut choices: Vec<String>,
19
0
    ) -> Option<Expr> {
20
0
        match expr {
21
0
            Expr::Choice(lhs, rhs) => {
22
0
                if let Expr::Str(string) = *lhs {
23
0
                    choices.push(string);
24
0
                    populate_choices(*rhs, map, choices)
25
0
                } else if let Expr::Ident(name) = *lhs {
26
                    // Try inlining rule in choices
27
0
                    if let Some(Expr::Skip(mut inlined_choices)) = map
28
0
                        .get(&name)
29
0
                        .and_then(|expr| populate_choices(expr.clone(), map, vec![]))
30
                    {
31
0
                        choices.append(&mut inlined_choices);
32
0
                        populate_choices(*rhs, map, choices)
33
                    } else {
34
0
                        None
35
                    }
36
                } else {
37
0
                    None
38
                }
39
            }
40
0
            Expr::Str(string) => {
41
0
                choices.push(string);
42
0
                Some(Expr::Skip(choices))
43
            }
44
            // Try inlining single rule
45
0
            Expr::Ident(name) => map
46
0
                .get(&name)
47
0
                .and_then(|expr| populate_choices(expr.clone(), map, choices)),
48
0
            _ => None,
49
        }
50
0
    }
51
52
0
    let Rule { name, ty, expr } = rule;
53
    Rule {
54
0
        name,
55
0
        ty,
56
0
        expr: if ty == RuleType::Atomic {
57
0
            expr.map_top_down(|expr| {
58
0
                if let Expr::Rep(expr) = expr.clone() {
59
0
                    if let Expr::Seq(lhs, rhs) = *expr {
60
0
                        if let (Expr::NegPred(expr), Expr::Ident(ident)) = (*lhs, *rhs) {
61
0
                            if ident == "ANY" {
62
0
                                if let Some(expr) = populate_choices(*expr, map, vec![]) {
63
0
                                    return expr;
64
0
                                }
65
0
                            }
66
0
                        }
67
0
                    }
68
0
                };
69
70
0
                expr
71
0
            })
72
        } else {
73
0
            expr
74
        },
75
    }
76
0
}