конфликты вы показываете указывают на проблему с как number
нетерминал является используемого, а не с number
.
Основная проблема заключается в том, что после просмотра pnumber
или nnumber
, когда следующий знак опережающего просмотра является DOT
, он не может решить, что должно быть конец number
(уменьшения, так DOT
является частью какой-то другой нетерминальный послеnumber
), или если DOT
следует рассматривать как часть number
(смещенной так что он может позже уменьшить один из р/nnumber правил pnumber DOT.)
поэтому для того, чтобы диагностировать проблема, вам нужно будет показать все правила, которые используют number
в любом месте справа (и возвращают любые другие правила, которые используют любое из этих правил без терминалов справа).
Обратите внимание, что это редко бывает полезно размещать только фрагмент грамматики, так как процесс синтаксического анализа строительства LR в значительной степени зависит от контекста, где правила используются в другом месте в грамматике ...
Таким образом, проблема заключается в том, что вам нужно иметь два токена, чтобы различать DOT
в (реальном) number
и DOT
в конце rule
.
Простое исправление, чтобы дело лексического анализатора с ним - лексеры могут сделать небольшое количество опережающего просмотра довольно легко, так что вы можете признать REAL_NUMBER
в качестве отдельного нетерминала из NUMBER
(вероятно, до сих пор без -
, так что вы» d в конечном итоге с
number ::= NUMBER | MINUS NUMBER | REAL_NUMBER | MINUS REAL_NUMBER
его гораздо труднее устранить конфликт факторингом грамматику, но это может быть сделано.
в целом, реорганизовать грамматику, чтобы удалить опережения конфликт, вам нужно выяснить правила, которые демонстрируют конфликт (rule
и number
здесь) и реорганизовать вещи, чтобы объединить их в правила, которые имеют общие префиксы, пока вы не получите достаточно далеко, чтобы устранить неоднозначность.
Во-первых, я собираюсь предположить, что существуют другие правила, кроме number
, которые могут присутствовать здесь, так как в противном случае мы могли бы просто устранить все промежуточные правила.
variable ::= number | name
Мы хотим, чтобы переместить number
правило «вверх» в грамматике, чтобы получить его в том же месте, rule
с DOT
. Поэтому нам нужно разделить содержащиеся правила на специальный случай, когда они заканчиваются number
. Добавим, суффикс для обозначения правил, которые соответствуют первоначальному правилу со всеми версиями, которые заканчиваются в number
отделилась
variable ::= number | variable_n
variable_n ::= name
... и ProGate, что «до»
literal ::= number | literal_n
literal_n ::= variable_n
... и Агинского
bodydef ::= number | bodydef_n
bodydef_n := literal_n
... и снова
body ::= number | body_n
body := body CONUNCTION number
body_n ::= bodydef_n
body_n ::= body CONJUNCTION bodydef_n
Обратите внимание, что при его перемещении вам нужно разделить все больше и больше правил, поэтому этот процесс может немного взорвать грамматику. Тем не менее, правила, которые используются только только в конце rhs, что вы рефакторинг, будут нуждаться только в версии _n
, поэтому вам не обязательно удваивать количество правил.
... последний шаг
rule ::= REVERSE_IMPLICATION body_n DOT
rule ::= REVERSE_IMPLICATION number DOT
rule ::= REVERSE_IMPLICATION body CONJUNCTION number DOT
Теперь у вас есть ДОТы во всех тех же местах, так что расширить number
правила:
rule ::= REVERSE_IMPLICATION body_n DOT
rule ::= REVERSE_IMPLICATION integer DOT
rule ::= REVERSE_IMPLICATION integer DOT pnumber DOT
rule ::= REVERSE_IMPLICATION body CONJUNCTION integer DOT
rule ::= REVERSE_IMPLICATION body CONJUNCTION integer DOT pnumber DOT
и сдвиг-свертка конфликты исчезли, так правила имеют общие префиксы до тех пор, пока не будет найден необходимый вид, чтобы определить, что использовать. Я уменьшил количество правил в этом последнем расширении путем добавления
integer ::= pnumber | nnumber
Для этого необходимо произвести MCVE ([MCVE]). При удалении ярлыков '(N)' (они не используются), данный фрагмент не создает конфликт смены сдвига с лимоном от SQLite 3.14.0. Как минимум, вы должны заглянуть в файл '.out' и включить в вопрос соответствующую информацию о конфликте, но лучше всего создать фрагмент грамматики, который можно скопировать и воспроизвести проблему. Тогда мы можем помочь вам (возможно). До тех пор мы застряли. –
@JonathanLeffler Я добавил вывод файла .out, где происходят конфликты. Ярлыки (N) фактически используются, но я сократил их из вопроса для краткости. –
Конечно, эти ярлыки используются в вашей реальной грамматике, но они являются неприятностью, когда вы пытаетесь помочь вам. Вам необходимо работать с MCVE-кодом вашего кода. Сдвиги к 39 и 40 актуальны, но мы не знаем, какие правила они являются частью. Беда может быть в том, что вашей грамматике нужно искать два токена - что он получает после DOT. Если это проблема, вам, скорее всего, необходимо улучшить ваш лексический анализатор, чтобы он вместо грамматики обрабатывал десятичные числа по сравнению с целыми числами, возвращая разные токены (например, NUMBER as now и DECIMAL). Обратите внимание, что начальные нули значительны после DOT. –