Это связано с тем, как работает разбор LR. Синтаксический анализ LR фактически выполняется снизу вверх, группируя токены в соответствии с RHS ваших правил грамматики и заменяя их LHS. Когда анализатор «сдвигается», он помещает токен в стек, но на самом деле еще не соответствует правилу. Вместо этого он отслеживает частично совпадающие правила через текущее состояние. Когда он попадает в состояние, которое соответствует концу правила, он может уменьшаться, выталкивая символы для RHS из стека и отталкивая один символ, обозначающий LHS. Поэтому, если есть конфликты, они не отображаются до тех пор, пока синтаксический анализатор не достигнет какого-либо правила, и не сможет решить, уменьшать (или уменьшать).
В вашем примере, после просмотра % ( val , это то, что будет в стеке (вершина находится на правая сторона здесь). Когда предвидение ) , он не может решить, должен ли он вытолкнуть val и уменьшить с помощью правила CommaLoop: val , или он должен сдвинуть ) , поэтому он может вытолкнуть 3 вещи и уменьшить с помощью правила Expr: '(' val ')'
Здесь я предполагаю, что у вас есть некоторые дополнительные правила, такие как CommaLoop: Expr , иначе ваша грамматика на самом деле ничего не соответствует и bison / yacc будет жаловаться на неиспользуемые нетерминалы.