antlr/antlr4 · error · FailedPredicateException

precpred(_ctx, {})

Error message

precpred(_ctx, {})

What it means

ParserInterpreter handles PRECEDENCE transitions by calling precpred(ctx, precedence); when the check fails it raises FailedPredicateException with the message 'precpred(_ctx, <n>)'. This is the left-recursion precedence mechanism: in an ambiguous left-recursive expression, the interpreter asked whether a sub-expression may continue at precedence level n and the answer was no.

Source

Thrown at runtime/Python3/src/antlr4/ParserInterpreter.py:153

            if ruleStartState.isPrecedenceRule:
                self.enterRecursionRule(ctx, ruleStartState.stateNumber, ruleIndex, transition.precedence)
            else:
                self.enterRule(ctx, transition.target.stateNumber, ruleIndex)

        elif tt==Transition.PREDICATE:

            if not self.sempred(self._ctx, transition.ruleIndex, transition.predIndex):
                raise FailedPredicateException(self)

        elif tt==Transition.ACTION:

            self.action(self._ctx, transition.ruleIndex, transition.actionIndex)

        elif tt==Transition.PRECEDENCE:

            if not self.precpred(self._ctx, transition.precedence):
                msg = "precpred(_ctx, " + str(transition.precedence) + ")"
                raise FailedPredicateException(self, msg)

        else:
            raise UnsupportedOperationException("Unrecognized ATN transition type.")

        self.state = transition.target.stateNumber

    def visitRuleStopState(self, p:ATNState):
        ruleStartState = self.atn.ruleToStartState[p.ruleIndex]
        if ruleStartState.isPrecedenceRule:
            parentContext = self._parentContextStack.pop()
            self.unrollRecursionContexts(parentContext.a)
            self.state = parentContext[1]
        else:
            self.exitRule()

        ruleTransition = self.atn.states[self.state].transitions[0]
        self.state = ruleTransition.followState.stateNumber

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Do not override precpred/enterRecursionRule/unrollRecursionContexts in interpreter subclasses unless replicating generated-parser semantics exactly
  2. Ensure the tool version that produced the serialized ATN matches the runtime version interpreting it
  3. If the input itself is genuinely invalid for the precedence rules, validate/catch FailedPredicateException and report a syntax error instead of letting it propagate
  4. For production parsing of left-recursive grammars, use the generated parser rather than the interpreter

Example fix

# before
class MyInterp(ParserInterpreter):
    def precpred(self, ctx, precedence):
        return False  # breaks left-recursion: raises precpred(_ctx, n)

# after
class MyInterp(ParserInterpreter):
    pass  # inherit default: return self.precpred(ctx, precedence) semantics intact
Defensive patterns

Strategy: try-catch

Try / catch

from antlr4.error.Errors import FailedPredicateException
try:
    tree = interpreter.parse(start_rule)
except FailedPredicateException as ex:
    if "precpred" in (ex.msg or ""):
        # precedence walk failed: verify tool/runtime versions match, then reparse with generated parser
        raise SyntaxError("interpreter precedence failure: " + str(ex.msg)) from ex
    raise

Prevention

When it happens

Trigger: Interpreting a grammar with left-recursive expression rules where the precedence walk fails — usually because the interpreter's precedence bookkeeping (the _p precedence stack maintained by generated parsers via enterRecursionRule/unrollRecursionContexts) is out of sync; custom overrides of precpred returning false; ATN deserialized with options that alter precedence transitions.

Common situations: Grammar prototyping with ParserInterpreter on expression grammars; runtime/tool version mismatch producing an ATN the interpreter walks incorrectly; subclassed interpreters overriding precpred or recursion-context hooks incorrectly.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/5ffad02c9f86a0ec. Report an issue: GitHub.