{"record":{"id":"c23f7fce20961043","repo":"antlr/antlr4","slug":"only-precedence-dfas-may-contain-a-precedence-star","errorCode":null,"errorMessage":"Only precedence DFAs may contain a precedence start state.","messagePattern":"Only precedence DFAs may contain a precedence start state\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java","lineNumber":96,"sourceCode":"\t */\n\tpublic final boolean isPrecedenceDfa() {\n\t\treturn precedenceDfa;\n\t}\n\n\t/**\n\t * Get the start state for a specific precedence value.\n\t *\n\t * @param precedence The current precedence.\n\t * @return The start state corresponding to the specified precedence, or\n\t * {@code null} if no start state exists for the specified precedence.\n\t *\n\t * @throws IllegalStateException if this is not a precedence DFA.\n\t * @see #isPrecedenceDfa()\n\t */\n\t@SuppressWarnings(\"null\")\n\tpublic final DFAState getPrecedenceStartState(int precedence) {\n\t\tif (!isPrecedenceDfa()) {\n\t\t\tthrow new IllegalStateException(\"Only precedence DFAs may contain a precedence start state.\");\n\t\t}\n\n\t\t// s0.edges is never null for a precedence DFA\n\t\tif (precedence < 0 || precedence >= s0.edges.length) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn s0.edges[precedence];\n\t}\n\n\t/**\n\t * Set the start state for a specific precedence value.\n\t *\n\t * @param precedence The current precedence.\n\t * @param startState The start state corresponding to the specified\n\t * precedence.\n\t *\n\t * @throws IllegalStateException if this is not a precedence DFA.","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java#L78-L114","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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"],"exampleFix":"// before\nDFAState start = dfa.getPrecedenceStartState(prec); // throws for normal DFA\n// after\nDFAState start = dfa.isPrecedenceDfa()\n        ? dfa.getPrecedenceStartState(prec)\n        : dfa.s0;","handlingStrategy":"type-guard","validationCode":"DFAState start = dfa.isPrecedenceDfa() ? dfa.getPrecedenceStartState(prec) : dfa.s0;","typeGuard":"static boolean isPrecedenceDfa(DFA dfa) { return dfa.isPrecedenceDfa(); }","tryCatchPattern":null,"preventionTips":["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"],"tags":["antlr","java","dfa","precedence","illegal-state"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}