Skip to main content

rgx/explain/
visitor.rs

1use regex_syntax::ast::Ast;
2
3use super::formatter;
4use super::ExplainNode;
5
6#[derive(Default)]
7pub struct ExplainVisitor {
8    nodes: Vec<ExplainNode>,
9    depth: usize,
10}
11
12impl ExplainVisitor {
13    pub fn new() -> Self {
14        Self::default()
15    }
16
17    pub fn into_nodes(self) -> Vec<ExplainNode> {
18        self.nodes
19    }
20
21    fn push(&mut self, description: String) {
22        self.nodes.push(ExplainNode {
23            depth: self.depth,
24            description,
25        });
26    }
27
28    pub fn visit(&mut self, ast: &Ast) {
29        match ast {
30            Ast::Empty(_) => {}
31            Ast::Flags(flags) => {
32                self.push(formatter::format_flags_item(&flags.flags));
33            }
34            Ast::Literal(lit) => {
35                self.push(formatter::format_literal(lit));
36            }
37            Ast::Dot(_) => {
38                self.push("Any character (except newline by default)".to_string());
39            }
40            Ast::Assertion(assertion) => {
41                self.push(formatter::format_assertion(assertion));
42            }
43            Ast::ClassUnicode(class) => {
44                self.push(formatter::format_unicode_class(class));
45            }
46            Ast::ClassPerl(class) => {
47                self.push(formatter::format_perl_class(class));
48            }
49            Ast::ClassBracketed(class) => {
50                self.push(formatter::format_bracketed_class(class));
51            }
52            Ast::Repetition(rep) => {
53                self.push(formatter::format_repetition(rep));
54                self.depth += 1;
55                self.visit(&rep.ast);
56                self.depth -= 1;
57            }
58            Ast::Group(group) => {
59                self.push(formatter::format_group(group));
60                self.depth += 1;
61                self.visit(&group.ast);
62                self.depth -= 1;
63            }
64            Ast::Alternation(alt) => {
65                self.push("Either:".to_string());
66                self.depth += 1;
67                for (i, ast) in alt.asts.iter().enumerate() {
68                    if i > 0 {
69                        self.push("Or:".to_string());
70                    }
71                    self.visit(ast);
72                }
73                self.depth -= 1;
74            }
75            Ast::Concat(concat) => {
76                for ast in &concat.asts {
77                    self.visit(ast);
78                }
79            }
80        }
81    }
82}