antlr_rust_sleagon/
error_strategy.rs

1//! Error handling and recovery
2use std::borrow::Borrow;
3use std::error::Error;
4use std::fmt;
5use std::fmt::{Display, Formatter};
6use std::ops::{Deref, DerefMut};
7use std::rc::Rc;
8
9use crate::atn_simulator::IATNSimulator;
10use crate::atn_state::*;
11use crate::char_stream::{CharStream, InputData};
12use crate::dfa::ScopeExt;
13use crate::errors::{ANTLRError, FailedPredicateError, InputMisMatchError, NoViableAltError};
14use crate::interval_set::IntervalSet;
15use crate::parser::{Parser, ParserNodeType};
16use crate::parser_rule_context::ParserRuleContext;
17use crate::rule_context::{CustomRuleContext, RuleContext};
18use crate::token::{Token, TOKEN_DEFAULT_CHANNEL, TOKEN_EOF, TOKEN_EPSILON, TOKEN_INVALID_TYPE};
19use crate::token_factory::TokenFactory;
20use crate::transition::RuleTransition;
21use crate::tree::Tree;
22use crate::utils::escape_whitespaces;
23use better_any::{Tid, TidAble};
24
25/// The interface for defining strategies to deal with syntax errors encountered
26/// during a parse by ANTLR-generated parsers. We distinguish between three
27/// different kinds of errors:
28///  - The parser could not figure out which path to take in the ATN (none of
29/// the available alternatives could possibly match)
30///  - The current input does not match what we were looking for
31///  - A predicate evaluated to false
32///
33/// Implementations of this interface should report syntax errors by calling [`Parser::notifyErrorListeners`]
34///
35/// [`Parser::notifyErrorListeners`]: crate::parser::Parser::notifyErrorListeners
36pub trait ErrorStrategy<'a, T: Parser<'a>>: Tid<'a> {
37    ///Reset the error handler state for the specified `recognizer`.
38    fn reset(&mut self, recognizer: &mut T);
39
40    /// This method is called when an unexpected symbol is encountered during an
41    /// inline match operation, such as `Parser::match`. If the error
42    /// strategy successfully recovers from the match failure, this method
43    /// returns the `Token` instance which should be treated as the
44    /// successful result of the match.
45    ///
46    /// This method handles the consumption of any tokens - the caller should
47    /// **not** call `Parser::consume` after a successful recovery.
48    ///
49    /// Note that the calling code will not report an error if this method
50    /// returns successfully. The error strategy implementation is responsible
51    /// for calling `Parser::notifyErrorListeners` as appropriate.
52    ///
53    /// Returns `ANTLRError` if can't recover from unexpected input symbol
54    fn recover_inline(
55        &mut self,
56        recognizer: &mut T,
57    ) -> Result<<T::TF as TokenFactory<'a>>::Tok, ANTLRError>;
58
59    /// This method is called to recover from error `e`. This method is
60    /// called after `ErrorStrategy::reportError` by the default error handler
61    /// generated for a rule method.
62    ///
63    ///
64    fn recover(&mut self, recognizer: &mut T, e: &ANTLRError) -> Result<(), ANTLRError>;
65
66    /// This method provides the error handler with an opportunity to handle
67    /// syntactic or semantic errors in the input stream before they result in a
68    /// error.
69    ///
70    /// The generated code currently contains calls to `ErrorStrategy::sync` after
71    /// entering the decision state of a closure block ({@code (...)*} or
72    /// {@code (...)+}).</p>
73    fn sync(&mut self, recognizer: &mut T) -> Result<(), ANTLRError>;
74
75    /// Tests whether or not {@code recognizer} is in the process of recovering
76    /// from an error. In error recovery mode, `Parser::consume` will create
77    /// `ErrorNode` leaf instead of `TerminalNode` one  
78    fn in_error_recovery_mode(&mut self, recognizer: &mut T) -> bool;
79
80    /// Report any kind of `ANTLRError`. This method is called by
81    /// the default exception handler generated for a rule method.
82    fn report_error(&mut self, recognizer: &mut T, e: &ANTLRError);
83
84    /// This method is called when the parser successfully matches an input
85    /// symbol.
86    fn report_match(&mut self, recognizer: &mut T);
87}
88//
89// impl<'a, T: Parser<'a>> Default for Box<dyn ErrorStrategy<'a, T> + 'a> {
90//     fn default() -> Self { Box::new(DefaultErrorStrategy::new()) }
91// }
92//
93// /// Error strategy trait object if there is a need to change error strategy at runtime
94// /// Supports downcasting.
95// pub type DynHandler<'a, T> = Box<dyn ErrorStrategy<'a, T> + 'a>;
96
97// impl<'a, T: Parser<'a> + TidAble<'a>> TidAble<'a> for Box<dyn ErrorStrategy<'a, T> + 'a> {}
98better_any::tid! { impl<'a, T> TidAble<'a> for Box<dyn ErrorStrategy<'a, T> + 'a> where T: Parser<'a>}
99
100impl<'a, T: Parser<'a> + TidAble<'a>> ErrorStrategy<'a, T> for Box<dyn ErrorStrategy<'a, T> + 'a> {
101    #[inline(always)]
102    fn reset(&mut self, recognizer: &mut T) {
103        self.deref_mut().reset(recognizer)
104    }
105
106    #[inline(always)]
107    fn recover_inline(
108        &mut self,
109        recognizer: &mut T,
110    ) -> Result<<T::TF as TokenFactory<'a>>::Tok, ANTLRError> {
111        self.deref_mut().recover_inline(recognizer)
112    }
113
114    #[inline(always)]
115    fn recover(&mut self, recognizer: &mut T, e: &ANTLRError) -> Result<(), ANTLRError> {
116        self.deref_mut().recover(recognizer, e)
117    }
118
119    #[inline(always)]
120    fn sync(&mut self, recognizer: &mut T) -> Result<(), ANTLRError> {
121        self.deref_mut().sync(recognizer)
122    }
123
124    #[inline(always)]
125    fn in_error_recovery_mode(&mut self, recognizer: &mut T) -> bool {
126        self.deref_mut().in_error_recovery_mode(recognizer)
127    }
128
129    #[inline(always)]
130    fn report_error(&mut self, recognizer: &mut T, e: &ANTLRError) {
131        self.deref_mut().report_error(recognizer, e)
132    }
133
134    #[inline(always)]
135    fn report_match(&mut self, recognizer: &mut T) {
136        self.deref_mut().report_match(recognizer)
137    }
138}
139
140/// This is the default implementation of `ErrorStrategy` used for
141/// error reporting and recovery in ANTLR parsers.
142#[derive(Debug)]
143pub struct DefaultErrorStrategy<'input, Ctx: ParserNodeType<'input>> {
144    error_recovery_mode: bool,
145    last_error_index: isize,
146    last_error_states: Option<IntervalSet>,
147    next_tokens_state: isize,
148    next_tokens_ctx: Option<Rc<Ctx::Type>>,
149}
150
151better_any::tid! { impl<'i,Ctx> TidAble<'i> for DefaultErrorStrategy<'i,Ctx> where Ctx: ParserNodeType<'i>}
152
153impl<'input, Ctx: ParserNodeType<'input>> Default for DefaultErrorStrategy<'input, Ctx> {
154    fn default() -> Self {
155        Self::new()
156    }
157}
158
159impl<'input, Ctx: ParserNodeType<'input>> DefaultErrorStrategy<'input, Ctx> {
160    /// Creates new instance of `DefaultErrorStrategy`
161    pub fn new() -> Self {
162        Self {
163            error_recovery_mode: false,
164            last_error_index: -1,
165            last_error_states: None,
166            next_tokens_state: ATNSTATE_INVALID_STATE_NUMBER,
167            next_tokens_ctx: None,
168        }
169    }
170
171    fn begin_error_condition<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
172        &mut self,
173        _recognizer: &T,
174    ) {
175        self.error_recovery_mode = true;
176    }
177
178    fn end_error_condition<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
179        &mut self,
180        _recognizer: &T,
181    ) {
182        self.error_recovery_mode = false;
183        self.last_error_index = -1;
184        self.last_error_states = None;
185    }
186
187    fn report_no_viable_alternative<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
188        &self,
189        recognizer: &mut T,
190        e: &NoViableAltError,
191    ) -> String {
192        let input = if e.start_token.token_type == TOKEN_EOF {
193            "<EOF>".to_owned()
194        } else {
195            recognizer.get_input_stream_mut().get_text_from_interval(
196                e.start_token.get_token_index(),
197                e.base.offending_token.get_token_index(),
198            )
199        };
200
201        format!("no viable alternative at input '{}'", input)
202    }
203
204    fn report_input_mismatch<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
205        &self,
206        recognizer: &T,
207        e: &InputMisMatchError,
208    ) -> String {
209        format!(
210            "mismatched input {} expecting {}",
211            self.get_token_error_display(&e.base.offending_token),
212            e.base
213                .get_expected_tokens(recognizer)
214                .to_token_string(recognizer.get_vocabulary())
215        )
216    }
217
218    fn report_failed_predicate<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
219        &self,
220        recognizer: &T,
221        e: &FailedPredicateError,
222    ) -> String {
223        format!(
224            "rule {} {}",
225            recognizer.get_rule_names()[recognizer.get_parser_rule_context().get_rule_index()],
226            e.base.message
227        )
228    }
229
230    fn report_unwanted_token<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
231        &mut self,
232        recognizer: &mut T,
233    ) {
234        if self.in_error_recovery_mode(recognizer) {
235            return;
236        }
237
238        self.begin_error_condition(recognizer);
239        let expecting = self.get_expected_tokens(recognizer);
240        let expecting = expecting.to_token_string(recognizer.get_vocabulary());
241        let t = recognizer.get_current_token().borrow();
242        let token_name = self.get_token_error_display(t);
243        let msg = format!("extraneous input {} expecting {}", token_name, expecting);
244        let t = t.get_token_index();
245        recognizer.notify_error_listeners(msg, Some(t), None);
246    }
247
248    fn report_missing_token<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
249        &mut self,
250        recognizer: &mut T,
251    ) {
252        if self.in_error_recovery_mode(recognizer) {
253            return;
254        }
255
256        self.begin_error_condition(recognizer);
257        let expecting = self.get_expected_tokens(recognizer);
258        let expecting = expecting.to_token_string(recognizer.get_vocabulary());
259        let t = recognizer.get_current_token().borrow();
260        let _token_name = self.get_token_error_display(t);
261        let msg = format!(
262            "missing {} at {}",
263            expecting,
264            self.get_token_error_display(t)
265        );
266        let t = t.get_token_index();
267        recognizer.notify_error_listeners(msg, Some(t), None);
268    }
269
270    fn single_token_insertion<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
271        &mut self,
272        recognizer: &mut T,
273    ) -> bool {
274        let current_token = recognizer.get_input_stream_mut().la(1);
275
276        let atn = recognizer.get_interpreter().atn();
277        let current_state = atn.states[recognizer.get_state() as usize].as_ref();
278        let next = current_state
279            .get_transitions()
280            .first()
281            .unwrap()
282            .get_target();
283        let expect_at_ll2 = atn.next_tokens_in_ctx::<Ctx>(
284            atn.states[next].as_ref(),
285            Some(recognizer.get_parser_rule_context().deref()),
286        );
287        if expect_at_ll2.contains(current_token) {
288            self.report_missing_token(recognizer);
289            return true;
290        }
291        false
292    }
293
294    fn single_token_deletion<'a, T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
295        &mut self,
296        recognizer: &'a mut T,
297    ) -> Option<&'a <T::TF as TokenFactory<'input>>::Tok> {
298        let next_token_type = recognizer.get_input_stream_mut().la(2);
299        let expecting = self.get_expected_tokens(recognizer);
300        //        println!("expecting {}", expecting.to_token_string(recognizer.get_vocabulary()));
301        if expecting.contains(next_token_type) {
302            self.report_unwanted_token(recognizer);
303            recognizer.consume(self);
304            self.report_match(recognizer);
305            let matched_symbol = recognizer.get_current_token();
306            return Some(matched_symbol);
307        }
308        None
309    }
310
311    fn get_missing_symbol<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
312        &self,
313        recognizer: &mut T,
314    ) -> <T::TF as TokenFactory<'input>>::Tok {
315        let expected = self.get_expected_tokens(recognizer);
316        let expected_token_type = expected.get_min().unwrap_or(TOKEN_INVALID_TYPE);
317        let token_text = if expected_token_type == TOKEN_EOF {
318            "<missing EOF>".to_owned()
319        } else {
320            format!(
321                "<missing {}>",
322                recognizer
323                    .get_vocabulary()
324                    .get_display_name(expected_token_type)
325            )
326        };
327        let token_text = <T::TF as TokenFactory<'input>>::Data::from_text(&token_text);
328        let mut curr = recognizer.get_current_token().borrow();
329        if curr.get_token_type() == TOKEN_EOF {
330            curr = recognizer
331                .get_input_stream()
332                .run(|it| it.get((it.index() - 1).max(0)).borrow());
333        }
334        let (line, column) = (curr.get_line(), curr.get_column());
335        recognizer.get_token_factory().create(
336            None::<&mut dyn CharStream<<Ctx::TF as TokenFactory<'input>>::From>>,
337            expected_token_type,
338            Some(token_text),
339            TOKEN_DEFAULT_CHANNEL,
340            -1,
341            -1,
342            line,
343            column,
344        )
345        // Token::to_owned(token.borrow())
346        // .modify_with(|it| it.text = token_text)
347    }
348
349    fn get_expected_tokens<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
350        &self,
351        recognizer: &T,
352    ) -> IntervalSet {
353        recognizer.get_expected_tokens()
354    }
355
356    fn get_token_error_display<T: Token + ?Sized>(&self, t: &T) -> String {
357        let text = t.get_text().to_display();
358        self.escape_ws_and_quote(&text)
359    }
360
361    fn escape_ws_and_quote(&self, s: &str) -> String {
362        format!("'{}'", escape_whitespaces(s, false))
363    }
364
365    fn get_error_recovery_set<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
366        &self,
367        recognizer: &T,
368    ) -> IntervalSet {
369        let atn = recognizer.get_interpreter().atn();
370        let mut ctx = Some(recognizer.get_parser_rule_context().clone());
371        let mut recover_set = IntervalSet::new();
372        while let Some(c) = ctx {
373            if c.get_invoking_state() < 0 {
374                break;
375            }
376
377            let invoking_state = atn.states[c.get_invoking_state() as usize].as_ref();
378            let tr = invoking_state.get_transitions().first().unwrap().as_ref();
379            let tr = tr.cast::<RuleTransition>();
380            let follow = atn.next_tokens(atn.states[tr.follow_state].as_ref());
381            recover_set.add_set(follow);
382            ctx = c.get_parent_ctx();
383        }
384        recover_set.remove_one(TOKEN_EPSILON);
385        return recover_set;
386    }
387
388    fn consume_until<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
389        &mut self,
390        recognizer: &mut T,
391        set: &IntervalSet,
392    ) {
393        let mut ttype = recognizer.get_input_stream_mut().la(1);
394        while ttype != TOKEN_EOF && !set.contains(ttype) {
395            recognizer.consume(self);
396            ttype = recognizer.get_input_stream_mut().la(1);
397        }
398    }
399}
400
401impl<'a, T: Parser<'a>> ErrorStrategy<'a, T> for DefaultErrorStrategy<'a, T::Node> {
402    fn reset(&mut self, recognizer: &mut T) {
403        self.end_error_condition(recognizer)
404    }
405
406    fn recover_inline(
407        &mut self,
408        recognizer: &mut T,
409    ) -> Result<<T::TF as TokenFactory<'a>>::Tok, ANTLRError> {
410        let t = self
411            .single_token_deletion(recognizer)
412            .map(|it| it.to_owned());
413        if let Some(t) = t {
414            recognizer.consume(self);
415            return Ok(t);
416        }
417
418        if self.single_token_insertion(recognizer) {
419            return Ok(self.get_missing_symbol(recognizer));
420        }
421
422        if let Some(next_tokens_ctx) = &self.next_tokens_ctx {
423            Err(ANTLRError::InputMismatchError(
424                InputMisMatchError::with_state(
425                    recognizer,
426                    self.next_tokens_state,
427                    next_tokens_ctx.clone(),
428                ),
429            ))
430        } else {
431            Err(ANTLRError::InputMismatchError(InputMisMatchError::new(
432                recognizer,
433            )))
434        }
435        //        Err(ANTLRError::IllegalStateError("aaa".to_string()))
436    }
437
438    fn recover(&mut self, recognizer: &mut T, _e: &ANTLRError) -> Result<(), ANTLRError> {
439        if self.last_error_index == recognizer.get_input_stream_mut().index()
440            && self.last_error_states.is_some()
441            && self
442                .last_error_states
443                .as_ref()
444                .unwrap()
445                .contains(recognizer.get_state())
446        {
447            recognizer.consume(self)
448        }
449
450        self.last_error_index = recognizer.get_input_stream_mut().index();
451        self.last_error_states
452            .get_or_insert(IntervalSet::new())
453            .apply(|x| x.add_one(recognizer.get_state()));
454        let follow_set = self.get_error_recovery_set(recognizer);
455        self.consume_until(recognizer, &follow_set);
456        Ok(())
457    }
458
459    fn sync(&mut self, recognizer: &mut T) -> Result<(), ANTLRError> {
460        if self.in_error_recovery_mode(recognizer) {
461            return Ok(());
462        }
463        let next = recognizer.get_input_stream_mut().la(1);
464        let state =
465            recognizer.get_interpreter().atn().states[recognizer.get_state() as usize].as_ref();
466
467        let next_tokens = recognizer.get_interpreter().atn().next_tokens(state);
468        //        println!("{:?}",next_tokens);
469
470        if next_tokens.contains(next) {
471            self.next_tokens_state = ATNSTATE_INVALID_STATE_NUMBER;
472            self.next_tokens_ctx = None;
473            return Ok(());
474        }
475
476        if next_tokens.contains(TOKEN_EPSILON) {
477            if self.next_tokens_ctx.is_none() {
478                self.next_tokens_state = recognizer.get_state();
479                self.next_tokens_ctx = Some(recognizer.get_parser_rule_context().clone());
480            }
481            return Ok(());
482        }
483
484        match state.get_state_type_id() {
485            ATNSTATE_BLOCK_START
486            | ATNSTATE_PLUS_BLOCK_START
487            | ATNSTATE_STAR_BLOCK_START
488            | ATNSTATE_STAR_LOOP_ENTRY => {
489                if self.single_token_deletion(recognizer).is_none() {
490                    return Err(ANTLRError::InputMismatchError(InputMisMatchError::new(
491                        recognizer,
492                    )));
493                }
494            }
495            ATNSTATE_PLUS_LOOP_BACK | ATNSTATE_STAR_LOOP_BACK => {
496                self.report_unwanted_token(recognizer);
497                let mut expecting = recognizer.get_expected_tokens();
498                expecting.add_set(&self.get_error_recovery_set(recognizer));
499                self.consume_until(recognizer, &expecting);
500            }
501            _ => panic!("invalid ANTState type id"),
502        }
503
504        Ok(())
505    }
506
507    fn in_error_recovery_mode(&mut self, _recognizer: &mut T) -> bool {
508        self.error_recovery_mode
509    }
510
511    fn report_error(&mut self, recognizer: &mut T, e: &ANTLRError) {
512        if self.in_error_recovery_mode(recognizer) {
513            return;
514        }
515
516        self.begin_error_condition(recognizer);
517        let msg = match e {
518            ANTLRError::NoAltError(e) => self.report_no_viable_alternative(recognizer, e),
519            ANTLRError::InputMismatchError(e) => self.report_input_mismatch(recognizer, e),
520            ANTLRError::PredicateError(e) => self.report_failed_predicate(recognizer, e),
521            _ => e.to_string(),
522        };
523        let offending_token_index = e.get_offending_token().map(|it| it.get_token_index());
524        recognizer.notify_error_listeners(msg, offending_token_index, Some(&e))
525    }
526
527    fn report_match(&mut self, recognizer: &mut T) {
528        self.end_error_condition(recognizer);
529        //println!("matched token succesfully {}", recognizer.get_input_stream().la(1))
530    }
531}
532
533/// This implementation of `ANTLRErrorStrategy` responds to syntax errors
534/// by immediately canceling the parse operation with a
535/// `ParseCancellationException`. The implementation ensures that the
536/// [`ParserRuleContext.exception`] field is set for all parse tree nodes
537/// that were not completed prior to encountering the error.
538///
539/// <p> This error strategy is useful in the following scenarios.</p>
540///
541///  - Two-stage parsing: This error strategy allows the first
542/// stage of two-stage parsing to immediately terminate if an error is
543/// encountered, and immediately fall back to the second stage. In addition to
544/// avoiding wasted work by attempting to recover from errors here, the empty
545/// implementation of `sync` improves the performance of
546/// the first stage.
547///  - Silent validation: When syntax errors are not being
548/// reported or logged, and the parse result is simply ignored if errors occur,
549/// the `BailErrorStrategy` avoids wasting work on recovering from errors
550/// when the result will be ignored either way.
551///
552/// # Usage
553/// ```ignore
554/// use antlr_rust::error_strategy::BailErrorStrategy;
555/// myparser.err_handler = BailErrorStrategy::new();
556/// ```
557///
558/// [`ParserRuleContext.exception`]: todo
559/// */
560#[derive(Default, Debug)]
561pub struct BailErrorStrategy<'input, Ctx: ParserNodeType<'input>>(
562    DefaultErrorStrategy<'input, Ctx>,
563);
564
565better_any::tid! {impl<'i,Ctx> TidAble<'i> for BailErrorStrategy<'i,Ctx> where Ctx:ParserNodeType<'i> }
566
567impl<'input, Ctx: ParserNodeType<'input>> BailErrorStrategy<'input, Ctx> {
568    /// Creates new instance of `BailErrorStrategy`
569    pub fn new() -> Self {
570        Self(DefaultErrorStrategy::new())
571    }
572
573    fn process_error<T: Parser<'input, Node = Ctx, TF = Ctx::TF>>(
574        &self,
575        recognizer: &mut T,
576        e: &ANTLRError,
577    ) -> ANTLRError {
578        let mut ctx = recognizer.get_parser_rule_context().clone();
579        let _: Option<()> = (|| {
580            loop {
581                ctx.set_exception(e.clone());
582                ctx = ctx.get_parent()?
583            }
584            Some(())
585        })();
586        return ANTLRError::FallThrough(Rc::new(ParseCancelledError(e.clone())));
587    }
588}
589
590/// `ANTLRError::FallThrough` Error returned `BailErrorStrategy` to bail out from parsing
591#[derive(Debug)]
592pub struct ParseCancelledError(ANTLRError);
593
594impl Error for ParseCancelledError {
595    fn source(&self) -> Option<&(dyn Error + 'static)> {
596        Some(&self.0)
597    }
598}
599
600impl Display for ParseCancelledError {
601    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
602        f.write_str("ParseCancelledError, caused by ")?;
603        self.0.fmt(f)
604    }
605}
606
607impl<'a, T: Parser<'a>> ErrorStrategy<'a, T> for BailErrorStrategy<'a, T::Node> {
608    #[inline(always)]
609    fn reset(&mut self, recognizer: &mut T) {
610        self.0.reset(recognizer)
611    }
612
613    #[cold]
614    fn recover_inline(
615        &mut self,
616        recognizer: &mut T,
617    ) -> Result<<T::TF as TokenFactory<'a>>::Tok, ANTLRError> {
618        let err = ANTLRError::InputMismatchError(InputMisMatchError::new(recognizer));
619
620        Err(self.process_error(recognizer, &err))
621    }
622
623    #[cold]
624    fn recover(&mut self, recognizer: &mut T, e: &ANTLRError) -> Result<(), ANTLRError> {
625        Err(self.process_error(recognizer, &e))
626    }
627
628    #[inline(always)]
629    fn sync(&mut self, _recognizer: &mut T) -> Result<(), ANTLRError> {
630        /* empty */
631        Ok(())
632    }
633
634    #[inline(always)]
635    fn in_error_recovery_mode(&mut self, recognizer: &mut T) -> bool {
636        self.0.in_error_recovery_mode(recognizer)
637    }
638
639    #[inline(always)]
640    fn report_error(&mut self, recognizer: &mut T, e: &ANTLRError) {
641        self.0.report_error(recognizer, e)
642    }
643
644    #[inline(always)]
645    fn report_match(&mut self, _recognizer: &mut T) {}
646}