7.2. Interpreting conflicts

When you have a conflict, you will see an entry like this in your info file:

State 432

        atype -> SIMPLEQUOTE '[' . comma_types0 ']'         (rule 318)
        sysdcon -> '[' . ']'                                (rule 613)

        '_'            shift, and enter state 60
        'as'           shift, and enter state 16

...

        ']'            shift, and enter state 381
                        (reduce using rule 328)

...

On large, complex grammars, determining what the conflict is can be a bit of an art, since the state with the conflict may not have enough information to determine why a conflict is occurring).

In some cases, the rules associated with the state with the conflict will immediately give you enough guidance to determine what the ambiguous syntax is. For example, in the miniature shift/reduce conflict described in Section 8.4, “Conflict Tips”, the conflict looks like this:

State 13

        exp -> exp . '+' exp0                               (rule 1)
        exp0 -> if exp then exp else exp .                  (rule 3)

        then           reduce using rule 3
        else           reduce using rule 3
        '+'            shift, and enter state 7
                        (reduce using rule 3)

        %eof           reduce using rule 3

Here, rule 3 makes it easy to imagine that we had been parsing a statement like if 1 then 2 else 3 + 4; the conflict arises from whether or not we should shift (thus parsing as if 1 then 2 else (3 + 4)) or reduce (thus parsing as (if 1 then 2 else 3) + 4).

Sometimes, there's not as much helpful context in the error message; take this abridged example from GHC's parser:

State 49

        type -> btype .                                     (rule 281)
        type -> btype . '->' ctype                          (rule 284)

        '->'           shift, and enter state 472
                        (reduce using rule 281)

A pair of rules like this doesn't always result in a shift/reduce conflict: to reduce with rule 281 implies that, in some context when parsing the non-terminal type, it is possible for an '->' to occur immediately afterwards (indeed these source rules are factored such that there is no rule of the form ... -> type '->' ...).

The best way this author knows how to sleuth this out is to look for instances of the token and check if any of the preceeding non-terminals could terminate in a type:

        texp -> exp '->' texp                              (500)
        exp -> infixexp '::' sigtype                       (414)
        sigtype -> ctype                                   (260)
        ctype -> type                                      (274)

As it turns out, this shift/reduce conflict results from ambiguity for view patterns, as in the code sample case v of { x :: T -> T ... }.