{"record":{"id":"af04f4dded542a28","repo":"antlr/antlr4","slug":"only-precedence-dfas-may-contain-a-precedence-star-af04f4","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":"Exception","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Dfa/DFA.cs","lineNumber":89,"sourceCode":"\t\t\t\treturn precedenceDfa;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Get the start state for a specific precedence value.\n\t\t *\n\t\t * @param precedence The current precedence.\n\t\t * @return The start state corresponding to the specified precedence, or\n\t\t * {@code null} if no start state exists for the specified precedence.\n\t\t *\n\t\t * @throws IllegalStateException if this is not a precedence DFA.\n\t\t * @see #isPrecedenceDfa()\n\t\t */\n\t\tpublic DFAState GetPrecedenceStartState(int precedence)\n\t\t{\n\t\t\tif (!IsPrecedenceDfa)\n\t\t\t{\n\t\t\t\tthrow new Exception(\"Only precedence DFAs may contain a precedence start state.\");\n\t\t\t}\n\n\t\t\t// s0.edges is never null for a precedence DFA\n\t\t\tif (precedence < 0 || precedence >= s0.edges.Length)\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn s0.edges[precedence];\n\t\t}\n\n\t\t/**\n\t\t * Set the start state for a specific precedence value.\n\t\t *\n\t\t * @param precedence The current precedence.\n\t\t * @param startState The start state corresponding to the specified\n\t\t * precedence.\n\t\t *","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Dfa/DFA.cs#L71-L107","documentation":"DFA.GetPrecedenceStartState(precedence) returns the per-precedence start state of a precedence DFA — a DFA built for a grammar with left-recursive rules, where the simulator caches one start state per precedence level. The getter only makes sense when IsPrecedenceDfa is true (s0 is a special state whose edges array holds the precedence start states); on a normal DFA there is no such structure, so the method refuses instead of returning a misleading value.","triggerScenarios":"Calling GetPrecedenceStartState on a DFA whose start state was not marked as a precedence start state — i.e. grammars without left-recursive rules, or a precedence DFA whose s0 was replaced with a plain DFAState. Usually reached indirectly: ParserATNSimulator computes start states via this API when the decision is a precedence decision; manual DFA construction or copied s0 states can break the invariant.","commonSituations":"Manually building/resetting DFA objects (e.g. cache warmup that assigns dfa.s0 without setting isPrecedenceDfa); library code that assumes every parser DFA is a precedence DFA; porting Java code that manipulated dfa.s0 directly.","solutions":["Check dfa.IsPrecedenceDfa before calling Get/SetPrecedenceStartState","When constructing or resetting DFAs yourself, set dfa.s0 = new DFAState(...) plus dfa.IsPrecedenceDfa = true only for decisions that are precedence decisions (check atn.decisionToState[i].stateType)","Let ParserATNSimulator manage s0; avoid writing dfa.s0 by hand"],"exampleFix":"// before\nDFAState start = dfa.GetPrecedenceStartState(prec); // throws for non-precedence DFA\n\n// after\nDFAState start = dfa.IsPrecedenceDfa ? dfa.GetPrecedenceStartState(prec) : dfa.s0;","handlingStrategy":"validation","validationCode":"DFAState start = dfa.IsPrecedenceDfa ? dfa.GetPrecedenceStartState(precedence) : dfa.s0;","typeGuard":"static bool IsPrecedenceDfa(DFA dfa) => dfa != null && dfa.IsPrecedenceDfa;","tryCatchPattern":null,"preventionTips":["Check IsPrecedenceDfa before any Get/SetPrecedenceStartState call","Never assign dfa.s0 by hand; let the simulator initialize it"],"tags":["antlr","csharp","dfa","precedence","state-machine"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}