Зубр уменьшает / уменьшает конфликт в грамматике
Я строю грамматику в зубре, и у меня есть ар / г конфликт (который я знаю, где он находится), но я не знаю, как это исправить. Буду признателен за любую возможную помощь.
Часть моего кода, которая включает конфликт:
orismos2: %empty
|orismos orismos2
|error {yyerrok;yyclearin;};
orismos: orismosmetablitwn
|orismossunartisis
|prwtotuposunartisis;
orismosmetablitwn: tuposdedomenwn listametablitwn SEMICOLON ;
tuposdedomenwn: INT
|BOOL
|STRING;
listametablitwn: ID nid ;
nid: %empty
|pid nid
|error {yyerrok;yyclearin;};
pid: COMMA ID ;
orismossunartisis: kefalidasunartisis tmimaorismwn tmimaentolwn;
prwtotuposunartisis: kefalidasunartisis SEMICOLON;
kefalidasunartisis: typos_synartisis ID OPENBRACKET c CLOSEBRACKET;
typos_synartisis: INT
|BOOL
|VOID;
Я сделал выходной файл, в котором я вижу все конфликты.
Часть файла, которая включает конфликты:
State 21 conflicts: 1 reduce/reduce
State 22 conflicts: 1 reduce/reduce
Grammar
10 orismos2: %empty
11 | orismos orismos2
12 | error
13 orismos: orismosmetablitwn
14 | orismossunartisis
15 | prwtotuposunartisis
16 orismosmetablitwn: tuposdedomenwn listametablitwn SEMICOLON
17 tuposdedomenwn: INT
18 | BOOL
19 | STRING
20 listametablitwn: ID nid
21 nid: %empty
22 | pid nid
23 | error
24 pid: COMMA ID
25 orismossunartisis: kefalidasunartisis tmimaorismwn tmimaentolwn
26 prwtotuposunartisis: kefalidasunartisis SEMICOLON
27 kefalidasunartisis: typos_synartisis ID OPENBRACKET c CLOSEBRACKET
28 typos_synartisis: INT
29 | BOOL
30 | VOID
State 21
17 tuposdedomenwn: INT .
28 typos_synartisis: INT .
ID reduce using rule 17 (tuposdedomenwn)
ID [reduce using rule 28 (typos_synartisis)]
$default reduce using rule 17 (tuposdedomenwn)
State 22
18 tuposdedomenwn: BOOL .
29 typos_synartisis: BOOL .
ID reduce using rule 18 (tuposdedomenwn)
ID [reduce using rule 29 (typos_synartisis)]
$default reduce using rule 18 (tuposdedomenwn)
Я действительно все перепробовал, но не могу устранить конфликты... Любые идеи или предложения приветствуются!
Большое спасибо!!
1 ответ
Ключ здесь: …
orismos → (13) orismosmetablitwn → (16) tuposdedomenwn listametablitwn
orismos → (14) orismossunartisis → (25) kefalidasunartisis … → (27) typos_synartisis …
orismos → (15) prwtotuposunartisis → (26) kefalidasunartisis … → (27) typos_synartisis …
Также:
tuposdedomenwn → NUMBER | BOOL | STRING
listametablitwn → ID …
kefalidasunartisis → typos_synartisis ID …
typos_synartisis → NUMBER | BOOL | VOID
Итак, вот некоторые выводы из orismos
:
orismos → orismosmetablitwn → tuposdedomenwn listametablitwn → NUMBER ID …
orismos → orismossunartisis → kefalidasunartisis … → typos_synartisis … → NUMBER ID …
orismos → prwtotuposunartisis → kefalidasunartisis … → typos_synartisis … → NUMBER ID …
Скажем, мы находимся в контексте, где orismis
возможно, и мы только что видели NUMBER
и теперь мы смотрим на ID
, Все три из приведенных выше выводов возможны. Но есть небольшая проблема: в первом NUMBER
происходит от tuposdedomenwn
в то время как во вторых двух это происходит от typos_synartisis
, Прежде чем мы сможем сделать что-нибудь с ID
нам нужно знать, какое из двух производных уменьшить, но мы никак не можем это знать, пока не увидим токен после ID
,
Это означает, что грамматике нужно два токена упреждения, поэтому парсер LALR(1) не может ее проанализировать.
Простейшим решением было бы объединить два нетерминала, представляющих наборы типов, создавая нетерминал, который допускает все четыре варианта:
tuposdedomenwn: NUMBER | BOOL | STRING | VOID
Затем вам нужно будет выполнить семантическую проверку, чтобы убедиться, что переменная не объявлена VOID
ни объявленная функция STRING
, (Почему ваши функции не могут возвращать строки? Это кажется немного ограничивающим.) Эта стратегия принятия верхнего индекса языка, а затем выполнения семантических проверок во время построения AST или даже позже, очень распространена; например, это единственный способ обеспечить декларацию перед использованием переменных.
Но если вы не хотите выполнять семантическую проверку, вы можете просто отложить сокращение, создав нетерминалы, состоящие из типа данных и ID
, Это привело бы к чему-то вроде:
tupodedomenon_kai_metavlites
: INT ID
| BOOL ID
| STRING ID
| tupodedomenon_kai_metavlites ',' ID
tupo_synartisis_kai_metavliton
: INT ID
| BOOL ID
| VOID ID
orismos: orismosmetablitwn
| orismossunartisis
| prwtotuposunartisis
orismosmetablitwn
: tupodedomenon_kai_metavlites ';'
orismossunartisis
: kefalidasunartisis tmimaorismwn tmimaentolwn
prwtotuposunartisis
: kefalidasunartisis ';'
kefalidasunartisis
: tupo_synartisis_kai_metavliton '(' c ')'
С этим изменением нет необходимости уменьшать NUMBER
(или другой тип); ID
может быть сдвинут, и затем будет выполнено приведение к одной или другой возможности на основе следующего токена: как объявление переменной, если следующий токен ;
или же ,
и как объявление функции, если следующий токен (
,