我创建了一个语法,其精简版本如下所示:
(0) exp1: ternary;
(1) exp1: exp2;
(2) ternary: exp2 "?" exp1 ":" exp1;
(3) exp2: exp2 "+" exp3;
(4) exp2: exp3;
(5) exp3: maybe;
(6) exp3: "1";
(7) maybe: exp3 "?";
我相信这种语言是明确的,应该是 LR 可解析的。(如果我错了,请告诉我!)
但是,当我尝试为此语法生成 LR(1) 解析器时,我会遇到移位/归约冲突,因为当解析器看到exp3
前瞻?
时,它不知道是移位还是归约:
Conflicts in state 3:
Reduction using rule 4: exp2: exp3 · | "?"
Shift to state 6
Conflicts in state 9:
Reduction using rule 3: exp2: exp2 "+" exp3 · | "?"
Shift to state 6
Conflicts in state 13:
Reduction using rule 4: exp2: exp3 · | "?"
Shift to state 16
Conflicts in state 20:
Reduction using rule 4: exp2: exp3 · | "?"
Shift to state 23
Conflicts in state 25:
Reduction using rule 3: exp2: exp2 "+" exp3 · | "?"
Shift to state 23
Conflicts in state 28:
Reduction using rule 3: exp2: exp2 "+" exp3 · | "?"
Shift to state 16
有没有一种合理的方法可以使这种语言 LR(1) 可解析(没有冲突)?
还是 GLR(或者可能是 LR(2)?)对于这样的语言,我唯一现实的选择是什么?
(或者我认为语言一开始是明确的,我什至是错误的?)
作为参考,我生成的模棱两可的状态机如下(其中 ♦ 是 EOF):
State 0:
exp1: · ternary | {♦} → shift 1
ternary: · exp2 "?" exp1 ":" exp1 | {♦} → shift 2
exp2: · exp2 "+" exp3 | {"?", "+"} → shift 2
exp2: · exp3 | {"?", "+"} → shift 3
exp3: · maybe | {"?", "+"} → shift 4
exp3: · "1" | {"?", "+"} → shift 5
maybe: · exp3 "?" | {"?", "+"} → shift 3
State 1:
exp1: ternary · | {♦} → reduce 0
State 2:
ternary: exp2 · "?" exp1 ":" exp1 | {♦} → shift 7
exp2: exp2 · "+" exp3 | {"?", "+"} → shift 8
State 3:
exp2: exp3 · | {"+"} → reduce 4
exp2: exp3 · | {"?"} → reduce 4 shift 6
maybe: exp3 · "?" | {"?", "+"} → reduce 4 shift 6
State 4:
exp3: maybe · | {"?", "+"} → reduce 5
State 5:
exp3: "1" · | {"?", "+"} → reduce 6
State 6:
maybe: exp3 "?" · | {"?", "+"} → reduce 7
State 7:
exp1: · ternary | {":"} → shift 10
exp1: · exp2 | {":"} → shift 11
ternary: · exp2 "?" exp1 ":" exp1 | {":"} → shift 11
ternary: exp2 "?" · exp1 ":" exp1 | {♦} → shift 12
exp2: · exp2 "+" exp3 | {"?", ":", "+"} → shift 11
exp2: · exp3 | {"?", ":", "+"} → shift 13
exp3: · maybe | {"?", ":", "+"} → shift 14
exp3: · "1" | {"?", ":", "+"} → shift 15
maybe: · exp3 "?" | {"?", ":", "+"} → shift 13
State 8:
exp2: exp2 "+" · exp3 | {"?", "+"} → shift 9
exp3: · maybe | {"?", "+"} → shift 4
exp3: · "1" | {"?", "+"} → shift 5
maybe: · exp3 "?" | {"?", "+"} → shift 9
State 9:
exp2: exp2 "+" exp3 · | {"+"} → reduce 3
exp2: exp2 "+" exp3 · | {"?"} → reduce 3 shift 6
maybe: exp3 · "?" | {"?", "+"} → reduce 3 shift 6
State 10:
exp1: ternary · | {":"} → reduce 0
State 11:
exp1: exp2 · | {":"} → reduce 1
ternary: exp2 · "?" exp1 ":" exp1 | {":"} → shift 26
exp2: exp2 · "+" exp3 | {"?", ":", "+"} → shift 27
State 12:
ternary: exp2 "?" exp1 · ":" exp1 | {♦} → shift 17
State 13:
exp2: exp3 · | {":", "+"} → reduce 4
exp2: exp3 · | {"?"} → reduce 4 shift 16
maybe: exp3 · "?" | {"?", ":", "+"} → reduce 4 shift 16
State 14:
exp3: maybe · | {"?", ":", "+"} → reduce 5
State 15:
exp3: "1" · | {"?", ":", "+"} → reduce 6
State 16:
maybe: exp3 "?" · | {"?", ":", "+"} → reduce 7
State 17:
exp1: · ternary | {♦} → shift 1
exp1: · exp2 | {♦} → shift 18
ternary: · exp2 "?" exp1 ":" exp1 | {♦} → shift 18
ternary: exp2 "?" exp1 ":" · exp1 | {♦} → shift 19
exp2: · exp2 "+" exp3 | {♦, "?", "+"} → shift 18
exp2: · exp3 | {♦, "?", "+"} → shift 20
exp3: · maybe | {♦, "?", "+"} → shift 21
exp3: · "1" | {♦, "?", "+"} → shift 22
maybe: · exp3 "?" | {♦, "?", "+"} → shift 20
State 18:
exp1: exp2 · | {♦} → reduce 1
ternary: exp2 · "?" exp1 ":" exp1 | {♦} → shift 7
exp2: exp2 · "+" exp3 | {♦, "?", "+"} → shift 24
State 19:
ternary: exp2 "?" exp1 ":" exp1 · | {♦} → reduce 2
State 20:
exp2: exp3 · | {♦, "+"} → reduce 4
exp2: exp3 · | {"?"} → reduce 4 shift 23
maybe: exp3 · "?" | {♦, "?", "+"} → reduce 4 shift 23
State 21:
exp3: maybe · | {♦, "?", "+"} → reduce 5
State 22:
exp3: "1" · | {♦, "?", "+"} → reduce 6
State 23:
maybe: exp3 "?" · | {♦, "?", "+"} → reduce 7
State 24:
exp2: exp2 "+" · exp3 | {♦, "?", "+"} → shift 25
exp3: · maybe | {♦, "?", "+"} → shift 21
exp3: · "1" | {♦, "?", "+"} → shift 22
maybe: · exp3 "?" | {♦, "?", "+"} → shift 25
State 25:
exp2: exp2 "+" exp3 · | {♦, "+"} → reduce 3
exp2: exp2 "+" exp3 · | {"?"} → reduce 3 shift 23
maybe: exp3 · "?" | {♦, "?", "+"} → reduce 3 shift 23
State 26:
exp1: · ternary | {":"} → shift 10
exp1: · exp2 | {":"} → shift 11
ternary: · exp2 "?" exp1 ":" exp1 | {":"} → shift 11
ternary: exp2 "?" · exp1 ":" exp1 | {":"} → shift 29
exp2: · exp2 "+" exp3 | {"?", ":", "+"} → shift 11
exp2: · exp3 | {"?", ":", "+"} → shift 13
exp3: · maybe | {"?", ":", "+"} → shift 14
exp3: · "1" | {"?", ":", "+"} → shift 15
maybe: · exp3 "?" | {"?", ":", "+"} → shift 13
State 27:
exp2: exp2 "+" · exp3 | {"?", ":", "+"} → shift 28
exp3: · maybe | {"?", ":", "+"} → shift 14
exp3: · "1" | {"?", ":", "+"} → shift 15
maybe: · exp3 "?" | {"?", ":", "+"} → shift 28
State 28:
exp2: exp2 "+" exp3 · | {":", "+"} → reduce 3
exp2: exp2 "+" exp3 · | {"?"} → reduce 3 shift 16
maybe: exp3 · "?" | {"?", ":", "+"} → reduce 3 shift 16
State 29:
ternary: exp2 "?" exp1 · ":" exp1 | {":"} → shift 30
State 30:
exp1: · ternary | {":"} → shift 10
exp1: · exp2 | {":"} → shift 11
ternary: · exp2 "?" exp1 ":" exp1 | {":"} → shift 11
ternary: exp2 "?" exp1 ":" · exp1 | {":"} → shift 31
exp2: · exp2 "+" exp3 | {"?", ":", "+"} → shift 11
exp2: · exp3 | {"?", ":", "+"} → shift 13
exp3: · maybe | {"?", ":", "+"} → shift 14
exp3: · "1" | {"?", ":", "+"} → shift 15
maybe: · exp3 "?" | {"?", ":", "+"} → shift 13
State 31:
ternary: exp2 "?" exp1 ":" exp1 · | {":"} → reduce 2