我正在尝试编写一个小解析器。不幸的是,我得到了“轮班减少冲突”。语法不是我的强项,我只需要完成这一小事。这是产生错误的简化语法:
stmts_opt -> stmts
;
stmts -> stmt
| stmts stmt
| stmsts
;
stmt -> id
| ITERATE content_stmt
| IF test then content_stmt ELSE content_stmt
| IF test then content_stmt
;
content_stmt: BEGIN stmt_opt END
| stmt
;
提供修改过的语法的解决方案将受到高度赞赏。
修改:
我修改了我的语法适合@ rici的答案,但问题仍然存在。这是我的实际语法产品:
prog: BEGIN_PROG def_sprogram BEGIN_EXEC stmts_opt END_EXEC END_PROG
{ () }
;
def_sprogram: /* empty */ { () }
| define_new def_sprogram { () }
;
define_new: DEFINE_NEW_INSTRUCTION ID AS content_stmt SEMI { }
;
stmts_opt: /* empty */ { () }
| stmts { () }
;
stmts: stmt { () }
| stmts SEMI stmt { () }
| stmts SEMI { () }
;
content_stmt: BEGIN stmts_opt END { () }
| stmt { () }
;
stmt: open_stmt { () }
| closed_stmt { () }
;
open_stmt: ITERATE INT TIMES open_stmt { () }
| WHILE test DO open_stmt { () }
| IF test THEN closed_stmt ELSE open_stmt { () }
| IF test THEN stmt { () }
;
closed_stmt: simple_stmt { () }
| ITERATE INT TIMES closed_stmt { () }
| WHILE test DO closed_stmt { () }
| IF test THEN closed_stmt ELSE closed_stmt { () }
;
以下是我正在测试的示例:
BEGINNING-OF-PROGRAM
BEGINNING-OF-EXECUTION
IF not-next-to-a-beeper THEN
move;
IF not-facing-north THEN
turnleft;
ELSE <--- ERROR
turnleft;
IF not-facing-east THEN
IF not-facing-west THEN
turnleft;
turnoff
END-OF-EXECUTION
END-OF-PROGRAM
我在第一个ELSE
收到错误。我还尝试按照@rici的建议声明一个简单的优先级:
%nonassoc THEN
%nonassoc ELSE
但是这也没有解决错误。
答案 0 :(得分:1)
最简单的解决方案是&#34;悬挂其他&#34; shift-reduce冲突是强制解决支持转移Group/Column
令牌。由于camlyacc支持优先级声明(根据我能够找到的相当粗略的文档),这应该就像在声明部分(在第一个ELSE
之前)添加以下内容一样简单:
%%
(关联性并不重要,因为%nonassoc THEN
%nonassoc ELSE
和THEN
可以关联的语法中没有任何内容。)
如果你想使用明确的&#34;匹配/不匹配&#34; (或&#34;打开/关闭语句&#34;),只需注意ELSE
是&#34;匹配&#34; (或&#34;已关闭&#34;声明)因为它无法接受BEGIN stmts_opt END
。其他匹配的陈述是
THEN
不匹配的陈述是
matched_stmt: BEGIN stmts_opt END
| ITERATE matched_stmt
| IF test THEN matched_stmt ELSE matched_stmt
| /* Any other kind of simple statement */
许多人更喜欢创建包含unmatched_stmt: ITERATE unmatched_stmt
| IF test THEN matched_stmt
| IF test THEN unmatched_stmt
| IF test THEN matched_stmt ELSE unmatched_stmt
和matched_stmt
的非终端。但是,在您的情况下,您似乎不想嵌套unmatched_stmt
... BEGIN
块,将它们限制为复合语句的内容。因此,对于END
右侧,您的stmt
将是以上所有,除外。