Ответ 1
Я думаю, что ваш синтаксический анализатор LR(0)
не является стандартным парсером:
Парсер LR (0) является парсером сдвига/уменьшения, который использует нулевые токены для определения того, какое действие нужно предпринять (следовательно, 0). Это означает, что в любой конфигурации анализатора парсер должен иметь однозначное действие для выбора - либо он сдвигает определенный символ, либо применяет конкретное сокращение. Если есть два или более вариантов, парсер терпит неудачу, и мы говорим, что грамматика не LR (0).
Итак, когда у вас есть:
S->A|B
A->xy
B->Az
или
S->A|B
A->xy
B->xyz
LR(0)
никогда не будет проверять правило B
, и для обоих из них он будет терпеть неудачу.
State0 - Clousure(S->°A):
S->°A
A->°xy
Arcs:
0 --> x --> 2
0 --> A --> 1
-------------------------
State1 - Goto(State0,A):
S->A°
Arcs:
1 --> $ --> Accept
-------------------------
State2 - Goto(State0,x):
A->x°y
Arcs:
2 --> y --> 3
-------------------------
State3 - Goto(State2,y):
A->xy°
Arcs:
-------------------------
Но если у вас
I->S
S->A|B
A->xy
B->xyz or B->Az
Оба они будут принимать xyz
, но в состояниях разности:
State0 - Clousure(I->°S):
I->°S
S->°A
S->°B
A->°xy A->°xy, $z
B->°xyz B->°Az, $
Arcs:
0 --> x --> 4
0 --> S --> 1
0 --> A --> 2
0 --> B --> 3
-------------------------
State1 - Goto(State0,S):
I->S°
Arcs:
1 --> $ --> Accept
-------------------------
State2 - Goto(State0,A):
S->A° S->A°, $
B->A°z, $
Arcs: 2 --> z --> 5
-------------------------
State3 - Goto(State0,B):
S->B°
Arcs:
-------------------------
State4 - Goto(State0,x):
A->x°y A->x°y, $z
B->x°yz
Arcs:
4 --> y --> 5 4 --> y --> 6
-------------------------
State5 - Goto(State4,y): - Goto(State2,z):
A->xy° B->Az°, $
Arcs:
5 --> z --> 6 -<None>-
-------------------------
State6 - Goto(State5,z): - Goto(State4,y)
B->xyz° A->xy°, $z
Arcs:
-------------------------
Вы можете видеть, что Goto Table
и Action Table
отличаются.
[B->xyz] [B->Az]
| Stack | Input | Action | Stack | Input | Action
--+---------+--------+---------- --+---------+--------+----------
1 | 0 | xyz$ | Shift 1 | 0 | xyz$ | Shift
2 | 0 4 | yz$ | Shift 2 | 0 4 | xy$ | Shift
3 | 0 4 5 | z$ | Shift 3 | 0 4 6 | z$ | Reduce A->xy
4 | 0 4 5 6 | $ | Reduce B->xyz 4 | 0 2 | z$ | Shift
5 | 0 3 | $ | Reduce S->B 5 | 0 2 5 | $ | Reduce B->Az
6 | 0 1 | $ | Accept 6 | 0 3 | $ | Reduce S->B
7 | 0 1 | $ | Accept
Просто, когда вы меняете B->xyz
на B->Az
, вы добавляете Action
в свой LR Table
, чтобы найти различия, которые вы можете проверить Action Table
и Goto Table
(Построение таблиц разбора LR (0))
-
Если у вас есть
A->xy
иB->xyz
, тогда у вас есть две нижние дескрипторы [xy
илиxyz
], но когда у вас естьB->Az
, у вас есть только один нижний дескриптор [xy
], может принимать дополнительныеz
. -
Я думаю, что это связано с локальной оптимизацией -c = a + b; d = a + b → c = a + b; d = c- при использовании
B->Az
вы оптимизируетеB->xyz
.