diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ParserATNSimulator.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ParserATNSimulator.cs index ccc1b502db..a7d914a711 100644 --- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ParserATNSimulator.cs +++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Atn/ParserATNSimulator.cs @@ -1622,12 +1622,6 @@ protected void Closure_(ATNConfig config, depth == 0, fullCtx, treatEofAsEpsilon); if (c != null) { - if (!t.IsEpsilon && !closureBusy.Add(c)) - { - // avoid infinite recursion for EOF* and EOF+ - continue; - } - int newDepth = depth; if (config.state is RuleStopState) { @@ -1637,12 +1631,6 @@ protected void Closure_(ATNConfig config, // come in handy and we avoid evaluating context dependent // preds if this is > 0. - if (!closureBusy.Add(c)) - { - // avoid infinite recursion for right-recursive rules - continue; - } - if (thisDfa != null && thisDfa.IsPrecedenceDfa) { int outermostPrecedenceReturn = ((EpsilonTransition)t).OutermostPrecedenceReturn; @@ -1653,17 +1641,32 @@ protected void Closure_(ATNConfig config, } c.reachesIntoOuterContext++; + if (!closureBusy.Add(c)) + { + // avoid infinite recursion for right-recursive rules + continue; + } + configs.dipsIntoOuterContext = true; // TODO: can remove? only care when we add to set per middle of this method newDepth--; if (debug) ConsoleWriteLine("dips into outer ctx: " + c); } - else if (t is RuleTransition) + else { - // latch when newDepth goes negative - once we step out of the entry context we can't return - if (newDepth >= 0) + + if (!t.IsEpsilon && !closureBusy.Add(c)) { - newDepth++; + // avoid infinite recursion for EOF* and EOF+ + continue; + } + if (t is RuleTransition) + { + // latch when newDepth goes negative - once we step out of the entry context we can't return + if (newDepth >= 0) + { + newDepth++; + } } } diff --git a/runtime/Python2/src/antlr4/atn/ParserATNSimulator.py b/runtime/Python2/src/antlr4/atn/ParserATNSimulator.py index bd3d928f2f..11fc6995ab 100755 --- a/runtime/Python2/src/antlr4/atn/ParserATNSimulator.py +++ b/runtime/Python2/src/antlr4/atn/ParserATNSimulator.py @@ -1145,11 +1145,6 @@ def closure_(self, config, configs, closureBusy, collectPredicates, fullCtx, dep continueCollecting = collectPredicates and not isinstance(t, ActionTransition) c = self.getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx, treatEofAsEpsilon) if c is not None: - if not t.isEpsilon: - if c in closureBusy: - # avoid infinite recursion for EOF* and EOF+ - continue - closureBusy.add(c) newDepth = depth if isinstance( config.state, RuleStopState): # target fell off end of rule; mark resulting c as having dipped into outer context @@ -1158,23 +1153,28 @@ def closure_(self, config, configs, closureBusy, collectPredicates, fullCtx, dep # come in handy and we avoid evaluating context dependent # preds if this is > 0. - if c in closureBusy: - # avoid infinite recursion for right-recursive rules - continue - closureBusy.add(c) - if self._dfa is not None and self._dfa.precedenceDfa: if t.outermostPrecedenceReturn == self._dfa.atnStartState.ruleIndex: c.precedenceFilterSuppressed = True c.reachesIntoOuterContext += 1 + if c in closureBusy: + # avoid infinite recursion for right-recursive rules + continue + closureBusy.add(c) configs.dipsIntoOuterContext = True # TODO: can remove? only care when we add to set per middle of this method newDepth -= 1 if ParserATNSimulator.debug: print("dips into outer ctx: " + str(c)) - elif isinstance(t, RuleTransition): - # latch when newDepth goes negative - once we step out of the entry context we can't return - if newDepth >= 0: - newDepth += 1 + else: + if not t.isEpsilon: + if c in closureBusy: + # avoid infinite recursion for EOF* and EOF+ + continue + closureBusy.add(c) + if isinstance(t, RuleTransition): + # latch when newDepth goes negative - once we step out of the entry context we can't return + if newDepth >= 0: + newDepth += 1 self.closureCheckingStopState(c, configs, closureBusy, continueCollecting, fullCtx, newDepth, treatEofAsEpsilon) diff --git a/runtime/Python3/src/antlr4/atn/ParserATNSimulator.py b/runtime/Python3/src/antlr4/atn/ParserATNSimulator.py index a3b2c7c14d..5f932dbea9 100644 --- a/runtime/Python3/src/antlr4/atn/ParserATNSimulator.py +++ b/runtime/Python3/src/antlr4/atn/ParserATNSimulator.py @@ -1150,11 +1150,6 @@ def closure_(self, config:ATNConfig, configs:ATNConfigSet, closureBusy:set, coll continueCollecting = collectPredicates and not isinstance(t, ActionTransition) c = self.getEpsilonTarget(config, t, continueCollecting, depth == 0, fullCtx, treatEofAsEpsilon) if c is not None: - if not t.isEpsilon: - if c in closureBusy: - # avoid infinite recursion for EOF* and EOF+ - continue - closureBusy.add(c) newDepth = depth if isinstance( config.state, RuleStopState): # target fell off end of rule; mark resulting c as having dipped into outer context @@ -1162,24 +1157,28 @@ def closure_(self, config:ATNConfig, configs:ATNConfigSet, closureBusy:set, coll # track how far we dip into outer context. Might # come in handy and we avoid evaluating context dependent # preds if this is > 0. - - if c in closureBusy: - # avoid infinite recursion for right-recursive rules - continue - closureBusy.add(c) - if self._dfa is not None and self._dfa.precedenceDfa: if t.outermostPrecedenceReturn == self._dfa.atnStartState.ruleIndex: c.precedenceFilterSuppressed = True c.reachesIntoOuterContext += 1 + if c in closureBusy: + # avoid infinite recursion for right-recursive rules + continue + closureBusy.add(c) configs.dipsIntoOuterContext = True # TODO: can remove? only care when we add to set per middle of this method newDepth -= 1 if ParserATNSimulator.debug: print("dips into outer ctx: " + str(c)) - elif isinstance(t, RuleTransition): - # latch when newDepth goes negative - once we step out of the entry context we can't return - if newDepth >= 0: - newDepth += 1 + else: + if not t.isEpsilon: + if c in closureBusy: + # avoid infinite recursion for EOF* and EOF+ + continue + closureBusy.add(c) + if isinstance(t, RuleTransition): + # latch when newDepth goes negative - once we step out of the entry context we can't return + if newDepth >= 0: + newDepth += 1 self.closureCheckingStopState(c, configs, closureBusy, continueCollecting, fullCtx, newDepth, treatEofAsEpsilon)