use proc_macro2::Span; use super::{ ast::{ Alt, Call, Cat, Epsilon, Expression, Fix, Literal, NamedExpression, Parameter, Variable, }, Name, }; pub trait Visitor { type Out; fn visit_epsilon( &mut self, name: Option<&Name>, span: Option, eps: &Epsilon, ) -> Self::Out; fn visit_literal( &mut self, name: Option<&Name>, span: Option, lit: &Literal, ) -> Self::Out; fn visit_cat(&mut self, name: Option<&Name>, span: Option, cat: &Cat) -> Self::Out; fn visit_alt(&mut self, name: Option<&Name>, span: Option, alt: &Alt) -> Self::Out; fn visit_fix(&mut self, name: Option<&Name>, span: Option, fix: &Fix) -> Self::Out; fn visit_variable( &mut self, name: Option<&Name>, span: Option, var: &Variable, ) -> Self::Out; fn visit_parameter( &mut self, name: Option<&Name>, span: Option, param: &Parameter, ) -> Self::Out; fn visit_call(&mut self, name: Option<&Name>, span: Option, call: &Call) -> Self::Out; } pub trait Mapper { type Out; fn map_epsilon( &mut self, name: &mut Option, span: Option, eps: &mut Epsilon, ) -> Self::Out; fn map_literal( &mut self, name: &mut Option, span: Option, lit: &mut Literal, ) -> Self::Out; fn map_cat(&mut self, name: &mut Option, span: Option, cat: &mut Cat) -> Self::Out; fn map_alt(&mut self, name: &mut Option, span: Option, alt: &mut Alt) -> Self::Out; fn map_fix(&mut self, name: &mut Option, span: Option, fix: &mut Fix) -> Self::Out; fn map_variable( &mut self, name: &mut Option, span: Option, var: &mut Variable, ) -> Self::Out; fn map_parameter( &mut self, name: &mut Option, span: Option, param: &mut Parameter, ) -> Self::Out; fn map_call( &mut self, name: &mut Option, span: Option, call: &mut Call, ) -> Self::Out; } pub trait Folder { type Out; fn fold_epsilon(&mut self, name: Option, span: Option, eps: Epsilon) -> Self::Out; fn fold_literal(&mut self, name: Option, span: Option, lit: Literal) -> Self::Out; fn fold_cat(&mut self, name: Option, span: Option, cat: Cat) -> Self::Out; fn fold_alt(&mut self, name: Option, span: Option, alt: Alt) -> Self::Out; fn fold_fix(&mut self, name: Option, span: Option, fix: Fix) -> Self::Out; fn fold_variable(&mut self, name: Option, span: Option, var: Variable) -> Self::Out; fn fold_parameter( &mut self, name: Option, span: Option, param: Parameter, ) -> Self::Out; fn fold_call(&mut self, name: Option, span: Option, call: Call) -> Self::Out; } pub trait Visitable { fn visit(&self, visitor: &mut V) -> ::Out; fn map(&mut self, mapper: &mut M) -> ::Out; fn fold(self, folder: &mut F) -> ::Out; } impl Visitable for NamedExpression { fn visit(&self, visitor: &mut V) -> ::Out { match &self.expr { Expression::Epsilon(e) => visitor.visit_epsilon(self.name.as_ref(), self.span, e), Expression::Literal(l) => visitor.visit_literal(self.name.as_ref(), self.span, l), Expression::Cat(c) => visitor.visit_cat(self.name.as_ref(), self.span, c), Expression::Alt(a) => visitor.visit_alt(self.name.as_ref(), self.span, a), Expression::Fix(f) => visitor.visit_fix(self.name.as_ref(), self.span, f), Expression::Variable(v) => visitor.visit_variable(self.name.as_ref(), self.span, v), Expression::Parameter(p) => visitor.visit_parameter(self.name.as_ref(), self.span, p), Expression::Call(c) => visitor.visit_call(self.name.as_ref(), self.span, c), } } fn map(&mut self, mapper: &mut M) -> ::Out { match &mut self.expr { Expression::Epsilon(e) => mapper.map_epsilon(&mut self.name, self.span, e), Expression::Literal(l) => mapper.map_literal(&mut self.name, self.span, l), Expression::Cat(c) => mapper.map_cat(&mut self.name, self.span, c), Expression::Alt(a) => mapper.map_alt(&mut self.name, self.span, a), Expression::Fix(f) => mapper.map_fix(&mut self.name, self.span, f), Expression::Variable(v) => mapper.map_variable(&mut self.name, self.span, v), Expression::Parameter(p) => mapper.map_parameter(&mut self.name, self.span, p), Expression::Call(c) => mapper.map_call(&mut self.name, self.span, c), } } fn fold(self, folder: &mut F) -> ::Out { match self.expr { Expression::Epsilon(e) => folder.fold_epsilon(self.name, self.span, e), Expression::Literal(l) => folder.fold_literal(self.name, self.span, l), Expression::Cat(c) => folder.fold_cat(self.name, self.span, c), Expression::Alt(a) => folder.fold_alt(self.name, self.span, a), Expression::Fix(f) => folder.fold_fix(self.name, self.span, f), Expression::Variable(v) => folder.fold_variable(self.name, self.span, v), Expression::Parameter(p) => folder.fold_parameter(self.name, self.span, p), Expression::Call(c) => folder.fold_call(self.name, self.span, c), } } }