Skip to main content

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