use std::borrow::Borrow;
use std::error::Error;
use std::fmt;
use std::fmt::Formatter;
use std::fmt::{Debug, Display};
use std::ops::Deref;
use std::rc::Rc;
use crate::atn_simulator::IATNSimulator;
use crate::interval_set::IntervalSet;
use crate::parser::{Parser, ParserNodeType};
use crate::rule_context::states_stack;
use crate::token::{OwningToken, Token};
use crate::transition::PredicateTransition;
use crate::transition::TransitionType::TRANSITION_PREDICATE;
#[derive(Debug)]
pub enum ANTLRError {
LexerNoAltError { start_index: isize },
NoAltError(NoViableAltError),
InputMismatchError(InputMisMatchError),
PredicateError(FailedPredicateError),
IllegalStateError(String),
FallThrough(Box<dyn Error>),
OtherError(Box<dyn Error>),
}
impl Clone for ANTLRError {
fn clone(&self) -> Self {
match self {
ANTLRError::LexerNoAltError { start_index } => ANTLRError::LexerNoAltError {
start_index: *start_index,
},
ANTLRError::NoAltError(e) => ANTLRError::NoAltError(e.clone()),
ANTLRError::InputMismatchError(e) => ANTLRError::InputMismatchError(e.clone()),
ANTLRError::PredicateError(e) => ANTLRError::PredicateError(e.clone()),
ANTLRError::IllegalStateError(e) => ANTLRError::IllegalStateError(e.clone()),
ANTLRError::FallThrough(_) => panic!("clone not supported"),
ANTLRError::OtherError(_) => panic!("clone not supported"),
}
}
}
impl Display for ANTLRError {
fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { <Self as Debug>::fmt(self, _f) }
}
impl Error for ANTLRError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
ANTLRError::FallThrough(x) => Some(x.as_ref()),
ANTLRError::OtherError(x) => Some(x.as_ref()),
_ => None,
}
}
}
impl RecognitionError for ANTLRError {
fn get_offending_token(&self) -> Option<&OwningToken> {
Some(match self {
ANTLRError::NoAltError(e) => &e.base.offending_token,
ANTLRError::InputMismatchError(e) => &e.base.offending_token,
ANTLRError::PredicateError(e) => &e.base.offending_token,
_ => return None,
})
}
}
pub trait RecognitionError: Error {
fn get_offending_token(&self) -> Option<&OwningToken>;
fn get_message(&self) -> String { self.to_string() }
}
#[derive(Debug, Clone)]
pub struct BaseRecognitionError {
pub message: String,
pub offending_token: OwningToken,
pub offending_state: isize,
states_stack: Vec<isize>, }
impl BaseRecognitionError {
pub fn get_expected_tokens<'a, T: Parser<'a>>(&self, recognizer: &T) -> IntervalSet {
recognizer
.get_interpreter()
.atn()
.get_expected_tokens(self.offending_state, self.states_stack.iter().copied())
}
fn new<'a, T: Parser<'a>>(recog: &mut T) -> BaseRecognitionError {
BaseRecognitionError {
message: "".to_string(),
offending_token: recog.get_current_token().borrow().to_owned(),
offending_state: recog.get_state(),
states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(),
}
}
}
#[derive(Debug, Clone)]
pub struct LexerNoViableAltError {
base: BaseRecognitionError,
start_index: isize,
}
#[derive(Debug, Clone)]
pub struct NoViableAltError {
pub base: BaseRecognitionError,
pub start_token: OwningToken,
}
impl NoViableAltError {
pub fn new<'a, T: Parser<'a>>(recog: &mut T) -> NoViableAltError {
Self {
base: BaseRecognitionError {
message: "".to_string(),
offending_token: recog.get_current_token().borrow().to_owned(),
offending_state: recog.get_state(),
states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(),
},
start_token: recog.get_current_token().borrow().to_owned(),
}
}
pub fn new_full<'a, T: Parser<'a>>(
recog: &mut T,
start_token: OwningToken,
offending_token: OwningToken,
) -> NoViableAltError {
Self {
base: BaseRecognitionError {
message: "".to_string(),
offending_token,
offending_state: recog.get_state(),
states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(), },
start_token,
}
}
}
#[derive(Debug, Clone)]
pub struct InputMisMatchError {
pub(crate) base: BaseRecognitionError,
}
impl InputMisMatchError {
pub fn new<'a, T: Parser<'a>>(recognizer: &mut T) -> InputMisMatchError {
InputMisMatchError {
base: BaseRecognitionError::new(recognizer),
}
}
pub fn with_state<'a, T: Parser<'a>>(
recognizer: &mut T,
offending_state: isize,
ctx: Rc<<T::Node as ParserNodeType<'a>>::Type>,
) -> InputMisMatchError {
let mut a = Self::new(recognizer);
a.base.offending_state = offending_state;
a.base.states_stack = states_stack(ctx).collect();
a
}
}
#[derive(Debug, Clone)]
pub struct FailedPredicateError {
pub(crate) base: BaseRecognitionError,
rule_index: isize,
predicate_index: isize,
predicate: String,
}
impl FailedPredicateError {
pub fn new<'a, T: Parser<'a>>(
recog: &mut T,
predicate: Option<String>,
msg: Option<String>,
) -> ANTLRError {
let tr = recog.get_interpreter().atn().states[recog.get_state() as usize]
.get_transitions()
.first()
.unwrap();
let (rule_index, predicate_index) = if tr.get_serialization_type() == TRANSITION_PREDICATE {
let pr = tr.deref().cast::<PredicateTransition>();
(pr.rule_index, pr.pred_index)
} else {
(0, 0)
};
ANTLRError::PredicateError(FailedPredicateError {
base: BaseRecognitionError {
message: msg.unwrap_or_else(|| {
format!(
"failed predicate: {}",
predicate.as_deref().unwrap_or("None")
)
}),
offending_token: recog.get_current_token().borrow().to_owned(),
offending_state: recog.get_state(),
states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(), },
rule_index,
predicate_index,
predicate: predicate.unwrap_or_default(),
})
}
}