我收到以下错误:
Warning : *** Shift/Reduce conflict found in state #2
between ExitLoopStatement ::= EXITLOOP (*)
and VarAccess ::= (*) DOLLAR IDENTIFIER
under symbol DOLLAR
这是我使用的语法。目前我有赋值和break(每个break语句可以指定退出的循环级别数)。
start with StatementList;
StatementList
::= Statement
|
StatementList Statement
;
Statement
::= AssignmentStatement
|
ExitLoopStatement
;
AssignmentStatement
::= VarAccess EQ_OP VarAccess
;
VarAccess
::= DOLLAR IDENTIFIER
;
ExitLoopStatement
::= EXITLOOP
|
EXITLOOP VarAccess
;
根据我的理解,问题是在我遇到EXITLOOP之后,下一个令牌可以是作业的开始或退出的等级数。
有什么方法可以解决这个问题吗?
谢谢!
答案 0 :(得分:2)
实际上,如果您的语言允许语句可选地以可能启动另一个语句的内容结束,并且语言不需要在语句之间显式标点符号,那么您将无法使用有限的先行解析器来解析它。
在这个非常简单的情况下,你可以使用LR(3)解析器解析你的语言,这意味着存在LR(1)语法(虽然它不会非常易读)。但是,当您向该语言添加更多语法时,您可能会发现所需的前瞻开始增加,甚至变得无限制。 (例如,如果您实现数组并允许下标为任意表达式,则会发生这种情况。)
只要该语言实际上不明确,您仍然可以使用GLR解析器解析它。不幸的是,CUP没有提供这个选项,我也不确定野牛的Java框架是否允许它。
总的来说,最简单的解决方案是坚持语句分隔符/终止符(如Java中的; )或删除可能与语句开头混淆的可选尾随语法。例如,如果您将exit $x
更改为exit ($x)
并且不允许语句以开头(那么您将不会遇到解析冲突。