Bison precedence is behaving unexpectedly with %prec for non operator precedence

2026-09-05

Stack Overflow: View Question

Tags: parsing, compiler-construction, bison

Score: 1 | Views: 88

The asker is trying to eliminate the classic dangling-else shift/reduce conflict in a small Bison grammar by using %nonassoc and %prec — not because they need a novel solution, but to understand precisely how Bison's precedence machinery works when it's applied to something that isn't an operator.

Why it's interesting. Precedence in Bison is almost always taught with binary operators: give + and * priorities, done. But precedence is really a lower-level mechanism — it's a tie-breaker attached to tokens and productions, consulted whenever the LALR(1) table has a shift/reduce conflict on a particular lookahead. Understanding what happens when you try to bend that mechanism to non-operator tokens (like ELSE) forces you to think about the conflict as a comparison between two things: the precedence of the rule about to be reduced and the precedence of the lookahead token.

The mechanics. When Bison sees IF PO PC statement · ELSE ..., it has a choice: reduce (turn the inner IF ... statement into a statement, associating ELSE with the outer if) or shift (attach ELSE to the inner if). Bison resolves this by comparing:

Higher precedence wins; equal precedence uses associativity (%nonassoc → error, %left → reduce, %right → shift).

Sketch of a fix. The idiomatic recipe is:

%nonassoc THEN     /* pseudo-token, never lexed */
%nonassoc ELSE

if-stmt : IF PO PC statement            %prec THEN
        | IF PO PC statement ELSE statement
        ;

Because ELSE has higher precedence than the fake THEN, and the short rule is tagged with THEN's precedence, Bison prefers to shift ELSE — attaching it to the innermost if, which matches C/Java semantics.

Gotchas. A few things trip people up:

The challenge: Bison's %prec looks like a knob you turn on operators, but it's really a rule-level annotation whose behavior only makes sense once you understand the shift-vs-reduce comparison it drives.

All newsletters