Мне кажется, что конфликт, вероятно, возникает, потому что когда анализатор видит «!», Он сталкивается с проблемами при переписывании «expr». Игнорируя другие произведения для «фактора», обратите особое внимание на эти два произведения:
expr : expr "or" term { printf("expr : expr or term\n"); $$ = $1 | $3; }
| term { printf("expr : term\n"); }
;
factor : '!' expr { printf("factor : !expr\n"); $$ = !$2; }
Поскольку expr является рекурсивным, когда анализатор видит '!', Он знает, что отрицание применяется к следующему выражению, но если вы напишите "! TRUE OR TRUE", это отрицание применяется только к первому значению true или вся дизъюнкция?
РЕДАКТИРОВАТЬ: Другими словами, он не может решить, нужно ли ему сдвигать "или" или уменьшать "expr".
Установка параметра командной строки -v в yacc приведет к созданию файла .output, в котором есть все полезные свойства, включая диагностическую информацию для конфликтов сдвига / уменьшения. Он покажет вам все состояния DFA и места, где возникают конфликты, а иногда покажет, почему.
Размещение отрицаний в собственном производстве логически «между» «термином» и «фактором» должно помочь.