protected void closureCheckingStopState(ATNConfig config,
											ATNConfigSet configs,
											Set<ATNConfig> closureBusy,
											boolean collectPredicates,
											boolean fullCtx,
											int depth,
											boolean treatEofAsEpsilon)
	{
		if ( trace_atn_sim ) System.out.println("closure("+config.toString(parser,true)+")");

		if ( config.state instanceof RuleStopState ) {
			// We hit rule end. If we have context info, use it
			// run thru all possible stack tops in ctx
			if ( !config.context.isEmpty() ) {
				for (int i = 0; i < config.context.size(); i++) {
					if ( config.context.getReturnState(i)==PredictionContext.EMPTY_RETURN_STATE ) {
						if (fullCtx) {
							configs.add(new ATNConfig(config, config.state, EmptyPredictionContext.Instance), mergeCache);
							continue;
						}
						else {
							// we have no context info, just chase follow links (if greedy)
							if ( debug ) System.out.println("FALLING off rule "+
															getRuleName(config.state.ruleIndex));
							closure_(config, configs, closureBusy, collectPredicates,
									 fullCtx, depth, treatEofAsEpsilon);
						}
						continue;
					}
					ATNState returnState = atn.states.get(config.context.getReturnState(i));
					PredictionContext newContext = config.context.getParent(i); // "pop" return state
					ATNConfig c = new ATNConfig(returnState, config.alt, newContext,
												config.semanticContext);
					// While we have context to pop back from, we may have
					// gotten that context AFTER having falling off a rule.
					// Make sure we track that we are now out of context.
					//
					// This assignment also propagates the
					// isPrecedenceFilterSuppressed() value to the new
					// configuration.
					c.reachesIntoOuterContext = config.reachesIntoOuterContext;
					assert depth > Integer.MIN_VALUE;
					closureCheckingStopState(c, configs, closureBusy, collectPredicates,
											 fullCtx, depth - 1, treatEofAsEpsilon);
				}
				return;
			}
			else if (fullCtx) {
				// reached end of start rule
				configs.add(config, mergeCache);
				return;
			}
			else {
				// else if we have no context info, just chase follow links (if greedy)
				if ( debug ) System.out.println("FALLING off rule "+
												getRuleName(config.state.ruleIndex));
			}
		}

		closure_(config, configs, closureBusy, collectPredicates,
				 fullCtx, depth, treatEofAsEpsilon);
	}
Evaluate a semantic context within a specific parser context.

<p>
This method might not be called for every semantic context evaluated
during the prediction process. In particular, we currently do not
evaluate the following but it may change in the future:</p>

<ul>
<li>Precedence predicates (represented by
{@link SemanticContext.PrecedencePredicate}) are not currently evaluated
through this method.</li>
<li>Operator predicates (represented by {@link SemanticContext.AND} and
{@link SemanticContext.OR}) are evaluated as a single semantic
context, rather than evaluating the operands individually.
Implementations which require evaluation results from individual
predicates should override this method to explicitly handle evaluation of
the operands within operator predicates.</li>
</ul>

@param pred The semantic context to evaluate
@param parserCallStack The parser context in which to evaluate the
semantic context
@param alt The alternative which is guarded by {@code pred}
@param fullCtx {@code true} if the evaluation is occurring during LL
prediction; otherwise, {@code false} if the evaluation is occurring
during SLL prediction

@since 4.3
runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java