How To: Resolve Choice Conflicts¶
When CongoCC cannot tell two alternatives apart, it warns — typically
Expansion is unreachable. — and the parser silently always takes the first.
This guide is the practical workflow for fixing that; the full reference is
Disambiguation.
Step 1: see whether you have a conflict¶
Generate the grammar and read the warnings. An Expansion is unreachable
warning at a choice means two branches begin with the same token, so the later
branch can never be reached:
Entry : ( Declaration | Reference )+ <EOF> ;
Declaration : <ID> <COLON> <ID> ;
Reference : <ID> ; // unreachable: both start with <ID>
Step 2: reach for =>|| first¶
The up-to-here marker handles the common case with the least ceremony. Put it in the alternative just past the point that makes the choice unambiguous:
Declaration : <ID> <COLON> =>|| <ID> ;
Now the parser scans <ID> <COLON> before committing to Declaration and
falls through to Reference otherwise. This is the right tool for the large
majority of conflicts.
Step 3: use SCAN for the special cases¶
Switch to a full SCAN when =>|| is not enough:
a numeric limit when unbounded scanning is wasteful —
SCAN 3 => …;a semantic condition that depends on run-time state —
SCAN { someFlag } => …;a contextual predicate that depends on the parse stack, such as the non-reentrancy guard
SCAN ~\...\Foo => Foo.
Step 4: prefer restructuring to heavy lookahead¶
If two alternatives share a long common prefix, factor the prefix out so the choice happens later, when the alternatives genuinely differ. A grammar that needs little lookahead is usually clearer and faster than one that scans far ahead at every turn — left-factoring is often the better fix.