antlr/antlr4 · warning · UnsupportedOperationException

The precedenceDfa field cannot change after a DFA is constru

Error message

The precedenceDfa field cannot change after a DFA is constructed.

What it means

DFA.setPrecedenceDfa(boolean) is deprecated and intentionally performs nothing except a consistency check: the precedence-ness of a DFA is fixed at construction. Passing a value different from the DFA's current isPrecedenceDfa() throws UnsupportedOperationException. The method exists only so old code that toggled this flag fails loudly instead of silently misbehaving.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java:153

			s0.edges[precedence] = startState;
		}
	}

	/**
	 * Sets whether this is a precedence DFA.
	 *
	 * @param precedenceDfa {@code true} if this is a precedence DFA; otherwise,
	 * {@code false}
	 *
	 * @throws UnsupportedOperationException if {@code precedenceDfa} does not
	 * match the value of {@link #isPrecedenceDfa} for the current DFA.
	 *
	 * @deprecated This method no longer performs any action.
	 */
	@Deprecated
	public final void setPrecedenceDfa(boolean precedenceDfa) {
		if (precedenceDfa != isPrecedenceDfa()) {
			throw new UnsupportedOperationException("The precedenceDfa field cannot change after a DFA is constructed.");
		}
	}

	/**
	 * Return a list of all states in this DFA, ordered by state number.
	 */

	public List<DFAState> getStates() {
		List<DFAState> result = new ArrayList<DFAState>(states.keySet());
		Collections.sort(result, new Comparator<DFAState>() {
			@Override
			public int compare(DFAState o1, DFAState o2) {
				return o1.stateNumber - o2.stateNumber;
			}
		});

		return result;
	}

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Delete the setPrecedenceDfa call; pass precedence at construction: new DFA(atnStart, precedence) (precedence >= 0 marks a precedence DFA)
  2. If the call was a no-op consistency check in your code, replace it with an assertion on dfa.isPrecedenceDfa()
  3. Regenerate nothing here; fix runtime-side code only and re-run your parser tests

Example fix

// before (pre-4.6 style)
DFA dfa = new DFA(atnStart);
dfa.setPrecedenceDfa(true); // throws in 4.6+
// after
DFA dfa = new DFA(atnStart, 0); // precedence DFA from construction
assert dfa.isPrecedenceDfa();
Defensive patterns

Strategy: type-guard

Validate before calling

// replace the call with a construction-time choice
DFA dfa = wantPrecedence ? new DFA(atnStart, 0) : new DFA(atnStart);

Type guard

static boolean precedenceFlagMatches(DFA dfa, boolean want) { return dfa.isPrecedenceDfa() == want; }

Prevention

When it happens

Trigger: Calling dfa.setPrecedenceDfa(true) on a DFA constructed as a normal DFA, or setPrecedenceDfa(false) on a precedence DFA (created via new DFA(atnStart, -1)/precedence form or flagged during left-recursive rule simulation). Copy-pasted pre-4.6 code that 'converted' a DFA into a precedence DFA at runtime.

Common situations: Upgrading from ANTLR < 4.6 (where the field was mutable) to 4.6+: old workarounds that called setPrecedenceDfa now throw. Custom parser subclasses that mimic the old ParserATNSimulator init sequence.

Related errors


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