antlr4rust/
errors.rs

1//! Error types
2use crate::atn_simulator::IATNSimulator;
3use crate::interval_set::IntervalSet;
4use crate::parser::{Parser, ParserNodeType};
5use crate::rule_context::states_stack;
6use crate::token::{OwningToken, Token};
7use crate::transition::PredicateTransition;
8use crate::transition::TransitionType::TRANSITION_PREDICATE;
9use std::borrow::Borrow;
10use std::error::Error;
11use std::fmt;
12use std::fmt::Formatter;
13use std::fmt::{Debug, Display};
14use std::ops::Deref;
15use std::rc::Rc;
16use std::sync::Arc;
17
18/// Main ANTLR4 Rust runtime error
19#[derive(Debug, Clone)]
20pub enum ANTLRError {
21    /// Returned from Lexer when it fails to find matching token type for current input
22    ///
23    /// Usually Lexers contain last rule that captures all invalid tokens like:
24    /// ```text
25    /// ERROR_TOKEN: . ;
26    /// ```
27    /// to prevent lexer from throwing errors and have all error handling in parser.
28    LexerNoAltError {
29        /// Index at which error has happened
30        start_index: isize,
31    },
32
33    /// Indicates that the parser could not decide which of two or more paths
34    /// to take based upon the remaining input. It tracks the starting token
35    /// of the offending input and also knows where the parser was
36    /// in the various paths when the error. Reported by reportNoViableAlternative()
37    NoAltError(NoViableAltError),
38
39    /// This signifies any kind of mismatched input exceptions such as
40    /// when the current input does not match the expected token.
41    InputMismatchError(InputMisMatchError),
42
43    /// A semantic predicate failed during validation. Validation of predicates
44    /// occurs when normally parsing the alternative just like matching a token.
45    /// Disambiguating predicate evaluation occurs when we test a predicate during
46    /// prediction.
47    PredicateError(FailedPredicateError),
48
49    /// Internal error. Or user provided type returned data that is
50    /// incompatible with current parser state
51    IllegalStateError(String),
52
53    /// Unrecoverable error. Indicates that error should not be processed by parser/error strategy
54    /// and it should abort parsing and immediately return to caller.
55    FallThrough(Arc<dyn Error + Send + Sync + 'static>),
56
57    /// Potentially recoverable error.
58    /// Used to allow user to emit his own errors from parser actions or from custom error strategy.
59    /// Parser will try to recover with provided `ErrorStrategy`
60    OtherError(Arc<dyn Error + Send + Sync + 'static>),
61}
62
63// impl Clone for ANTLRError {
64//     fn clone(&self) -> Self {
65//         match self {
66//             ANTLRError::LexerNoAltError { start_index } => ANTLRError::LexerNoAltError {
67//                 start_index: *start_index,
68//             },
69//             ANTLRError::NoAltError(e) => ANTLRError::NoAltError(e.clone()),
70//             ANTLRError::InputMismatchError(e) => ANTLRError::InputMismatchError(e.clone()),
71//             ANTLRError::PredicateError(e) => ANTLRError::PredicateError(e.clone()),
72//             ANTLRError::IllegalStateError(e) => ANTLRError::IllegalStateError(e.clone()),
73//             ANTLRError::FallThrough(_) => panic!("clone not supported"),
74//             ANTLRError::OtherError(_) => panic!("clone not supported"),
75//         }
76//     }
77// }
78
79impl Display for ANTLRError {
80    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
81        <Self as Debug>::fmt(self, _f)
82    }
83}
84
85impl Error for ANTLRError {
86    fn source(&self) -> Option<&(dyn Error + 'static)> {
87        match self {
88            ANTLRError::FallThrough(x) => Some(x.as_ref()),
89            ANTLRError::OtherError(x) => Some(x.as_ref()),
90            _ => None,
91        }
92    }
93}
94
95impl ANTLRError {
96    /// Returns first token that caused parser to fail.
97    pub fn get_offending_token(&self) -> Option<&OwningToken> {
98        Some(match self {
99            ANTLRError::NoAltError(e) => &e.base.offending_token,
100            ANTLRError::InputMismatchError(e) => &e.base.offending_token,
101            ANTLRError::PredicateError(e) => &e.base.offending_token,
102            _ => return None,
103        })
104    }
105}
106
107//impl ANTLRError {
108//    fn get_expected_tokens(&self, _atn: &ATN) -> IntervalSet {
109//        atn.get_expected_tokens(se)
110//        unimplemented!()
111//    }
112//}
113
114/// Common part of ANTLR parser errors
115#[derive(Debug, Clone)]
116#[allow(missing_docs)]
117pub struct BaseRecognitionError {
118    pub message: String,
119    //    recognizer: Box<Recognizer>,
120    pub offending_token: OwningToken,
121    pub offending_state: i32,
122    states_stack: Vec<i32>, // ctx: Rc<dyn ParserRuleContext>
123                              //    input: Box<IntStream>
124}
125
126impl BaseRecognitionError {
127    /// Returns tokens that were expected by parser in error place
128    pub fn get_expected_tokens<'a, T: Parser<'a>>(&self, recognizer: &T) -> IntervalSet {
129        recognizer
130            .get_interpreter()
131            .atn()
132            .get_expected_tokens(self.offending_state, self.states_stack.iter().copied())
133    }
134
135    fn new<'a, T: Parser<'a>>(recog: &mut T) -> BaseRecognitionError {
136        BaseRecognitionError {
137            message: "".to_string(),
138            offending_token: recog.get_current_token().borrow().to_owned(),
139            offending_state: recog.get_state(),
140            // ctx: recog.get_parser_rule_context().clone(),
141            states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(),
142        }
143    }
144}
145
146/// See `ANTLRError::NoAltError`
147#[derive(Debug, Clone)]
148#[allow(missing_docs)]
149pub struct NoViableAltError {
150    pub base: BaseRecognitionError,
151    pub start_token: OwningToken,
152    //    ctx: Rc<dyn ParserRuleContext>,
153    //    dead_end_configs: BaseATNConfigSet,
154}
155
156#[allow(missing_docs)]
157impl NoViableAltError {
158    pub fn new<'a, T: Parser<'a>>(recog: &mut T) -> NoViableAltError {
159        Self {
160            base: BaseRecognitionError {
161                message: "".to_string(),
162                offending_token: recog.get_current_token().borrow().to_owned(),
163                offending_state: recog.get_state(),
164                // ctx: recog.get_parser_rule_context().clone(),
165                states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(),
166            },
167            start_token: recog.get_current_token().borrow().to_owned(),
168            //            ctx: recog.get_parser_rule_context().clone()
169        }
170    }
171    pub fn new_full<'a, T: Parser<'a>>(
172        recog: &mut T,
173        start_token: OwningToken,
174        offending_token: OwningToken,
175    ) -> NoViableAltError {
176        Self {
177            base: BaseRecognitionError {
178                message: "".to_string(),
179                offending_token,
180                offending_state: recog.get_state(),
181                states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(), // ctx: recog.get_parser_rule_context().clone(),
182            },
183            start_token,
184            //            ctx
185        }
186    }
187}
188
189/// See `ANTLRError::InputMismatchError`
190#[derive(Debug, Clone)]
191#[allow(missing_docs)]
192pub struct InputMisMatchError {
193    pub base: BaseRecognitionError,
194}
195
196#[allow(missing_docs)]
197impl InputMisMatchError {
198    pub fn new<'a, T: Parser<'a>>(recognizer: &mut T) -> InputMisMatchError {
199        InputMisMatchError {
200            base: BaseRecognitionError::new(recognizer),
201        }
202    }
203
204    pub fn with_state<'a, T: Parser<'a>>(
205        recognizer: &mut T,
206        offending_state: i32,
207        ctx: Rc<<T::Node as ParserNodeType<'a>>::Type>,
208    ) -> InputMisMatchError {
209        let mut a = Self::new(recognizer);
210        // a.base.ctx = ctx;
211        a.base.offending_state = offending_state;
212        a.base.states_stack = states_stack(ctx).collect();
213        a
214    }
215}
216
217//fn new_input_mis_match_exception(recognizer: Parser) -> InputMisMatchError { unimplemented!() }
218
219/// See `ANTLRError::PredicateError`
220#[derive(Debug, Clone)]
221#[allow(missing_docs)]
222pub struct FailedPredicateError {
223    pub base: BaseRecognitionError,
224    pub rule_index: i32,
225    pub predicate: String,
226}
227
228#[allow(missing_docs)]
229impl FailedPredicateError {
230    pub fn new<'a, T: Parser<'a>>(
231        recog: &mut T,
232        predicate: Option<String>,
233        msg: Option<String>,
234    ) -> ANTLRError {
235        let tr = recog.get_interpreter().atn().states[recog.get_state() as usize]
236            .get_transitions()
237            .first()
238            .unwrap();
239        let (rule_index, _) = if tr.get_serialization_type() == TRANSITION_PREDICATE {
240            let pr = tr.deref().cast::<PredicateTransition>();
241            (pr.rule_index, pr.pred_index)
242        } else {
243            (0, 0)
244        };
245
246        ANTLRError::PredicateError(FailedPredicateError {
247            base: BaseRecognitionError {
248                message: msg.unwrap_or_else(|| {
249                    format!(
250                        "failed predicate: {}",
251                        predicate.as_deref().unwrap_or("None")
252                    )
253                }),
254                offending_token: recog.get_current_token().borrow().to_owned(),
255                offending_state: recog.get_state(),
256                states_stack: states_stack(recog.get_parser_rule_context().clone()).collect(), // ctx: recog.get_parser_rule_context().clone()
257            },
258            rule_index,
259            predicate: predicate.unwrap_or_default(),
260        })
261    }
262}