2016-08-16 10 views
0

Я пытаюсь проанализировать положительные и отрицательные десятичные числа.Как преодолеть конфликт сдвига в LALR-грамматике

number(N) ::= pnumber(N1). 

number(N) ::= nnumber(N1). 

number(N) ::= pnumber(N1) DOT pnumber(N2). 

number(N) ::= nnumber(N1) DOT pnumber(N2). 

pnumber(N) ::= NUMBER(N1). 

nnumber(N) ::= MINUS NUMBER(N1). 

Включение первых двух правил дает сдвиг/свертка конфликта, но я не знаю, как я могу написать грамматику таким образом, что конфликт никогда не происходит. Я использую парсер Лимона.

Edit: конфликты из .out файла

State 79: 
    (56) number ::= nnumber * 
      number ::= nnumber * DOT pnumber 

          DOT shift  39 
          DOT reduce  56  ** Parsing conflict ** 
        {default} reduce  56  number ::= nnumber 

State 80: 
    (55) number ::= pnumber * 
      number ::= pnumber * DOT pnumber 

          DOT shift  40 
          DOT reduce  55  ** Parsing conflict ** 
        {default} reduce  55  number ::= pnumber 
State 39: 
      number ::= nnumber DOT * pnumber 
      pnumber ::= * NUMBER 

         NUMBER shift-reduce 59  pnumber ::= NUMBER 
         pnumber shift-reduce 58  number ::= nnumber DOT pnumber 

State 40: 
      number ::= pnumber DOT * pnumber 
      pnumber ::= * NUMBER 

         NUMBER shift-reduce 59  pnumber ::= NUMBER 
         pnumber shift-reduce 57  number ::= pnumber DOT pnumber 

Edit 2: Минимальная грамматика, которая вызывает Issue

start ::= prog. 
prog ::= rule. 
rule ::= REVERSE_IMPLICATION body DOT. 
body ::= bodydef. 
body ::= body CONJUNCTION bodydef. 
bodydef ::= literal. 
literal ::= variable. 
variable ::= number. 
number ::= pnumber. 
number ::= nnumber. 
number ::= pnumber DOT pnumber. 
number ::= nnumber DOT pnumber. 
pnumber ::= NUMBER. 
nnumber ::= MINUS NUMBER. 
+1

Для этого необходимо произвести MCVE ([MCVE]). При удалении ярлыков '(N)' (они не используются), данный фрагмент не создает конфликт смены сдвига с лимоном от SQLite 3.14.0. Как минимум, вы должны заглянуть в файл '.out' и включить в вопрос соответствующую информацию о конфликте, но лучше всего создать фрагмент грамматики, который можно скопировать и воспроизвести проблему. Тогда мы можем помочь вам (возможно). До тех пор мы застряли. –

+0

@JonathanLeffler Я добавил вывод файла .out, где происходят конфликты. Ярлыки (N) фактически используются, но я сократил их из вопроса для краткости. –

+0

Конечно, эти ярлыки используются в вашей реальной грамматике, но они являются неприятностью, когда вы пытаетесь помочь вам. Вам необходимо работать с MCVE-кодом вашего кода. Сдвиги к 39 и 40 актуальны, но мы не знаем, какие правила они являются частью. Беда может быть в том, что вашей грамматике нужно искать два токена - что он получает после DOT. Если это проблема, вам, скорее всего, необходимо улучшить ваш лексический анализатор, чтобы он вместо грамматики обрабатывал десятичные числа по сравнению с целыми числами, возвращая разные токены (например, NUMBER as now и DECIMAL). Обратите внимание, что начальные нули значительны после DOT. –

ответ

2

конфликты вы показываете указывают на проблему с как 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 
+0

Вы имеете в виду конец 'rule' или часть права' number'? –

+0

То, что я имел в виду, было с вводом 'DOT', он не знал бы, следует ли уменьшить' rule' или использовать его как часть 'number' –

+0

@SamidhT: yes ... –

0

Вы должны объявить ассоциативность маркеров DOT оператора с %left или %right.

Или еще одна идея - отказаться от этой промежуточной редукции. Очевидная особенность вашей грамматики заключается в том, что числа растут на DOT, а затем на число. Это может быть захвачен с одним правилом:

number : number DOT NUMBER 

ряд с последующим DOT с последующим NUMBER маркера по-прежнему является числом.

Это правило не требует DOT, чтобы объявить ассоциативность, поскольку нет двусмысленности; правило является чисто левым рекурсивным, а правая сторона DOT является терминальным токеном. Анализатор должен уменьшить верхнюю часть стека number, когда автомат находится в этой точке, а затем переложить DOT:

number : number DOT NUMBER 

языка, который вы разбор здесь регулярно; он может анализироваться регулярными выражениями без какой-либо рекурсии. Вот почему правила, которые имеют как левую, так и правую рекурсию в них и требуют объявления ассоциативности, представляют собой нечто вроде «большого молотка».

+0

В настоящее время я разбираю 'номер DOT NUMBER' с регулярным выражением как часть моего решения. Однако я дам левую ассоциативность «DOT» и посмотрю, работает ли это. –

 Смежные вопросы

  • Нет связанных вопросов^_^