转移/减少Java Cup中的冲突

时间:2016-11-09 13:23:44

标签: java parsing grammar cup

我收到以下错误:

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之后,下一个令牌可以是作业的开始或退出的等级数。

有什么方法可以解决这个问题吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

实际上,如果您的语言允许语句可选地以可能启动另一个语句的内容结束,并且语言不需要在语句之间显式标点符号,那么您将无法使用有限的先行解析器来解析它。

在这个非常简单的情况下,你可以使用LR(3)解析器解析你的语言,这意味着存在LR(1)语法(虽然它不会非常易读)。但是,当您向该语言添加更多语法时,您可能会发现所需的前瞻开始增加,甚至变得无限制。 (例如,如果您实现数组并允许下标为任意表达式,则会发生这种情况。)

只要该语言实际上不明确,您仍然可以使用GLR解析器解析它。不幸的是,CUP没有提供这个选项,我也不确定野牛的Java框架是否允许它。

总的来说,最简单的解决方案是坚持语句分隔符/终止符(如Java中的; )或删除可能与语句开头混淆的可选尾随语法。例如,如果您将exit $x更改为exit ($x)并且不允许语句以开头(那么您将不会遇到解析冲突。