Skip to main content

dbt_antlr4/
errors.rs

1//! Error types
2use crate::atn_simulator::IATNSimulator;
3use crate::interval_set::IntervalSet;
4use crate::parser::Parser;
5use crate::rule_context::states_stack;
6use crate::token::{OwningToken, Token};
7use crate::token_factory::TokenFactory;
8use crate::transition::Transition;
9use std::error::Error;
10use std::fmt;
11use std::fmt::Formatter;
12use std::fmt::{Debug, Display};
13use std::ops::Deref;
14use std::sync::Arc;
15
16/// Main ANTLR4 Rust runtime error
17#[derive(Debug, Clone)]
18pub enum ANTLRErrorKind {
19    /// Returned from Lexer when it fails to find matching token type for current input
20    ///
21    /// Usually Lexers contain last rule that captures all invalid tokens like:
22    /// ```text
23    /// ERROR_TOKEN: . ;
24    /// ```
25    /// to prevent lexer from throwing errors and have all error handling in parser.
26    LexerNoAltError {
27        /// Index at which error has happened
28        start_index: isize,
29    },
30
31    /// Indicates that the parser could not decide which of two or more paths
32    /// to take based upon the remaining input. It tracks the starting token
33    /// of the offending input and also knows where the parser was
34    /// in the various paths when the error. Reported by reportNoViableAlternative()
35    NoAltError(NoViableAltError),
36
37    /// This signifies any kind of mismatched input exceptions such as
38    /// when the current input does not match the expected token.
39    InputMismatchError(InputMisMatchError),
40
41    /// A semantic predicate failed during validation. Validation of predicates
42    /// occurs when normally parsing the alternative just like matching a token.
43    /// Disambiguating predicate evaluation occurs when we test a predicate during
44    /// prediction.
45    PredicateError(FailedPredicateError),
46
47    /// Internal error. Or user provided type returned data that is
48    /// incompatible with current parser state
49    IllegalStateError(String),
50
51    CustomError(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#[derive(Debug, Clone)]
64pub struct ANTLRError(pub Box<ANTLRErrorKind>);
65
66impl Display for ANTLRError {
67    fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
68        <Self as Debug>::fmt(self, _f)
69    }
70}
71
72impl Error for ANTLRError {
73    fn source(&self) -> Option<&(dyn Error + 'static)> {
74        match self.0.as_ref() {
75            ANTLRErrorKind::FallThrough(x) => Some(x.as_ref()),
76            ANTLRErrorKind::OtherError(x) => Some(x.as_ref()),
77            _ => None,
78        }
79    }
80}
81
82impl From<ANTLRErrorKind> for ANTLRError {
83    fn from(value: ANTLRErrorKind) -> Self {
84        ANTLRError(Box::new(value))
85    }
86}
87
88impl From<Box<dyn Error + Send + Sync + 'static>> for ANTLRError {
89    fn from(value: Box<dyn Error + Send + Sync + 'static>) -> Self {
90        ANTLRErrorKind::OtherError(Arc::from(value)).into()
91    }
92}
93
94impl AsRef<ANTLRErrorKind> for ANTLRError {
95    fn as_ref(&self) -> &ANTLRErrorKind {
96        self.0.as_ref()
97    }
98}
99
100impl Deref for ANTLRError {
101    type Target = ANTLRErrorKind;
102
103    fn deref(&self) -> &Self::Target {
104        self.0.as_ref()
105    }
106}
107
108impl ANTLRError {
109    pub fn custom_error(msg: String) -> Self {
110        ANTLRErrorKind::CustomError(msg).into()
111    }
112
113    pub fn lexer_no_alt(start_index: isize) -> Self {
114        ANTLRErrorKind::LexerNoAltError { start_index }.into()
115    }
116
117    pub fn illegal_state(msg: String) -> Self {
118        ANTLRErrorKind::IllegalStateError(msg).into()
119    }
120
121    pub fn fall_through<E: Error + Send + Sync + 'static>(err: E) -> Self {
122        ANTLRErrorKind::FallThrough(Arc::new(err)).into()
123    }
124
125    pub fn no_alt<'input, 'arena, TF, P>(recog: &mut P) -> Self
126    where
127        'input: 'arena,
128        TF: TokenFactory<'input, 'arena> + 'arena,
129        P: Parser<'input, 'arena, TF>,
130    {
131        ANTLRErrorKind::NoAltError(NoViableAltError {
132            base: BaseRecognitionError {
133                message: "".to_string(),
134                offending_token: OwningToken::from(recog.get_current_token() as &dyn Token),
135                offending_state: recog.get_state(),
136                // ctx: recog.get_parser_rule_context().clone(),
137                states_stack: states_stack(recog.get_current_context()).collect(),
138            },
139            start_token: OwningToken::from(recog.get_current_token() as &dyn Token),
140            //            ctx: recog.get_parser_rule_context().clone()
141        })
142        .into()
143    }
144
145    pub fn no_alt_full<'input, 'arena, TF, P>(
146        recog: &mut P,
147        start_token: OwningToken,
148        offending_token: OwningToken,
149    ) -> Self
150    where
151        'input: 'arena,
152        TF: TokenFactory<'input, 'arena> + 'arena,
153        P: Parser<'input, 'arena, TF>,
154    {
155        ANTLRErrorKind::NoAltError(NoViableAltError {
156            base: BaseRecognitionError {
157                message: "".to_string(),
158                offending_token,
159                offending_state: recog.get_state(),
160                states_stack: states_stack(recog.get_current_context()).collect(), // ctx: recog.get_parser_rule_context().clone(),
161            },
162            start_token,
163            //            ctx
164        })
165        .into()
166    }
167
168    pub fn input_mismatch<'input, 'arena, TF, P>(recognizer: &mut P) -> Self
169    where
170        'input: 'arena,
171        TF: TokenFactory<'input, 'arena> + 'arena,
172        P: Parser<'input, 'arena, TF>,
173    {
174        ANTLRErrorKind::InputMismatchError(InputMisMatchError {
175            base: BaseRecognitionError::new(recognizer),
176        })
177        .into()
178    }
179
180    pub fn input_mismatch_with_state<'input, 'arena, TF, P>(
181        recognizer: &mut P,
182        offending_state: i32,
183        ctx: &'arena P::Node,
184    ) -> Self
185    where
186        'input: 'arena,
187        TF: TokenFactory<'input, 'arena> + 'arena,
188        P: Parser<'input, 'arena, TF>,
189    {
190        let mut a = InputMisMatchError {
191            base: BaseRecognitionError::new(recognizer),
192        };
193        // a.base.ctx = ctx;
194        a.base.offending_state = offending_state;
195        a.base.states_stack = states_stack(ctx).collect();
196        ANTLRErrorKind::InputMismatchError(a).into()
197    }
198
199    pub fn failed_predicate<'input, 'arena, TF, P>(
200        recog: &mut P,
201        predicate: Option<String>,
202        msg: Option<String>,
203    ) -> Self
204    where
205        'input: 'arena,
206        TF: TokenFactory<'input, 'arena> + 'arena,
207        P: Parser<'input, 'arena, TF>,
208    {
209        let tr = recog
210            .get_interpreter()
211            .atn()
212            .get_state(recog.get_state())
213            .get_transitions()
214            .first()
215            .unwrap();
216        let (rule_index, _) = if let Transition::Predicate(pr) = tr {
217            (pr.rule_index, pr.pred_index)
218        } else {
219            (0, 0)
220        };
221
222        ANTLRErrorKind::PredicateError(FailedPredicateError {
223            base: BaseRecognitionError {
224                message: msg.unwrap_or_else(|| {
225                    format!(
226                        "failed predicate: {}",
227                        predicate.as_deref().unwrap_or("None")
228                    )
229                }),
230                offending_token: OwningToken::from(recog.get_current_token() as &dyn Token),
231                offending_state: recog.get_state(),
232                states_stack: states_stack(recog.get_current_context()).collect(), // ctx: recog.get_parser_rule_context().clone()
233            },
234            rule_index,
235            predicate: predicate.unwrap_or_default(),
236        })
237        .into()
238    }
239
240    pub fn is_recoverable(&self) -> bool {
241        !matches!(self.0.as_ref(), ANTLRErrorKind::FallThrough(_))
242    }
243
244    /// Returns first token that caused parser to fail.
245    pub fn get_offending_token(&self) -> Option<&OwningToken> {
246        Some(match self.0.as_ref() {
247            ANTLRErrorKind::NoAltError(e) => &e.base.offending_token,
248            ANTLRErrorKind::InputMismatchError(e) => &e.base.offending_token,
249            ANTLRErrorKind::PredicateError(e) => &e.base.offending_token,
250            _ => return None,
251        })
252    }
253}
254
255//impl ANTLRError {
256//    fn get_expected_tokens(&self, _atn: &ATN) -> IntervalSet {
257//        atn.get_expected_tokens(se)
258//        unimplemented!()
259//    }
260//}
261
262/// Common part of ANTLR parser errors
263#[derive(Debug, Clone)]
264#[allow(missing_docs)]
265pub struct BaseRecognitionError {
266    pub message: String,
267    //    recognizer: Box<Recognizer>,
268    pub offending_token: OwningToken,
269    pub offending_state: i32,
270    states_stack: Vec<i32>, // ctx: Rc<dyn ParserRuleContext>
271                            //    input: Box<IntStream>
272}
273
274impl BaseRecognitionError {
275    /// Returns tokens that were expected by parser in error place
276    pub fn get_expected_tokens<'input, 'arena, TF, P>(&self, recognizer: &P) -> IntervalSet
277    where
278        'input: 'arena,
279        TF: TokenFactory<'input, 'arena> + 'arena,
280        P: Parser<'input, 'arena, TF>,
281    {
282        recognizer
283            .get_interpreter()
284            .atn()
285            .get_expected_tokens(self.offending_state, self.states_stack.iter().copied())
286    }
287
288    fn new<'input, 'arena, TF, P>(recog: &mut P) -> BaseRecognitionError
289    where
290        'input: 'arena,
291        TF: TokenFactory<'input, 'arena> + 'arena,
292        P: Parser<'input, 'arena, TF>,
293    {
294        BaseRecognitionError {
295            message: "".to_string(),
296            offending_token: OwningToken::from(recog.get_current_token() as &dyn Token),
297            offending_state: recog.get_state(),
298            // ctx: recog.get_parser_rule_context().clone(),
299            states_stack: states_stack(recog.get_current_context()).collect(),
300        }
301    }
302}
303
304/// See `ANTLRError::NoAltError`
305#[derive(Debug, Clone)]
306#[allow(missing_docs)]
307pub struct NoViableAltError {
308    pub base: BaseRecognitionError,
309    pub start_token: OwningToken,
310    //    ctx: Rc<dyn ParserRuleContext>,
311    //    dead_end_configs: BaseATNConfigSet,
312}
313
314/// See `ANTLRError::InputMismatchError`
315#[derive(Debug, Clone)]
316#[allow(missing_docs)]
317pub struct InputMisMatchError {
318    pub base: BaseRecognitionError,
319}
320
321/// See `ANTLRError::PredicateError`
322#[derive(Debug, Clone)]
323#[allow(missing_docs)]
324pub struct FailedPredicateError {
325    pub base: BaseRecognitionError,
326    pub rule_index: i32,
327    pub predicate: String,
328}