我正在尝试创建自己的LR(0)解析器,而且我遇到了一些语法问题。
基本上,语法
exp: mexp
mexp: '1'
mexp: mexp '*' '1'
我的解析器正在输出
State 0: • 1
| • mexp
| • exp
| • mexp * 1
State 1: 1 •
State 2: exp •
State 3: mexp • * 1
| mexp •
State 4: mexp * • 1
State 5: mexp * 1 •
带警告
(state 3, *) already has reduction: exp: mexp
我的程序为这个语法派生的LR(0)表是:
'1' exp mexp '*' $
State 0: s1 s2 s3
State 1: r3 r3 r3
State 2: acc
State 3: r2 s4 r2
State 4: s5
State 5: r4 r4 r4
其中$表示文件的结尾。
警告源于这样一个事实:状态3 - 对应于mexp • * 1 | mexp •
- 两者减少r2
和状态输入s4
的转化*
。
但似乎according to Wikipedia,这不应该发生 - 我应该只有减少:
如果项目 i 包含A→w形式的项目,而A→w是规则 m ,其中 m > 0然后动作表中状态 i 的行完全用reduce动作r m 填充。
有趣的是,当我删除规则exp: mexp
时,我没有遇到任何此类冲突。
所以我弄清楚的是,这确实是语法中的一个真正的问题吗?
(换句话说,这个语法实际上不是LR(0)吗?)
我不相信这种情况,但我不确定。
如果是这样,为什么?如果没有,那么什么是错的? (我的桌子错了,还是我做错了什么?)
答案 0 :(得分:1)
(更仔细阅读维基百科页面后。)
维基百科的报价是(重点补充):
如果一个项目集i包含一个形式为A→w的项目,而A→w是规则m ,其中m> 0 然后动作表中状态i的行完全用reduce动作r m 填充。
规则0是增强的开始规则,在您的情况下应该是:
start : mexp '$'
(就个人而言,我更喜欢明确地添加EOF令牌;这样的例外情况就更少了。)
但是,我认为你得到的是:
start : exp '$'
exp : mexp
实际上不是LR(0),因为单位缩减规则(exp→mexp)会导致您发现的移位减少冲突。
如果规则是用明确的结束标记写的,那么维基百科文章对m = 0
的例外是不必要的;在这种情况下,动作acc
是根据修改的动作3生成的:
- “$”(输入结束)的额外列添加到操作表中,该表包含每个包含S→E的项目集合的acc•'$'。
醇>
(实际上,你不需要“额外列”部分;使用明确的结束标记你应该已经有了一个列。重点是用acc动作覆盖shift行动。)