Skip to content

Commit a333aa0

Browse files
committed
feat: Make closureCheckingStopState iterative rather than recursive
1 parent 2406774 commit a333aa0

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

runtime/Go/antlr/v4/parser_atn_simulator.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,12 +995,78 @@ func (p *ParserATNSimulator) closure(config *ATNConfig, configs *ATNConfigSet, c
995995
fullCtx, initialDepth, treatEOFAsEpsilon)
996996
}
997997

998-
//goland:noinspection GoBoolExpressions
999998
func (p *ParserATNSimulator) closureCheckingStopState(config *ATNConfig, configs *ATNConfigSet, closureBusy *ClosureBusy, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
1000999
if runtimeConfig.parserATNSimulatorTraceATNSim {
10011000
fmt.Println("closure(" + config.String() + ")")
10021001
}
10031002

1003+
var stack []*ATNConfig
1004+
visited := make(map[*ATNConfig]bool)
1005+
1006+
stack = append(stack, config)
1007+
1008+
for len(stack) > 0 {
1009+
currConfig := stack[len(stack)-1]
1010+
stack = stack[:len(stack)-1]
1011+
1012+
if _, ok := visited[currConfig]; ok {
1013+
continue
1014+
}
1015+
visited[currConfig] = true
1016+
1017+
if _, ok := currConfig.GetState().(*RuleStopState); ok {
1018+
// We hit rule end. If we have context info, use it
1019+
// run thru all possible stack tops in ctx
1020+
if !currConfig.GetContext().isEmpty() {
1021+
for i := 0; i < currConfig.GetContext().length(); i++ {
1022+
if currConfig.GetContext().getReturnState(i) == BasePredictionContextEmptyReturnState {
1023+
if fullCtx {
1024+
nb := NewATNConfig1(currConfig, currConfig.GetState(), BasePredictionContextEMPTY)
1025+
configs.Add(nb, p.mergeCache)
1026+
continue
1027+
} else {
1028+
// we have no context info, just chase follow links (if greedy)
1029+
if runtimeConfig.parserATNSimulatorDebug {
1030+
fmt.Println("FALLING off rule " + p.getRuleName(currConfig.GetState().GetRuleIndex()))
1031+
}
1032+
p.closureWork(currConfig, configs, closureBusy, collectPredicates, fullCtx, depth, treatEOFAsEpsilon)
1033+
}
1034+
continue
1035+
}
1036+
returnState := p.atn.states[currConfig.GetContext().getReturnState(i)]
1037+
newContext := currConfig.GetContext().GetParent(i) // "pop" return state
1038+
1039+
c := NewATNConfig5(returnState, currConfig.GetAlt(), newContext, currConfig.GetSemanticContext())
1040+
// While we have context to pop back from, we may have
1041+
// gotten that context AFTER having falling off a rule.
1042+
// Make sure we track that we are now out of context.
1043+
c.SetReachesIntoOuterContext(currConfig.GetReachesIntoOuterContext())
1044+
1045+
stack = append(stack, c)
1046+
}
1047+
continue
1048+
} else if fullCtx {
1049+
// reached end of start rule
1050+
configs.Add(currConfig, p.mergeCache)
1051+
continue
1052+
} else {
1053+
// else if we have no context info, just chase follow links (if greedy)
1054+
if runtimeConfig.parserATNSimulatorDebug {
1055+
fmt.Println("FALLING off rule " + p.getRuleName(currConfig.GetState().GetRuleIndex()))
1056+
}
1057+
}
1058+
}
1059+
1060+
p.closureWork(currConfig, configs, closureBusy, collectPredicates, fullCtx, depth, treatEOFAsEpsilon)
1061+
}
1062+
}
1063+
1064+
//goland:noinspection GoBoolExpressions
1065+
func (p *ParserATNSimulator) closureCheckingStopStateRecursive(config *ATNConfig, configs *ATNConfigSet, closureBusy *ClosureBusy, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) {
1066+
if runtimeConfig.parserATNSimulatorTraceATNSim {
1067+
fmt.Println("closure(" + config.String() + ")")
1068+
}
1069+
10041070
if _, ok := config.GetState().(*RuleStopState); ok {
10051071
// We hit rule end. If we have context info, use it
10061072
// run thru all possible stack tops in ctx

0 commit comments

Comments
 (0)