#![crate_type = "lib"]
// #![warn(missing_docs)] // warn if there is missing docs
// #![warn(missing_debug_implementations)]
// #![warn(trivial_numeric_casts)]

//! # dbt-antlr4 runtime
//!
//! This is a Rust runtime for [ANTLR4] parser generator.
//! It is required to use parsers and lexers generated by [ANTLR4] parser generator
//!
//! This documentation refers to particular api used by generated parsers,lexers and syntax trees.
//!
//! For info on what is [ANTLR4] and how to generate parser please refer to:
//!  - [ANTLR4] main repository
//!  - [README] for Rust target
//!
//! [ANTLR4]: https://github.com/antlr/antlr4
//! [README]: https://github.com/sdf-labs/antlr4/blob/dev/runtime/Rust/README.md
//!
//! Documentation for this crate is still a work in progress, but you can find
//! some docs in the source code, and also refer to the Java runtime
//! documentation for general concepts and architecture of the runtime, as well
//! as for documentation of internal modules that are not yet documented in
//! Rust.
//!
//! [`CharStream`]: crate::char_stream::CharStream
//! [`TokenFactory`]: crate::token_factory::TokenFactory
//! [`Token`]: crate::token::Token
//! [`TokenStream`]: crate::token_stream::TokenStream
//! [`ParserRuleContext`]: crate::parser_rule_context::ParserRuleContext

#[doc(inline)]
pub use error_strategy::{BailErrorStrategy, DefaultErrorStrategy, ErrorStrategy};

pub use input_stream::InputStream;

#[doc(inline)]
pub use lexer::{BaseLexer, Lexer};
#[doc(inline)]
pub use parser::{BaseParser, ListenerId, Parser};
#[doc(inline)]
pub use token_source::TokenSource;
//extern crate uuid;
#[doc(hidden)]
pub use prediction_context::PredictionContextCache;

#[doc(inline)]
pub use prediction_mode::PredictionMode;

#[doc(inline)]
pub use arena::Arena;
#[cfg(feature = "arena-allocation-limit")]
#[doc(inline)]
pub use arena::{get_default_arena_alloc_limit, set_default_arena_alloc_limit};

mod arena;
#[doc(hidden)]
pub mod atn_config;
#[doc(hidden)]
pub mod atn_simulator;
pub mod int_stream;
mod lexer_action;
mod ll1_analyzer;
#[doc(hidden)]
pub mod recognizer;
pub mod token_factory;
//pub mod tokenstream_rewriter;
#[doc(hidden)]
pub mod atn_deserialization_options;
#[doc(hidden)]
pub mod atn_state;
pub mod char_stream;
#[doc(hidden)]
pub mod interval_set;
pub mod parser_rule_context;
mod prediction_context;
#[doc(hidden)]
pub mod semantic_context;
mod token_source;
pub mod token_stream;
//pub mod trace_listener;
#[doc(hidden)]
pub mod dfa;
#[doc(hidden)]
pub mod transition;
pub mod tree;
//pub mod file_stream;
#[doc(hidden)]
pub mod atn;
#[doc(hidden)]
pub mod atn_config_set;
#[doc(hidden)]
pub mod atn_deserializer;
pub mod common_token_stream;
pub mod error_listener;
pub mod error_strategy;
pub mod errors;
pub mod input_stream;
pub mod lexer;
#[doc(hidden)]
pub mod lexer_action_executor;
pub mod lexer_atn_simulator;
pub mod parser;
pub mod parser_atn_simulator;
mod prediction_mode;
pub mod token;
pub mod trees;
mod utils;
//pub mod tokenstream_rewriter_test;
mod atn_type;
// mod context_factory;
pub mod rule_context;
pub mod vocabulary;

// ======= Re-exports ========
pub use stacker;

pub const VERSION_MAJOR: &str = env!("CARGO_PKG_VERSION_MAJOR");
pub const VERSION_MINOR: &str = env!("CARGO_PKG_VERSION_MINOR");

// ======= Macros =======

pub const fn version_str_eq(a: &str, b: &str) -> bool {
    if a.len() != b.len() {
        return false;
    }
    let (a, b) = (a.as_bytes(), b.as_bytes());
    let mut i = 0;
    while i < a.len() {
        if a[i] != b[i] {
            return false;
        }
        i += 1;
    }
    true
}

#[macro_export]
macro_rules! check_version {
    ($major:literal, $minor:literal) => {
        const _: () = assert!(
            $crate::version_str_eq($major, $crate::VERSION_MAJOR)
                && $crate::version_str_eq($minor, $crate::VERSION_MINOR),
            "Generated parser is not compatible with current runtime version, \
             please regenerate using the matching ANTLR tool version, \
             or update the runtime to match the version used for generation."
        );
    };
}

#[macro_export]
macro_rules! impl_tree {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($enum_name:ident { $($variant:ident,)+ }) => {
        impl<'input, 'arena> Tree<'arena> for $enum_name<'input, 'arena> {
            fn get_parent(&self) -> Option<&'arena Self> {
                match self {
                    $( $enum_name::$variant(inner) => inner.get_parent(), )+
                    _ => None,
                }
            }

            fn has_parent(&self) -> bool {
                match self {
                    $( $enum_name::$variant(inner) => inner.has_parent(), )+
                    _ => false,
                }
            }

            // fn get_payload(&self) -> Box<dyn std::any::Any> {
            //     match self {
            //         $( $enum_name::$variant(inner) => Tree::get_payload(inner), )+
            //     }
            // }

            fn get_child(&self, i: usize) -> Option<&'arena Self> {
                match self {
                    $( $enum_name::$variant(inner) => inner.get_child(i), )+
                    _ => None,
                }
            }

            fn get_child_count(&self) -> usize {
                match self {
                    $( $enum_name::$variant(inner) => inner.get_child_count(), )+
                    _ => 0,
                }
            }

            fn get_children<'a>(&'a self) -> Box<dyn Iterator<Item = &'arena Self> + 'a> {
                match self {
                    $( $enum_name::$variant(inner) => inner.get_children(), )+
                    _ => Box::new(std::iter::empty()) as Box<dyn Iterator<Item = &'arena Self>>,
                }
            }

            // fn to_string_tree(&self) -> String {
            //     match self {
            //         $( $enum_name::$variant(inner) => Tree::to_string_tree(inner), )+
            //     }
            // }
        }
    };
}

#[macro_export]
macro_rules! impl_node_kind_common {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($node_kind:ident { $($labeled_variant:ident($inner:ident),)* ; $($variant:ident),* }) => {
        fn cast_to_ctx<'n, 'input: 'arena>(
            node: &'n TreeNode<'input, 'arena, Self, Tok>,
        ) -> &'n dyn ParserRuleContext<'input, 'arena> {
            match node.node_tag() {
                $( $node_kind::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>), )*
                $( $node_kind::$variant => $crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>), )*
                $node_kind::Terminal => $crate::cast_unchecked!(node.ctx_ptr() => TerminalNode<'input, 'arena, Tok>),
                $node_kind::Error => $crate::cast_unchecked!(node.ctx_ptr() => ErrorNode<'input, 'arena, Tok>),
            }
        }

        fn cast_to_ctx_mut<'n, 'input: 'arena>(
            node: &'n mut TreeNode<'input, 'arena, Self, Tok>,
        ) -> &'n mut dyn ParserRuleContext<'input, 'arena> {
            match node.node_tag() {
                $( $node_kind::$labeled_variant => $crate::cast_unchecked!(node => mut $inner<'input, 'arena, Tok>), )*
                $( $node_kind::$variant => $crate::cast_unchecked!(node.ctx_ptr() => mut $variant<'input, 'arena, Tok>), )*
                $node_kind::Terminal => $crate::cast_unchecked!(node.ctx_ptr() => mut TerminalNode<'input, 'arena, Tok>),
                $node_kind::Error => $crate::cast_unchecked!(node.ctx_ptr() => mut ErrorNode<'input, 'arena, Tok>),
            }
        }

        fn set_alt_number<'input: 'arena>(node: &mut TreeNode<'input, 'arena, Self, Tok>, alt_number: i32) {
            match node.node_tag() {
                $( $node_kind::$labeled_variant => $crate::cast_unchecked!(node => mut $inner<'input, 'arena, Tok>).set_alt_number(alt_number), )*
                $( $node_kind::$variant => $crate::cast_unchecked!(node.ctx_ptr() => mut $variant<'input, 'arena, Tok>).set_alt_number(alt_number), )*
                _ => {}
            }
        }

        fn get_rule_index<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>) -> usize {
            match node.node_tag() {
                $( $node_kind::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).get_rule_index(), )*
                $( $node_kind::$variant => $crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>).get_rule_index(), )*
                _ => 0,
            }
        }

        fn get_alt_number<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>) -> i32 {
            match node.node_tag() {
                $( $node_kind::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).get_alt_number(), )*
                $( $node_kind::$variant => $crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>).get_alt_number(), )*
                _ => INVALID_ALT,
            }
        }

        #[inline]
        fn terminal() -> Self {
            Self::Terminal
        }

        #[inline]
        fn error() -> Self {
            Self::Error
        }

        #[inline]
        fn is_context(&self) -> bool {
            !matches!(self, Self::Terminal | Self::Error)
        }
    };
}

#[macro_export]
macro_rules! impl_node_kind {
    // No Listener and no Visitor
    ($enum_name:ident { $($labeled_variant:ident($inner:ident),)* ; $($variant:ident),* }; ) => {
        impl<'arena, Tok: Token + 'arena> NodeKindType<'arena, Tok> for $enum_name {
            type Listener = dyn ParseTreeListener<'arena, Self, Tok>;

            $crate::impl_node_kind_common! { $enum_name { $($labeled_variant($inner),)* ; $($variant),* } }

            fn enter_rule<'input: 'arena>(_node: &TreeNode<'input, 'arena, Self, Tok>, _listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                Ok(())
            }

            fn exit_rule<'input: 'arena>(_node: &TreeNode<'input, 'arena, Self, Tok>, _listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                Ok(())
            }
        }
    };

    // Just Visitor
    ($enum_name:ident { $($labeled_variant:ident($inner:ident),)*; $($variant:ident($visit_method:ident),)* }; visitor = $visitor:ty, ) => {
        impl<'arena, Tok: Token + 'arena> NodeKindType<'arena, Tok> for $enum_name {
            type Listener = dyn ParseTreeListener<'arena, Self, Tok>;

            $crate::impl_node_kind_common! { $enum_name { $( $labeled_variant($inner),)*; $($variant),* } }

            fn enter_rule(_node: &TreeNode<'input, 'arena, Self, Tok>, _listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                Ok(())
            }

            fn exit_rule(_node: &TreeNode<'input, 'arena, Self, Tok>, _listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                Ok(())
            }

            // fn accept(&self, visitor: &mut Self::Visitor) -> Result<<Self::Visitor as ParseTreeVisitor<'input, 'arena, Self>>::Return, ANTLRError>
            // {
            //     match self {
            //         $( $enum_name::$labeled_variant(inner) => inner.dispatch_visit(visitor), )*
            //         $( $enum_name::$variant(inner) => visitor.$visit_method(inner), )*
            //         $enum_name::Terminal(inner) => { visitor.visit_terminal(inner) },
            //         $enum_name::Error(inner) => { visitor.visit_error_node(inner) },
            //     }
            // }
        }
    };

    // Just Listener
    ($enum_name:ident { $($labeled_variant:ident($inner:ident),)*; $($variant:ident($enter_method:ident, $exit_method:ident, ),)* }; listener = $listener:ty, ) => {
        impl<'arena, Tok: Token + 'arena> NodeKindType<'arena, Tok> for $enum_name {
            type Listener = $listener;

            $crate::impl_node_kind_common! { $enum_name { $( $labeled_variant($inner),)*; $($variant),* } }

            fn enter_rule<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>, listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                match node.node_tag() {
                    $( $enum_name::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).dispatch_enter(listener), )*
                    $( $enum_name::$variant => listener.$enter_method($crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>)), )*
                    $enum_name::Terminal => { listener.visit_terminal($crate::cast_unchecked!(node.ctx_ptr() => TerminalNode<'input, 'arena, Tok>)) },
                    $enum_name::Error => { listener.visit_error_node($crate::cast_unchecked!(node.ctx_ptr() => ErrorNode<'input, 'arena, Tok>)) },
                }
            }

            fn exit_rule<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>, listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                match node.node_tag() {
                    $( $enum_name::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).dispatch_exit(listener), )*
                    $( $enum_name::$variant => listener.$exit_method($crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>)), )*
                    $enum_name::Terminal => { listener.visit_terminal($crate::cast_unchecked!(node.ctx_ptr() => TerminalNode<'input, 'arena, Tok>)) },
                    $enum_name::Error => { listener.visit_error_node($crate::cast_unchecked!(node.ctx_ptr() => ErrorNode<'input, 'arena, Tok>)) },
                }
            }
        }
    };

    // Both listener and visitor
    ($enum_name:ident { $($labeled_variant:ident($inner:ident),)*; $($variant:ident($enter_method:ident, $exit_method:ident, $visit_method:ident),)* }; listener = $listener:ty, visitor = $visitor:ident, ) => {
        impl<'arena, Tok: Token + 'arena> NodeKindType<'arena, Tok> for $enum_name {
            type Listener = $listener;

            $crate::impl_node_kind_common! { $enum_name { $($labeled_variant($inner),)*; $($variant),* } }

            fn enter_rule<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>, listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                match node.node_tag() {
                    $( $enum_name::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).dispatch_enter(listener), )*
                    $( $enum_name::$variant => listener.$enter_method($crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>)), )*
                    $enum_name::Terminal => { listener.visit_terminal($crate::cast_unchecked!(node.ctx_ptr() => TerminalNode<'input, 'arena, Tok>)) },
                    $enum_name::Error => { listener.visit_error_node($crate::cast_unchecked!(node.ctx_ptr() => ErrorNode<'input, 'arena, Tok>)) },
                }
            }

            fn exit_rule<'input: 'arena>(node: &TreeNode<'input, 'arena, Self, Tok>, listener: &mut Self::Listener) -> Result<(), ANTLRError> {
                match node.node_tag() {
                    $( $enum_name::$labeled_variant => $crate::cast_unchecked!(node => $inner<'input, 'arena, Tok>).dispatch_exit(listener), )*
                    $( $enum_name::$variant => listener.$exit_method($crate::cast_unchecked!(node.ctx_ptr() => $variant<'input, 'arena, Tok>)), )*
                    $enum_name::Terminal => { listener.visit_terminal($crate::cast_unchecked!(node.ctx_ptr() => TerminalNode<'input, 'arena, Tok>)) },
                    $enum_name::Error => { listener.visit_error_node($crate::cast_unchecked!(node.ctx_ptr() => ErrorNode<'input, 'arena, Tok>)) },
                }
            }
        }

        impl<'input, 'arena, Tok: Token + 'arena> Visitable<'input, 'arena, Tok> for TreeNode<'input, 'arena, $enum_name, Tok>
        where
            'input: 'arena,
        {
            fn accept<V>(&'arena self, visitor: &mut V) -> Result<V::Return, ANTLRError>
            where
                V: $visitor<'input, 'arena, Tok> + ?Sized,
            {
                match self.node_tag() {
                    $( $enum_name::$labeled_variant => $crate::cast_unchecked!(self => $inner<'input, 'arena, Tok>).accept(visitor), )*
                    $( $enum_name::$variant => visitor.$visit_method($crate::cast_unchecked!(self.ctx_ptr() => $variant<'input, 'arena, Tok>)), )+
                    $enum_name::Terminal => { visitor.visit_terminal($crate::cast_unchecked!(self.ctx_ptr() => TerminalNode<'input, 'arena, Tok>)) },
                    $enum_name::Error => { visitor.visit_error_node($crate::cast_unchecked!(self.ctx_ptr() => ErrorNode<'input, 'arena, Tok>)) },
                }
            }
        }
    };
}

#[macro_export]
macro_rules! impl_listener_dispatch {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($listener:ident::$node_name:ident::$enum_name:ident { $($variant:ident($enter_method:ident, $exit_method:ident),)+ }) => {
        impl<'input, 'arena, Tok: Token + 'input> $enum_name<'input, 'arena, Tok>
        where
            'input: 'arena,
        {
            fn dispatch_enter(&self, listener: &mut (dyn $listener<'arena, Tok> + 'static)) -> Result<(), ANTLRError>
            {
                match self {
                    $( $enum_name::$variant(inner) => listener.$enter_method(inner), )+
                    $enum_name::Error(_) => Ok(()),
                }
            }

            fn dispatch_exit(&self, listener: &mut (dyn $listener<'arena, Tok> + 'static)) -> Result<(), ANTLRError>
            {
                match self {
                    $( $enum_name::$variant(inner) => listener.$exit_method(inner), )+
                    $enum_name::Error(_) => Ok(()),
                }
            }
        }
    };
}

#[macro_export]
macro_rules! impl_visitable {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($visitor:ident::$enum_name:ident { $($variant:ident($visit_method:ident),)+ }) => {
        impl<'input, 'arena, Tok: Token + 'input> Visitable<'input, 'arena, Tok> for $enum_name<'input, 'arena, Tok> {
            fn accept<V>(&'arena self, visitor: &mut V) -> Result<V::Return, ANTLRError>
            where
                V: $visitor<'input, 'arena, Tok> + ?Sized,
            {
                match self {
                    $( $enum_name::$variant(inner) => visitor.$visit_method(inner), )+
                    $enum_name::Error(_) => Ok(Default::default()),
                }
            }
        }
    };
    ($visitor:ident::$ctx_name:ident($visit_method:ident)) => {
        impl<'input, 'arena, Tok: Token + 'input> Visitable<'input, 'arena, Tok> for $ctx_name<'input, 'arena, Tok> {
            fn accept<V>(&'arena self, visitor: &mut V) -> Result<V::Return, ANTLRError>
            where
                V: $visitor<'input, 'arena, Tok> + ?Sized,
            {
                visitor.$visit_method(self)
            }
        }
    };
}

#[macro_export]
macro_rules! impl_rule_context {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($enum_name:ident { $($ref_variant:ident,)* } $({ $($inline_variant:ident,)+ })?) => {
        impl<'input, 'arena, Tok> RuleContext<'arena> for $enum_name<'input, 'arena, Tok>
        where
            'input: 'arena,
            Tok: Token + 'input,
        {
            fn get_rule_index(&self) -> usize {
                match self {
                    // Generate a match arm for every variant
                    $( $enum_name::$ref_variant(inner) => RuleContext::get_rule_index(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => RuleContext::get_rule_index(inner), )+)?
                }
            }

            fn get_alt_number(&self) -> i32 {
                match self {
                    $( $enum_name::$ref_variant(inner) => RuleContext::get_alt_number(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => RuleContext::get_alt_number(inner), )+)?
                }
            }

            fn get_invoking_state(&self) -> i32 {
                match self {
                    $( $enum_name::$ref_variant(inner) => RuleContext::get_invoking_state(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => RuleContext::get_invoking_state(inner), )+)?
                }
            }

            fn get_parent_ctx(&self) -> Option<&'arena dyn RuleContext<'arena>> {
                match self {
                    $( $enum_name::$ref_variant(inner) => RuleContext::get_parent_ctx(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => RuleContext::get_parent_ctx(inner), )+)?
                }
            }

            fn get_node_text(&self, rule_names: &[&str]) -> String {
                match self {
                    $( $enum_name::$ref_variant(inner) => RuleContext::get_node_text(&**inner, rule_names), )*
                    $($( $enum_name::$inline_variant(inner) => RuleContext::get_node_text(inner, rule_names), )+)?
                }
            }

        }
    };
}

#[macro_export]
macro_rules! impl_parser_rule_context {
    // Pattern: EnumName { Variant1, Variant2, ... }
    ($enum_name:ident { $($ref_variant:ident,)* } $({ $($inline_variant:ident,)+ })?) => {
        impl<'input, 'arena, Tok> ParserRuleContext<'input, 'arena> for $enum_name<'input, 'arena, Tok>
        where
            'input: 'arena,
            Tok: Token + 'input,
        {
            fn start(&self) -> &'arena dyn $crate::token::Token {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::start(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::start(inner), )+)?
                }
            }

            fn stop(&self) -> &'arena dyn $crate::token::Token {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::stop(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::stop(inner), )+)?
                }
            }

            fn get_parent_ctx(&self) -> Option<&'arena dyn ParserRuleContext<'input, 'arena>> {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_parent_ctx(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_parent_ctx(inner), )+)?
                }
            }

            fn get_child_ctx(&self, _i: usize) -> Option<&'arena dyn ParserRuleContext<'input, 'arena>> {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_child_ctx(&**inner, _i), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_child_ctx(inner, _i), )+)?
                }
            }

            fn get_child_count(&self) -> usize {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_child_count(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_child_count(inner), )+)?
                }
            }

            fn iter_children<'a>(
                &'a self,
            ) -> Box<dyn Iterator<Item = &'arena dyn ParserRuleContext<'input, 'arena>> + 'a>
            where
                'input: 'a,
                'arena: 'a,
            {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::iter_children(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::iter_children(inner), )+)?
                }
            }

            fn get_token(&self, _ttype: i32, _pos: usize) -> Option<&dyn $crate::token::Token> {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_token(&**inner, _ttype, _pos), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_token(inner, _ttype, _pos), )+)?
                }
            }

            fn get_tokens(&self, _ttype: i32) -> Vec<&dyn $crate::token::Token> {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_tokens(&**inner, _ttype), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_tokens(inner, _ttype), )+)?
                }
            }

            fn get_text(&self) -> String {
                match self {
                    $( $enum_name::$ref_variant(inner) => ParserRuleContext::get_text(&**inner), )*
                    $($( $enum_name::$inline_variant(inner) => ParserRuleContext::get_text(inner), )+)?
                }
            }
       }
    };
}

#[macro_export]
macro_rules! impl_tree_trait_delegates {
    ($node_kind:ident::$enum_name:ident { $($variant:ident),+ $(,)? }) => {
        impl<'input, 'arena, Tok> $enum_name<'input, 'arena, Tok>
        where
            'input: 'arena,
            Tok: Token + 'input,
        {
            // fn get_parent(&self) -> Option<&'arena TreeNode<'input, 'arena, $node_kind>> {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.get_parent(), )+
            //     }
            // }

            // fn has_parent(&self) -> bool {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.has_parent(), )+
            //     }
            // }

            // fn get_child(&self, i: usize) -> Option<&'arena TreeNode<'input, 'arena, $node_kind>> {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.get_child(i), )+
            //     }
            // }

            // fn get_child_count(&self) -> usize {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.get_child_count(), )+
            //     }
            // }

            // fn get_children<'a>(&'a self) -> Box<dyn Iterator<Item = &'arena TreeNode<'input, 'arena, $node_kind>> + 'a> {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.get_children(), )+
            //     }
            // }

            // fn set_start(&mut self, t: Option<&'arena dyn $crate::token::Token>) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.set_start(t), )+
            //     }
            // }

            // fn set_stop(&mut self, t: Option<&'arena dyn $crate::token::Token>) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.set_stop(t), )+
            //     }
            // }

            // fn set_parent(&mut self, parent: Option<&'arena TreeNode<'input, 'arena, $node_kind>>) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.set_parent(parent), )+
            //     }
            // }

            // fn set_invoking_state(&mut self, t: i32) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.set_invoking_state(t), )+
            //     }
            // }

            fn set_alt_number(&mut self, alt_number: i32) {
                match self {
                    $( $enum_name::$variant(inner) => inner.set_alt_number(alt_number), )+
                }
            }

            // fn set_exception(&self, e: $crate::errors::ANTLRError, arena: &'arena $crate::Arena) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.set_exception(e, arena), )+
            //     }
            // }

            // fn remove_last_child(&mut self) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.remove_last_child(), )+
            //     }
            // }

            // fn add_child(&mut self, child: &'arena TreeNode<'input, 'arena, $node_kind>) {
            //     match self {
            //         $( $enum_name::$variant(inner) => inner.add_child(child), )+
            //     }
            // }
        }
    };
}

#[macro_export]
macro_rules! impl_node_inner {
    ($node_kind:ident::$node_variant:ident::$context_all:ident { $($variant:ident),+ $(,)? }) => {
        impl<'input, 'arena, Tok> NodeInner<'input, 'arena, $node_kind, Tok>
            for $context_all<'input, 'arena, Tok>
        where
            'input: 'arena,
            Tok: Token + 'input,
        {
            fn cast_from<'a>(node: &'a TreeNode<'input, 'arena, $node_kind, Tok>) -> Option<&'a Self> {
                match node.node_tag() {
                    $node_kind::$node_variant => Some($crate::cast_unchecked!(node => Self)),
                    _ => None,
                }
            }

            fn cast_from_mut<'a>(node: &'a mut TreeNode<'input, 'arena, $node_kind, Tok>) -> Option<&'a mut Self>
            where
                Self: Sized,
            {
                match node.node_tag() {
                    $node_kind::$node_variant => Some($crate::cast_unchecked!(node => mut Self)),
                    _ => None,
                }
            }

            fn as_node(&self) -> &TreeNode<'input, 'arena, $node_kind, Tok> {
                $crate::cast_unchecked!(self => TreeNode<'input, 'arena, $node_kind, Tok>)
            }

            fn as_node_mut(&mut self) -> &mut TreeNode<'input, 'arena, $node_kind, Tok> {
                $crate::cast_unchecked!(self => mut TreeNode<'input, 'arena, $node_kind, Tok>)
            }

            fn iter_child_nodes<'a>(&'a self) -> Box<dyn Iterator<Item = &'arena TreeNode<'input, 'arena, $node_kind, Tok>> + 'a> {
                match self {
                    $( $context_all::$variant(inner) => inner.get_children(), )+
                }
            }
        }
    };
}

#[macro_export]
macro_rules! impl_token_source {
    ($lexer:ident) => {
        impl<'input, 'arena, Input, TF> $crate::TokenSource<'input, 'arena, TF>
            for $lexer<'input, 'arena, Input, TF>
        where
            TF: $crate::token_factory::TokenFactory<'input, 'arena> + 'arena,
            Input: $crate::char_stream::CharStream<'input>,
        {
            fn next_token(&mut self) -> &'arena mut TF::Tok {
                self.base.next_token()
            }

            fn get_line(&self) -> u32 {
                self.base.get_line()
            }

            fn get_char_position_in_line(&self) -> i32 {
                self.base.get_char_position_in_line()
            }

            fn get_input_stream(&mut self) -> Option<&mut dyn $crate::int_stream::IntStream> {
                self.base.get_input_stream()
            }

            fn get_source_name(&self) -> String {
                self.base.get_source_name()
            }

            fn get_token_factory(&self) -> &TF {
                self.base.get_token_factory()
            }

            fn get_dfa_string(&self) -> String {
                self.base.get_dfa_string()
            }
        }
    };
}

#[macro_export]
macro_rules! impl_deref {
    (parser => $parser_name:ident) => {
        impl<'input, 'arena, Input, TF> Deref for $parser_name<'input, 'arena, Input, TF>
        where
            'input: 'arena,
            TF: TokenFactory<'input, 'arena> + 'arena,
            Input: TokenStream<'input, 'arena, TF> + 'arena,
        {
            type Target = BaseParserType<'input, 'arena, Input, TF>;
            fn deref(&self) -> &Self::Target {
                &self.base
            }
        }

        impl<'input, 'arena, Input, TF> DerefMut for $parser_name<'input, 'arena, Input, TF>
        where
            'input: 'arena,
            TF: TokenFactory<'input, 'arena> + 'arena,
            Input: TokenStream<'input, 'arena, TF> + 'arena,
        {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.base
            }
        }
    };
    (lexer => $lexer_name:ident) => {
        impl<'input, 'arena, Input, TF> Deref for $lexer_name<'input, 'arena, Input, TF>
        where
            'input: 'arena,
            TF: TokenFactory<'input, 'arena> + 'arena,
            Input: CharStream<'input> + 'arena,
        {
            type Target = BaseLexerType<'input, 'arena, Input, TF>;
            fn deref(&self) -> &Self::Target {
                &self.base
            }
        }

        impl<'input, 'arena, Input, TF> DerefMut for $lexer_name<'input, 'arena, Input, TF>
        where
            'input: 'arena,
            TF: TokenFactory<'input, 'arena> + 'arena,
            Input: CharStream<'input> + 'arena,
        {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.base
            }
        }
    };
}

#[macro_export]
macro_rules! cast_unchecked {
    ($ptr:expr => $target:ty) => {{
        let ptr = ($ptr as *const _ as *const ()).cast::<$target>();
        unsafe { &*ptr }
    }};
    ($ptr:expr => mut $target:ty) => {{
        let ptr = ($ptr as *mut _ as *mut ()).cast::<$target>();
        unsafe { &mut *ptr }
    }};
}
