use std::{any::Any, error::Error};
use chiru::runtime::ast::{rule_context::RuleContext, ast_context::ASTContext, error_context::ErrorContext, terminal_context::TerminalContext};
use super::{
{{ grammar_name.0 }}_context::{
{% for nonterminal in nonterminals %}{{nonterminal.3}}Context,{% endfor %}
},
{{ grammar_name.0 }}_parser::{{grammar_name.2}}Parser,
};
pub trait {{ grammar_name.2 }}Visitor {
{% for item in nonterminals %}
fn visit_{{ item.1 }}(&mut self, ctx: &dyn {{ item.3 }}Context) -> Result<Box<dyn Any>, Box<dyn Error>> {
self.visit_children(ctx.as_rule())
}
{% endfor %}
fn visit(&mut self, ast: &RuleContext) -> Result<Box<dyn Any>, Box<dyn Error>> {
match ast.get_rule_index() {
{% for item in nonterminals %}
{{grammar_name.2}}Parser::{{item.2}} => self.visit_{{ item.1 }}(ast),{% endfor %}
_ => self.visit_children(ast)
}
}
fn visit_terminal(&mut self, _terminal: &TerminalContext) -> Result<Box<dyn Any>, Box<dyn Error>> { self.default_result() }
fn visit_errornode(&mut self, _errornode: &ErrorContext) -> Result<Box<dyn Any>, Box<dyn Error>> { self.default_result() }
fn visit_children(&mut self, ctx: &RuleContext) -> Result<Box<dyn Any>, Box<dyn Error>> {
let mut result = self.default_result();
for child in ctx.children.iter() {
if ! self.should_visit_next_child(ctx, &result) { break; }
let child_result = match child {
ASTContext::Terminal(ctx) => self.visit_terminal(ctx),
ASTContext::Rule(ctx) => self.visit(ctx),
ASTContext::Error(ctx) => self.visit_errornode(ctx),
};
result = self.aggregate_result(result, child_result);
}
result
}
fn default_result(&mut self) -> Result<Box<dyn Any>, Box<dyn Error>> { Ok(Box::new(())) }
fn aggregate_result(&mut self, _aggregate: Result<Box<dyn Any>, Box<dyn Error>> , next_result: Result<Box<dyn Any>, Box<dyn Error>> ) -> Result<Box<dyn Any>, Box<dyn Error>> { next_result }
fn should_visit_next_child(&mut self, _context: &RuleContext, _current_result: &dyn Any) -> bool {true}
}