antlr/antlr4 · error · IllegalStateException
Only precedence DFAs may contain a precedence start state.
Error message
Only precedence DFAs may contain a precedence start state.
What it means
DFA.getPrecedenceStartState(precedence) returns the per-precedence start state used by ALL(*) prediction for left-recursive rules. Only DFAs flagged as precedence DFAs (created with new DFA(atnStart, -1) or otherwise marked) keep the s0.edges array of per-precedence starts; a normal DFA has a single s0, so the request is a logic error and throws IllegalStateException.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java:96
*/
public final boolean isPrecedenceDfa() {
return precedenceDfa;
}
/**
* Get the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @return The start state corresponding to the specified precedence, or
* {@code null} if no start state exists for the specified precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.
* @see #isPrecedenceDfa()
*/
@SuppressWarnings("null")
public final DFAState getPrecedenceStartState(int precedence) {
if (!isPrecedenceDfa()) {
throw new IllegalStateException("Only precedence DFAs may contain a precedence start state.");
}
// s0.edges is never null for a precedence DFA
if (precedence < 0 || precedence >= s0.edges.length) {
return null;
}
return s0.edges[precedence];
}
/**
* Set the start state for a specific precedence value.
*
* @param precedence The current precedence.
* @param startState The start state corresponding to the specified
* precedence.
*
* @throws IllegalStateException if this is not a precedence DFA.View on GitHub (pinned to 7d5770395b)
Solutions
- Guard with isPrecedenceDfa() before calling, and fall back to get s0 via the normal start-state accessor
- If the DFA should be a precedence DFA, construct it as new DFA(atnStart, precedence) with precedence >= 0 (e.g. -1 initialization in ParserATNSimulator means precedence DFA for the artificial rule-start decision)
- Otherwise use dfa.s0 (or the appropriate public API) for non-precedence DFAs
Example fix
// before
DFAState start = dfa.getPrecedenceStartState(prec); // throws for normal DFA
// after
DFAState start = dfa.isPrecedenceDfa()
? dfa.getPrecedenceStartState(prec)
: dfa.s0; Defensive patterns
Strategy: type-guard
Validate before calling
DFAState start = dfa.isPrecedenceDfa() ? dfa.getPrecedenceStartState(prec) : dfa.s0;
Type guard
static boolean isPrecedenceDfa(DFA dfa) { return dfa.isPrecedenceDfa(); } Prevention
- Always pair getPrecedenceStartState with an isPrecedenceDfa check
- Learn which decisions in a left-recursive grammar produce precedence DFAs
- Do not copy DFA-inspection code between lexer and parser decisions
When it happens
Trigger: Calling getPrecedenceStartState on a DFA constructed with new DFA(atnStartState) (no precedence argument), or before the ParserATNSimulator has initialized it as a precedence DFA (setPrecedenceDfa path). Typically hit by custom prediction-context or DFA-inspection code, since the runtime itself only calls it after checking isPrecedenceDfa().
Common situations: Writing DFA diagnostics/visualization tools that assume every decision DFA is a precedence DFA. Copying runtime code that handles left-recursive rules into a context where the DFA was created without precedence. Using a DFA meant for a non-left-recursive grammar decision.
Related errors
- The precedenceDfa field cannot change after a DFA is constru
- This set is readonly
- This ATN simulator does not support clearing the DFA.
- Precedence predicates are not supported in lexers.
- Only precedence DFAs may contain a precedence start state.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/c23f7fce20961043.
Report an issue: GitHub.