pomsky 0.12.0

A new regular expression language
Documentation
use pomsky_syntax::exprs::{self, Rule};

pub(crate) enum NestingKind {
    Group,
    Alternation,
    Intersection,
    Repetition,
    Lookaround,
    StmtExpr,
    Let,
    Negation,
}

fn visit<V: RuleVisitor<E>, E>(rule: &Rule, visitor: &mut V) -> Result<(), E> {
    match rule {
        Rule::Literal(l) => visitor.visit_literal(l),
        Rule::CharClass(c) => visitor.visit_char_class(c),
        Rule::Group(g) => {
            visitor.visit_group(g)?;
            visitor.down(NestingKind::Group);
            for rule in &g.parts {
                visit(rule, visitor)?;
            }
            visitor.up(NestingKind::Group);
            Ok(())
        }
        Rule::Alternation(a) => {
            visitor.visit_alternation(a)?;
            visitor.down(NestingKind::Alternation);
            for rule in &a.rules {
                visit(rule, visitor)?;
            }
            visitor.up(NestingKind::Alternation);
            Ok(())
        }
        Rule::Intersection(i) => {
            visitor.visit_intersection(i)?;
            visitor.down(NestingKind::Intersection);
            for rule in &i.rules {
                visit(rule, visitor)?;
            }
            visitor.up(NestingKind::Intersection);
            Ok(())
        }
        Rule::Repetition(r) => {
            visitor.visit_repetition(r)?;
            visitor.down(NestingKind::Repetition);
            visit(&r.rule, visitor)?;
            visitor.up(NestingKind::Repetition);
            Ok(())
        }
        Rule::Boundary(b) => visitor.visit_boundary(b),
        Rule::Lookaround(l) => {
            visitor.visit_lookaround(l)?;
            visitor.down(NestingKind::Lookaround);
            visit(&l.rule, visitor)?;
            visitor.up(NestingKind::Lookaround);
            Ok(())
        }
        Rule::Variable(v) => visitor.visit_variable(v),
        Rule::Reference(r) => visitor.visit_reference(r),
        Rule::Range(r) => visitor.visit_range(r),
        Rule::StmtExpr(s) => {
            visitor.visit_statement(&s.stmt)?;
            if let exprs::Stmt::Let(l) = &s.stmt {
                visitor.down(NestingKind::Let);
                visit(&l.rule, visitor)?;
                visitor.up(NestingKind::Let);
            }
            visitor.down(NestingKind::StmtExpr);
            visit(&s.rule, visitor)?;
            visitor.up(NestingKind::StmtExpr);
            Ok(())
        }
        Rule::Negation(n) => {
            visitor.visit_negation(n)?;
            visitor.down(NestingKind::Negation);
            visit(&n.rule, visitor)?;
            visitor.up(NestingKind::Negation);
            Ok(())
        }
        Rule::Regex(r) => visitor.visit_regex(r),
        Rule::Recursion(r) => visitor.visit_recursion(r),
        Rule::Grapheme => visitor.visit_grapheme(),
        Rule::Codepoint => visitor.visit_codepoint(),
        Rule::Dot => visitor.visit_dot(),
    }
}

#[allow(unused_variables)]
pub(crate) trait RuleVisitor<E> {
    fn visit_rule(&mut self, rule: &exprs::Rule) -> Result<(), E>
    where
        Self: Sized,
    {
        visit(rule, self)
    }

    fn down(&mut self, kind: NestingKind) {}

    fn up(&mut self, kind: NestingKind) {}

    fn visit_literal(&mut self, literal: &exprs::Literal) -> Result<(), E> {
        Ok(())
    }

    fn visit_char_class(&mut self, char_class: &exprs::CharClass) -> Result<(), E> {
        Ok(())
    }

    fn visit_group(&mut self, group: &exprs::Group) -> Result<(), E> {
        Ok(())
    }

    fn visit_alternation(&mut self, alt: &exprs::Alternation) -> Result<(), E> {
        Ok(())
    }

    fn visit_intersection(&mut self, int: &exprs::Intersection) -> Result<(), E> {
        Ok(())
    }

    fn visit_repetition(&mut self, repetition: &exprs::Repetition) -> Result<(), E> {
        Ok(())
    }

    fn visit_boundary(&mut self, boundary: &exprs::Boundary) -> Result<(), E> {
        Ok(())
    }

    fn visit_lookaround(&mut self, lookaround: &exprs::Lookaround) -> Result<(), E> {
        Ok(())
    }

    fn visit_variable(&mut self, variable: &exprs::Variable) -> Result<(), E> {
        Ok(())
    }

    fn visit_reference(&mut self, reference: &exprs::Reference) -> Result<(), E> {
        Ok(())
    }

    fn visit_range(&mut self, range: &exprs::Range) -> Result<(), E> {
        Ok(())
    }

    fn visit_statement(&mut self, statement: &exprs::Stmt) -> Result<(), E> {
        Ok(())
    }

    fn visit_negation(&mut self, negation: &exprs::Negation) -> Result<(), E> {
        Ok(())
    }

    fn visit_regex(&mut self, regex: &exprs::Regex) -> Result<(), E> {
        Ok(())
    }

    fn visit_recursion(&mut self, recursion: &exprs::Recursion) -> Result<(), E> {
        Ok(())
    }

    fn visit_grapheme(&mut self) -> Result<(), E> {
        Ok(())
    }

    fn visit_codepoint(&mut self) -> Result<(), E> {
        Ok(())
    }

    fn visit_dot(&mut self) -> Result<(), E> {
        Ok(())
    }
}