use std::any::Any;
use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};
use std::iter::from_fn;
use std::marker::PhantomData;
use std::ops::Deref;
use std::rc::Rc;
use crate::atn::INVALID_ALT;
use crate::char_stream::InputData;
use crate::int_stream::EOF;
use crate::interval_set::Interval;
use crate::parser::ParserNodeType;
use crate::parser_rule_context::{ParserRuleContext, RuleContextExt};
use crate::recognizer::Recognizer;
use crate::rule_context::{CustomRuleContext, RuleContext};
use crate::token::Token;
use crate::token_factory::TokenFactory;
use crate::{interval_set, trees, CoerceTo};
use better_any::{Tid, TidAble};
use std::mem;
#[allow(missing_docs)]
pub trait Tree<'input>: RuleContext<'input> {
fn get_parent(&self) -> Option<Rc<<Self::Ctx as ParserNodeType<'input>>::Type>> {
None
}
fn has_parent(&self) -> bool {
false
}
fn get_payload(&self) -> Box<dyn Any> {
unimplemented!()
}
fn get_child(&self, _i: usize) -> Option<Rc<<Self::Ctx as ParserNodeType<'input>>::Type>> {
None
}
fn get_child_count(&self) -> usize {
0
}
fn get_children<'a>(
&'a self,
) -> Box<dyn Iterator<Item = Rc<<Self::Ctx as ParserNodeType<'input>>::Type>> + 'a>
where
'input: 'a,
{
let mut index = 0;
let iter = from_fn(move || {
if index < self.get_child_count() {
index += 1;
self.get_child(index - 1)
} else {
None
}
});
Box::new(iter)
}
}
pub trait ParseTree<'input>: Tree<'input> {
fn get_source_interval(&self) -> Interval {
interval_set::INVALID
}
fn get_text(&self) -> String {
String::new()
}
fn to_string_tree(
&self,
r: &dyn Recognizer<'input, TF = Self::TF, Node = Self::Ctx>,
) -> String {
trees::string_tree(self, r.get_rule_names())
}
}
#[doc(hidden)]
#[derive(Debug)]
pub struct NoError;
#[doc(hidden)]
#[derive(Debug)]
pub struct IsError;
pub struct LeafNode<'input, Node: ParserNodeType<'input>, T: 'static> {
pub symbol: <Node::TF as TokenFactory<'input>>::Tok,
iserror: PhantomData<T>,
}
better_any::tid! { impl <'input, Node, T:'static> TidAble<'input> for LeafNode<'input, Node, T> where Node:ParserNodeType<'input> }
impl<'input, Node: ParserNodeType<'input>, T: 'static> CustomRuleContext<'input>
for LeafNode<'input, Node, T>
{
type TF = Node::TF;
type Ctx = Node;
fn get_rule_index(&self) -> usize {
usize::max_value()
}
fn get_node_text(&self, rule_names: &[&str]) -> String {
self.symbol.borrow().get_text().to_display()
}
}
impl<'input, Node: ParserNodeType<'input>, T: 'static> ParserRuleContext<'input>
for LeafNode<'input, Node, T>
{
}
impl<'input, Node: ParserNodeType<'input>, T: 'static> Tree<'input> for LeafNode<'input, Node, T> {}
impl<'input, Node: ParserNodeType<'input>, T: 'static> RuleContext<'input>
for LeafNode<'input, Node, T>
{
}
impl<'input, Node: ParserNodeType<'input>, T: 'static> ParseTree<'input>
for LeafNode<'input, Node, T>
{
fn get_source_interval(&self) -> Interval {
let i = self.symbol.borrow().get_token_index();
Interval { a: i, b: i }
}
fn get_text(&self) -> String {
self.symbol.borrow().get_text().to_display()
}
}
impl<'input, Node: ParserNodeType<'input>, T: 'static> Debug for LeafNode<'input, Node, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.symbol.borrow().get_token_type() == EOF {
f.write_str("<EOF>")
} else {
let a = self.symbol.borrow().get_text().to_display();
f.write_str(&a)
}
}
}
impl<'input, Node: ParserNodeType<'input>, T: 'static> LeafNode<'input, Node, T> {
pub fn new(symbol: <Node::TF as TokenFactory<'input>>::Tok) -> Self {
Self {
symbol,
iserror: Default::default(),
}
}
}
pub type TerminalNode<'input, NodeType> = LeafNode<'input, NodeType, NoError>;
impl<'input, Node: ParserNodeType<'input>, Listener: ParseTreeListener<'input, Node> + ?Sized>
Listenable<Listener> for TerminalNode<'input, Node>
{
fn enter(&self, listener: &mut Listener) {
listener.visit_terminal(self)
}
fn exit(&self, _listener: &mut Listener) {
}
}
impl<'input, Node: ParserNodeType<'input>, R: Sized, Visitor: ParseTreeVisitor<'input, Node, R> + ?Sized>
Visitable<Visitor, R> for TerminalNode<'input, Node>
{
fn accept(&self, visitor: &mut Visitor) -> R {
visitor.visit_terminal(self)
}
}
pub type ErrorNode<'input, NodeType> = LeafNode<'input, NodeType, IsError>;
impl<'input, Node: ParserNodeType<'input>, Listener: ParseTreeListener<'input, Node> + ?Sized>
Listenable<Listener> for ErrorNode<'input, Node>
{
fn enter(&self, listener: &mut Listener) {
listener.visit_error_node(self)
}
fn exit(&self, _listener: &mut Listener) {
}
}
impl<'input, Node: ParserNodeType<'input>, R: Sized, Visitor: ParseTreeVisitor<'input, Node, R> + ?Sized>
Visitable<Visitor, R> for ErrorNode<'input, Node>
{
fn accept(&self, visitor: &mut Visitor) -> R {
visitor.visit_error_node(self)
}
}
pub trait ParseTreeVisitorCompat<'input>: VisitChildren<'input, Self::Node, Self::Return> {
type Node: ParserNodeType<'input>;
type Return: Default;
fn visit(&mut self, node: &<Self::Node as ParserNodeType<'input>>::Type) -> Self::Return {
return self.visit_node(&node);
}
fn visit_terminal(&mut self, _node: &TerminalNode<'input, Self::Node>) -> Self::Return {
Self::Return::default()
}
fn visit_error_node(&mut self, _node: &ErrorNode<'input, Self::Node>) -> Self::Return {
Self::Return::default()
}
fn visit_children(
&mut self,
node: &<Self::Node as ParserNodeType<'input>>::Type,
) -> Self::Return {
let mut result = Self::Return::default();
for node in node.get_children() {
if !self.should_visit_next_child(&node, &result) {
break;
}
let child_result = self.visit(&node);
result = self.aggregate_results(result, child_result);
}
return result;
}
fn aggregate_results(&self, aggregate: Self::Return, next: Self::Return) -> Self::Return {
next
}
fn should_visit_next_child(
&self,
node: &<Self::Node as ParserNodeType<'input>>::Type,
current: &Self::Return,
) -> bool {
true
}
}
impl<'input, Node, T, R: Sized> ParseTreeVisitor<'input, Node, R> for T
where
Node: ParserNodeType<'input>,
Node::Type: VisitableDyn<Self, R>,
T: ParseTreeVisitorCompat<'input, Node = Node, Return = R>,
{
fn visit_terminal(&mut self, node: &TerminalNode<'input, Node>) -> R {
<Self as ParseTreeVisitorCompat>::visit_terminal(self, node)
}
fn visit_error_node(&mut self, node: &ErrorNode<'input, Node>) -> R {
<Self as ParseTreeVisitorCompat>::visit_error_node(self, node)
}
fn visit_children(&mut self, node: &Node::Type) -> R {
<Self as ParseTreeVisitorCompat>::visit_children(self, node)
}
}
pub trait ParseTreeVisitor<'input, Node: ParserNodeType<'input>, T: Sized>:
VisitChildren<'input, Node, T>
{
fn visit_terminal(&mut self, _node: &TerminalNode<'input, Node>) -> T {
unreachable!()
}
fn visit_error_node(&mut self, _node: &ErrorNode<'input, Node>) -> T {
unreachable!()
}
fn visit_children(&mut self, node: &Node::Type) -> T {
unreachable!()
}
}
pub trait VisitChildren<'input, Node: ParserNodeType<'input>, T: ?Sized> {
fn visit_node(&mut self, node: &Node::Type) -> T;
}
impl<'input, Node, T, R: Sized> VisitChildren<'input, Node, R> for T
where
Node: ParserNodeType<'input>,
T: ParseTreeVisitor<'input, Node, R> + ?Sized,
Node::Type: VisitableDyn<T, R>,
{
fn visit_node(&mut self, node: &Node::Type) -> R {
node.accept_dyn(self)
}
}
pub trait Visitable<Vis: ?Sized, T: Sized> {
fn accept(&self, _visitor: &mut Vis) -> T {
unreachable!("should have been properly implemented by generated context when reachable")
}
}
#[doc(hidden)]
pub trait VisitableDyn<Vis: ?Sized, R: Sized> {
fn accept_dyn(&self, _visitor: &mut Vis) -> R {
unreachable!("should have been properly implemented by generated context when reachable")
}
}
pub trait ParseTreeListener<'input, Node: ParserNodeType<'input>> {
fn visit_terminal(&mut self, _node: &TerminalNode<'input, Node>) {}
fn visit_error_node(&mut self, _node: &ErrorNode<'input, Node>) {}
fn enter_every_rule(&mut self, _ctx: &Node::Type) {}
fn exit_every_rule(&mut self, _ctx: &Node::Type) {}
}
pub trait Listenable<T: ?Sized> {
fn enter(&self, _listener: &mut T) {}
fn exit(&self, _listener: &mut T) {}
}
#[derive(Debug)]
pub struct ParseTreeWalker<'input, 'a, Node, T = dyn ParseTreeListener<'input, Node> + 'a>(
PhantomData<fn(&'a T) -> &'input Node::Type>,
)
where
Node: ParserNodeType<'input>,
T: ParseTreeListener<'input, Node> + ?Sized;
impl<'input, 'a, Node, T> ParseTreeWalker<'input, 'a, Node, T>
where
Node: ParserNodeType<'input>,
T: ParseTreeListener<'input, Node> + 'a + ?Sized,
Node::Type: Listenable<T>,
{
pub fn walk<Listener, Ctx>(mut listener: Box<Listener>, t: &Ctx) -> Box<Listener>
where
Listener: CoerceTo<T>,
Ctx: CoerceTo<Node::Type>,
{
Self::walk_inner(listener.as_mut().coerce_mut_to(), t.coerce_ref_to());
listener
}
fn walk_inner(listener: &mut T, t: &Node::Type) {
t.enter(listener);
for child in t.get_children() {
Self::walk_inner(listener, child.deref())
}
t.exit(listener);
}
}