func (p *ParserATNSimulator) applyPrecedenceFilter(configs ATNConfigSet) ATNConfigSet {
	statesFromAlt1 := make(map[int]PredictionContext)
	configSet := NewBaseATNConfigSet(configs.FullContext())
	for _, config := range configs.GetItems() {
		if config.GetAlt() != 1 {
			continue
		}
		updatedContext := config.GetSemanticContext().evalPrecedence(p.parser, p.outerContext)
		if updatedContext == nil {
			continue
		}
		statesFromAlt1[config.GetState().GetStateNumber()] = config.GetContext()
		if updatedContext != config.GetSemanticContext() {
			configSet.Add(NewBaseATNConfig2(config, updatedContext), p.mergeCache)
		} else {
			configSet.Add(config, p.mergeCache)
		}
	}
	for _, config := range configs.GetItems() {
		if config.GetAlt() == 1 {
			continue
		}
		if !config.getPrecedenceFilterSuppressed() {
			context := statesFromAlt1[config.GetState().GetStateNumber()]
			if context != nil && context.equals(config.GetContext()) {
				continue
			}
		}
		configSet.Add(config, p.mergeCache)
	}
	return configSet
}
This method transforms the start state computed by
{@link //computeStartState} to the special start state used by a
precedence DFA for a particular precedence value. The transformation
process applies the following changes to the start state's configuration
set.

<ol>
<li>Evaluate the precedence predicates for each configuration using
{@link SemanticContext//evalPrecedence}.</li>
<li>Remove all configurations which predict an alternative greater than
1, for which another configuration that predicts alternative 1 is in the
same ATN state with the same prediction context. This transformation is
valid for the following reasons:
<ul>
<li>The closure block cannot contain any epsilon transitions which bypass
the body of the closure, so all states reachable via alternative 1 are
part of the precedence alternatives of the transformed left-recursive
rule.</li>
<li>The "primary" portion of a left recursive rule cannot contain an
epsilon transition, so the only way an alternative other than 1 can exist
in a state that is also reachable via alternative 1 is by nesting calls
to the left-recursive rule, with the outer calls not being at the
preferred precedence level.</li>
</ul>
</li>
</ol>

<p>
The prediction context must be considered by p filter to address
situations like the following.
</p>
<code>
<pre>
grammar TA
prog: statement* EOF
statement: letterA | statement letterA 'b'
letterA: 'a'
</pre>
</code>
<p>
If the above grammar, the ATN state immediately before the token
reference {@code 'a'} in {@code letterA} is reachable from the left edge
of both the primary and closure blocks of the left-recursive rule
{@code statement}. The prediction context associated with each of these
configurations distinguishes between them, and prevents the alternative
which stepped out to {@code prog} (and then back in to {@code statement}
from being eliminated by the filter.
</p>

@param configs The configuration set computed by
{@link //computeStartState} as the start state for the DFA.
@return The transformed configuration set representing the start state
for a precedence DFA at a particular precedence level (determined by
calling {@link Parser//getPrecedence}).
package antlr
import (
	"fmt"
	"strconv"
	"strings"
)
var (
	ParserATNSimulatorDebug            = false
	ParserATNSimulatorListATNDecisions = false
	ParserATNSimulatorDFADebug         = false
	ParserATNSimulatorRetryDebug       = false
)
type ParserATNSimulator struct {
	*BaseATNSimulator
	parser         Parser
	predictionMode int
	input          TokenStream
	startIndex     int
	dfa            *DFA
	mergeCache     *DoubleDict
	outerContext   ParserRuleContext
}
func NewParserATNSimulator(parser Parser, atn *ATN, decisionToDFA []*DFA, sharedContextCache *PredictionContextCache) *ParserATNSimulator {
	p := new(ParserATNSimulator)
	p.BaseATNSimulator = NewBaseATNSimulator(atn, sharedContextCache)
	p.parser = parser
	p.decisionToDFA = decisionToDFA
	p.predictionMode = PredictionModeLL
	p.input = nil
	p.startIndex = 0
	p.outerContext = nil
	p.dfa = nil
	p.mergeCache = nil
	return p
}
func (p *ParserATNSimulator) GetPredictionMode() int {
	return p.predictionMode
}
func (p *ParserATNSimulator) SetPredictionMode(v int) {
	p.predictionMode = v
}
func (p *ParserATNSimulator) reset() {
}
func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, outerContext ParserRuleContext) int {
	if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
		fmt.Println("AdaptivePredict decision " + strconv.Itoa(decision) +
			" exec LA(1)==" + p.getLookaheadName(input) +
			" line " + strconv.Itoa(input.LT(1).GetLine()) + ":" +
			strconv.Itoa(input.LT(1).GetColumn()))
	}
	p.input = input
	p.startIndex = input.Index()
	p.outerContext = outerContext
	dfa := p.decisionToDFA[decision]
	p.dfa = dfa
	m := input.Mark()
	index := input.Index()
	defer func() {
		p.dfa = nil
		p.mergeCache = nil  
		input.Seek(index)
		input.Release(m)
	}()
	var s0 *DFAState
	if dfa.precedenceDfa {
		s0 = dfa.getPrecedenceStartState(p.parser.GetPrecedence())
	} else {
		s0 = dfa.s0
	}
	if s0 == nil {
		if outerContext == nil {
			outerContext = RuleContextEmpty
		}
		if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
			fmt.Println("predictATN decision " + strconv.Itoa(dfa.decision) +
				" exec LA(1)==" + p.getLookaheadName(input) +
				", outerContext=" + outerContext.String(p.parser.GetRuleNames(), nil))
		}
		t2 := dfa.atnStartState
		t, ok := t2.(*StarLoopEntryState)
		if !dfa.precedenceDfa && ok {
			if t.precedenceRuleDecision {
				dfa.setPrecedenceDfa(true)
			}
		}
		fullCtx := false
		s0Closure := p.computeStartState(dfa.atnStartState, RuleContextEmpty, fullCtx)
		if dfa.precedenceDfa {
			s0Closure = p.applyPrecedenceFilter(s0Closure)
			s0 = p.addDFAState(dfa, NewDFAState(-1, s0Closure))
			dfa.setPrecedenceStartState(p.parser.GetPrecedence(), s0)
		} else {
			s0 = p.addDFAState(dfa, NewDFAState(-1, s0Closure))
			dfa.s0 = s0
		}
	}
	alt := p.execATN(dfa, s0, input, index, outerContext)
	if ParserATNSimulatorDebug {
		fmt.Println("DFA after predictATN: " + dfa.String(p.parser.GetLiteralNames(), nil))
	}
	return alt
}
func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, startIndex int, outerContext ParserRuleContext) int {
	if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
		fmt.Println("execATN decision " + strconv.Itoa(dfa.decision) +
			" exec LA(1)==" + p.getLookaheadName(input) +
			" line " + strconv.Itoa(input.LT(1).GetLine()) + ":" + strconv.Itoa(input.LT(1).GetColumn()))
	}
	previousD := s0
	if ParserATNSimulatorDebug {
		fmt.Println("s0 = " + s0.String())
	}
	t := input.LA(1)
	for {  
		D := p.getExistingTargetState(previousD, t)
		if D == nil {
			D = p.computeTargetState(dfa, previousD, t)
		}
		if D == ATNSimulatorError {
			e := p.noViableAlt(input, outerContext, previousD.configs, startIndex)
			input.Seek(startIndex)
			alt := p.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configs, outerContext)
			if alt != ATNInvalidAltNumber {
				return alt
			}
			panic(e)
		}
		if D.requiresFullContext && p.predictionMode != PredictionModeSLL {
			conflictingAlts := D.configs.GetConflictingAlts()
			if D.predicates != nil {
				if ParserATNSimulatorDebug {
					fmt.Println("DFA state has preds in DFA sim LL failover")
				}
				conflictIndex := input.Index()
				if conflictIndex != startIndex {
					input.Seek(startIndex)
				}
				conflictingAlts = p.evalSemanticContext(D.predicates, outerContext, true)
				if conflictingAlts.length() == 1 {
					if ParserATNSimulatorDebug {
						fmt.Println("Full LL avoided")
					}
					return conflictingAlts.minValue()
				}
				if conflictIndex != startIndex {
					input.Seek(conflictIndex)
				}
			}
			if ParserATNSimulatorDFADebug {
				fmt.Println("ctx sensitive state " + outerContext.String(nil, nil) + " in " + D.String())
			}
			fullCtx := true
			s0Closure := p.computeStartState(dfa.atnStartState, outerContext, fullCtx)
			p.ReportAttemptingFullContext(dfa, conflictingAlts, D.configs, startIndex, input.Index())
			alt := p.execATNWithFullContext(dfa, D, s0Closure, input, startIndex, outerContext)
			return alt
		}
		if D.isAcceptState {
			if D.predicates == nil {
				return D.prediction
			}
			stopIndex := input.Index()
			input.Seek(startIndex)
			alts := p.evalSemanticContext(D.predicates, outerContext, true)
			if alts.length() == 0 {
				panic(p.noViableAlt(input, outerContext, D.configs, startIndex))
			} else if alts.length() == 1 {
				return alts.minValue()
			} else {
				p.ReportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs)
				return alts.minValue()
			}
		}
		previousD = D
		if t != TokenEOF {
			input.Consume()
			t = input.LA(1)
		}
	}
	panic("Should not have reached p state")
}
func (p *ParserATNSimulator) getExistingTargetState(previousD *DFAState, t int) *DFAState {
	edges := previousD.edges
	if edges == nil {
		return nil
	}
	return edges[t+1]
}
func (p *ParserATNSimulator) computeTargetState(dfa *DFA, previousD *DFAState, t int) *DFAState {
	reach := p.computeReachSet(previousD.configs, t, false)
	if reach == nil {
		p.addDFAEdge(dfa, previousD, t, ATNSimulatorError)
		return ATNSimulatorError
	}
	D := NewDFAState(-1, reach)
	predictedAlt := p.getUniqueAlt(reach)
	if ParserATNSimulatorDebug {
		altSubSets := PredictionModegetConflictingAltSubsets(reach)
		fmt.Println("SLL altSubSets=" + fmt.Sprint(altSubSets) +
			", previous=" + previousD.configs.String() +
			", configs=" + reach.String() +
			", predict=" + strconv.Itoa(predictedAlt) +
			", allSubsetsConflict=" +
			fmt.Sprint(PredictionModeallSubsetsConflict(altSubSets)) +
			", conflictingAlts=" + p.getConflictingAlts(reach).String())
	}
	if predictedAlt != ATNInvalidAltNumber {
		D.isAcceptState = true
		D.configs.SetUniqueAlt(predictedAlt)
		D.setPrediction(predictedAlt)
	} else if PredictionModehasSLLConflictTerminatingPrediction(p.predictionMode, reach) {
		D.configs.SetConflictingAlts(p.getConflictingAlts(reach))
		D.requiresFullContext = true
		D.isAcceptState = true
		D.setPrediction(D.configs.GetConflictingAlts().minValue())
	}
	if D.isAcceptState && D.configs.HasSemanticContext() {
		p.predicateDFAState(D, p.atn.getDecisionState(dfa.decision))
		if D.predicates != nil {
			D.setPrediction(ATNInvalidAltNumber)
		}
	}
	D = p.addDFAEdge(dfa, previousD, t, D)
	return D
}
func (p *ParserATNSimulator) predicateDFAState(dfaState *DFAState, decisionState DecisionState) {
	nalts := len(decisionState.GetTransitions())
	altsToCollectPredsFrom := p.getConflictingAltsOrUniqueAlt(dfaState.configs)
	altToPred := p.getPredsForAmbigAlts(altsToCollectPredsFrom, dfaState.configs, nalts)
	if altToPred != nil {
		dfaState.predicates = p.getPredicatePredictions(altsToCollectPredsFrom, altToPred)
		dfaState.setPrediction(ATNInvalidAltNumber)  
	} else {
		dfaState.setPrediction(altsToCollectPredsFrom.minValue())
	}
}
func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 ATNConfigSet, input TokenStream, startIndex int, outerContext ParserRuleContext) int {
	if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions {
		fmt.Println("execATNWithFullContext " + s0.String())
	}
	fullCtx := true
	foundExactAmbig := false
	var reach ATNConfigSet
	previous := s0
	input.Seek(startIndex)
	t := input.LA(1)
	predictedAlt := -1
	for {  
		reach = p.computeReachSet(previous, t, fullCtx)
		if reach == nil {
			e := p.noViableAlt(input, outerContext, previous, startIndex)
			input.Seek(startIndex)
			alt := p.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext)
			if alt != ATNInvalidAltNumber {
				return alt
			}
			panic(e)
		}
		altSubSets := PredictionModegetConflictingAltSubsets(reach)
		if ParserATNSimulatorDebug {
			fmt.Println("LL altSubSets=" + fmt.Sprint(altSubSets) + ", predict=" +
				strconv.Itoa(PredictionModegetUniqueAlt(altSubSets)) + ", resolvesToJustOneViableAlt=" +
				fmt.Sprint(PredictionModeresolvesToJustOneViableAlt(altSubSets)))
		}
		reach.SetUniqueAlt(p.getUniqueAlt(reach))
		if reach.GetUniqueAlt() != ATNInvalidAltNumber {
			predictedAlt = reach.GetUniqueAlt()
			break
		} else if p.predictionMode != PredictionModeLLExactAmbigDetection {
			predictedAlt = PredictionModeresolvesToJustOneViableAlt(altSubSets)
			if predictedAlt != ATNInvalidAltNumber {
				break
			}
		} else {
			if PredictionModeallSubsetsConflict(altSubSets) && PredictionModeallSubsetsEqual(altSubSets) {
				foundExactAmbig = true
				predictedAlt = PredictionModegetSingleViableAlt(altSubSets)
				break
			}
		}
		previous = reach
		if t != TokenEOF {
			input.Consume()
			t = input.LA(1)
		}
	}
	if reach.GetUniqueAlt() != ATNInvalidAltNumber {
		p.ReportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.Index())
		return predictedAlt
	}
	p.ReportAmbiguity(dfa, D, startIndex, input.Index(), foundExactAmbig, nil, reach)
	return predictedAlt
}
func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCtx bool) ATNConfigSet {
	if ParserATNSimulatorDebug {
		fmt.Println("in computeReachSet, starting closure: " + closure.String())
	}
	if p.mergeCache == nil {
		p.mergeCache = NewDoubleDict()
	}
	intermediate := NewBaseATNConfigSet(fullCtx)
	var SkippedStopStates []*BaseATNConfig
	for _, c := range closure.GetItems() {
		if ParserATNSimulatorDebug {
			fmt.Println("testing " + p.GetTokenName(t) + " at " + c.String())
		}
		_, ok := c.GetState().(*RuleStopState)
		if ok {
			if fullCtx || t == TokenEOF {
				if SkippedStopStates == nil {
					SkippedStopStates = make([]*BaseATNConfig, 0)
				}
				SkippedStopStates = append(SkippedStopStates, c.(*BaseATNConfig))
				if ParserATNSimulatorDebug {
					fmt.Println("added " + c.String() + " to SkippedStopStates")
				}
			}
			continue
		}
		for j := 0; j < len(c.GetState().GetTransitions()); j++ {
			trans := c.GetState().GetTransitions()[j]
			target := p.getReachableTarget(trans, t)
			if target != nil {
				cfg := NewBaseATNConfig4(c, target)
				intermediate.Add(cfg, p.mergeCache)
				if ParserATNSimulatorDebug {
					fmt.Println("added " + cfg.String() + " to intermediate")
				}
			}
		}
	}
	var reach ATNConfigSet
	if SkippedStopStates == nil && t != TokenEOF {
		if len(intermediate.configs) == 1 {
			reach = intermediate
		} else if p.getUniqueAlt(intermediate) != ATNInvalidAltNumber {
			reach = intermediate
		}
	}
	if reach == nil {
		reach = NewBaseATNConfigSet(fullCtx)
		closureBusy := NewSet(nil, nil)
		treatEOFAsEpsilon := t == TokenEOF
		for k := 0; k < len(intermediate.configs); k++ {
			p.closure(intermediate.configs[k], reach, closureBusy, false, fullCtx, treatEOFAsEpsilon)
		}
	}
	if t == TokenEOF {
		reach = p.removeAllConfigsNotInRuleStopState(reach, reach == intermediate)
	}
	if SkippedStopStates != nil && ((!fullCtx) || (!PredictionModehasConfigInRuleStopState(reach))) {
		for l := 0; l < len(SkippedStopStates); l++ {
			reach.Add(SkippedStopStates[l], p.mergeCache)
		}
	}
	if len(reach.GetItems()) == 0 {
		return nil
	}
	return reach
}
func (p *ParserATNSimulator) removeAllConfigsNotInRuleStopState(configs ATNConfigSet, lookToEndOfRule bool) ATNConfigSet {
	if PredictionModeallConfigsInRuleStopStates(configs) {
		return configs
	}
	result := NewBaseATNConfigSet(configs.FullContext())
	for _, config := range configs.GetItems() {
		_, ok := config.GetState().(*RuleStopState)
		if ok {
			result.Add(config, p.mergeCache)
			continue
		}
		if lookToEndOfRule && config.GetState().GetEpsilonOnlyTransitions() {
			NextTokens := p.atn.NextTokens(config.GetState(), nil)
			if NextTokens.contains(TokenEpsilon) {
				endOfRuleState := p.atn.ruleToStopState[config.GetState().GetRuleIndex()]
				result.Add(NewBaseATNConfig4(config, endOfRuleState), p.mergeCache)
			}
		}
	}
	return result
}
func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, fullCtx bool) ATNConfigSet {
	initialContext := predictionContextFromRuleContext(p.atn, ctx)
	configs := NewBaseATNConfigSet(fullCtx)
	for i := 0; i < len(a.GetTransitions()); i++ {
		target := a.GetTransitions()[i].getTarget()
		c := NewBaseATNConfig6(target, i+1, initialContext)
		closureBusy := NewSet(nil, nil)
		p.closure(c, configs, closureBusy, true, fullCtx, false)
	}
	return configs
}