func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token {
	MatchedSymbol := d.SingleTokenDeletion(recognizer)
	if MatchedSymbol != nil {
		recognizer.Consume()
		return MatchedSymbol
	}
	if d.SingleTokenInsertion(recognizer) {
		return d.GetMissingSymbol(recognizer)
	}
	panic(NewInputMisMatchException(recognizer))
}
<p>The default implementation attempts to recover from the mismatched input
by using single token insertion and deletion as described below. If the
recovery attempt fails, d method panics an
{@link InputMisMatchException}.</p>

<p><strong>EXTRA TOKEN</strong> (single token deletion)</p>

<p>{@code LA(1)} is not what we are looking for. If {@code LA(2)} has the
right token, however, then assume {@code LA(1)} is some extra spurious
token and delete it. Then consume and return the next token (which was
the {@code LA(2)} token) as the successful result of the Match operation.</p>

<p>This recovery strategy is implemented by {@link
//singleTokenDeletion}.</p>

<p><strong>MISSING TOKEN</strong> (single token insertion)</p>

<p>If current token (at {@code LA(1)}) is consistent with what could come
after the expected {@code LA(1)} token, then assume the token is missing
and use the parser's {@link TokenFactory} to create it on the fly. The
"insertion" is performed by returning the created token as the successful
result of the Match operation.</p>

<p>This recovery strategy is implemented by {@link
//singleTokenInsertion}.</p>

<p><strong>EXAMPLE</strong></p>

<p>For example, Input {@code i=(3} is clearly missing the {@code ')'}. When
the parser returns from the nested call to {@code expr}, it will have
call chain:</p>

<pre>
stat &rarr expr &rarr atom
</pre>

and it will be trying to Match the {@code ')'} at d point in the
derivation:

<pre>
=&gt ID '=' '(' INT ')' ('+' atom)* ''
^
</pre>

The attempt to Match {@code ')'} will fail when it sees {@code ''} and
call {@link //recoverInline}. To recover, it sees that {@code LA(1)==''}
is in the set of tokens that can follow the {@code ')'} token reference
in rule {@code atom}. It can assume that you forgot the {@code ')'}.
package antlr
import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)
type ErrorStrategy interface {
	reset(Parser)
	RecoverInline(Parser) Token
	Recover(Parser, RecognitionException)
	Sync(Parser)
	inErrorRecoveryMode(Parser) bool
	ReportError(Parser, RecognitionException)
	ReportMatch(Parser)
}
type DefaultErrorStrategy struct {
	errorRecoveryMode bool
	lastErrorIndex    int
	lastErrorStates   *IntervalSet
}
var _ ErrorStrategy = &DefaultErrorStrategy{}
func NewDefaultErrorStrategy() *DefaultErrorStrategy {
	d := new(DefaultErrorStrategy)
	d.errorRecoveryMode = false
	d.lastErrorIndex = -1
	d.lastErrorStates = nil
	return d
}
func (d *DefaultErrorStrategy) reset(recognizer Parser) {
	d.endErrorCondition(recognizer)
}
func (d *DefaultErrorStrategy) beginErrorCondition(recognizer Parser) {
	d.errorRecoveryMode = true
}
func (d *DefaultErrorStrategy) inErrorRecoveryMode(recognizer Parser) bool {
	return d.errorRecoveryMode
}
func (d *DefaultErrorStrategy) endErrorCondition(recognizer Parser) {
	d.errorRecoveryMode = false
	d.lastErrorStates = nil
	d.lastErrorIndex = -1
}
func (d *DefaultErrorStrategy) ReportMatch(recognizer Parser) {
	d.endErrorCondition(recognizer)
}
func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionException) {
	if d.inErrorRecoveryMode(recognizer) {
		return  
	}
	d.beginErrorCondition(recognizer)
	switch t := e.(type) {
	default:
		fmt.Println("unknown recognition error type: " + reflect.TypeOf(e).Name())
		recognizer.NotifyErrorListeners(e.GetMessage(), e.GetOffendingToken(), e)
	case *NoViableAltException:
		d.ReportNoViableAlternative(recognizer, t)
	case *InputMisMatchException:
		d.ReportInputMisMatch(recognizer, t)
	case *FailedPredicateException:
		d.ReportFailedPredicate(recognizer, t)
	}
}
func (d *DefaultErrorStrategy) Recover(recognizer Parser, e RecognitionException) {
	if d.lastErrorIndex == recognizer.GetInputStream().Index() &&
		d.lastErrorStates != nil && d.lastErrorStates.contains(recognizer.GetState()) {
		recognizer.Consume()
	}
	d.lastErrorIndex = recognizer.GetInputStream().Index()
	if d.lastErrorStates == nil {
		d.lastErrorStates = NewIntervalSet()
	}
	d.lastErrorStates.addOne(recognizer.GetState())
	followSet := d.getErrorRecoverySet(recognizer)
	d.consumeUntil(recognizer, followSet)
}
func (d *DefaultErrorStrategy) Sync(recognizer Parser) {
	if d.inErrorRecoveryMode(recognizer) {
		return
	}
	s := recognizer.GetInterpreter().atn.states[recognizer.GetState()]
	la := recognizer.GetTokenStream().LA(1)
	nextTokens := recognizer.GetATN().NextTokens(s, nil)
	if nextTokens.contains(TokenEpsilon) || nextTokens.contains(la) {
		return
	}
	switch s.GetStateType() {
	case ATNStateBlockStart, ATNStateStarBlockStart, ATNStatePlusBlockStart, ATNStateStarLoopEntry:
		if d.SingleTokenDeletion(recognizer) != nil {
			return
		}
		panic(NewInputMisMatchException(recognizer))
	case ATNStatePlusLoopBack, ATNStateStarLoopBack:
		d.ReportUnwantedToken(recognizer)
		expecting := NewIntervalSet()
		expecting.addSet(recognizer.GetExpectedTokens())
		whatFollowsLoopIterationOrRule := expecting.addSet(d.getErrorRecoverySet(recognizer))
		d.consumeUntil(recognizer, whatFollowsLoopIterationOrRule)
	default:
	}
}
func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *NoViableAltException) {
	tokens := recognizer.GetTokenStream()
	var input string
	if tokens != nil {
		if e.startToken.GetTokenType() == TokenEOF {
			input = "<EOF>"
		} else {
			input = tokens.GetTextFromTokens(e.startToken, e.offendingToken)
		}
	} else {
		input = "<unknown input>"
	}
	msg := "no viable alternative at input " + d.escapeWSAndQuote(input)
	recognizer.NotifyErrorListeners(msg, e.offendingToken, e)
}
func (this *DefaultErrorStrategy) ReportInputMisMatch(recognizer Parser, e *InputMisMatchException) {
	msg := "mismatched input " + this.GetTokenErrorDisplay(e.offendingToken) +
		" expecting " + e.getExpectedTokens().StringVerbose(recognizer.GetLiteralNames(), recognizer.GetSymbolicNames(), false)
	recognizer.NotifyErrorListeners(msg, e.offendingToken, e)
}
func (d *DefaultErrorStrategy) ReportFailedPredicate(recognizer Parser, e *FailedPredicateException) {
	ruleName := recognizer.GetRuleNames()[recognizer.GetParserRuleContext().GetRuleIndex()]
	msg := "rule " + ruleName + " " + e.message
	recognizer.NotifyErrorListeners(msg, e.offendingToken, e)
}
func (d *DefaultErrorStrategy) ReportUnwantedToken(recognizer Parser) {
	if d.inErrorRecoveryMode(recognizer) {
		return
	}
	d.beginErrorCondition(recognizer)
	t := recognizer.GetCurrentToken()
	tokenName := d.GetTokenErrorDisplay(t)
	expecting := d.GetExpectedTokens(recognizer)
	msg := "extraneous input " + tokenName + " expecting " +
		expecting.StringVerbose(recognizer.GetLiteralNames(), recognizer.GetSymbolicNames(), false)
	recognizer.NotifyErrorListeners(msg, t, nil)
}
func (d *DefaultErrorStrategy) ReportMissingToken(recognizer Parser) {
	if d.inErrorRecoveryMode(recognizer) {
		return
	}
	d.beginErrorCondition(recognizer)
	t := recognizer.GetCurrentToken()
	expecting := d.GetExpectedTokens(recognizer)
	msg := "missing " + expecting.StringVerbose(recognizer.GetLiteralNames(), recognizer.GetSymbolicNames(), false) +
		" at " + d.GetTokenErrorDisplay(t)
	recognizer.NotifyErrorListeners(msg, t, nil)
}