1

我收到以下错误:

Warning : *** Shift/Reduce conflict found in state #2
  between ExitLoopStatement ::= EXITLOOP (*) 
  and     VarAccess ::= (*) DOLLAR IDENTIFIER 
  under symbol DOLLAR

这是我使用的语法。目前我有分配和中断(每个中断语句都可以指定要退出的循环级别数)。

start with StatementList;

StatementList
    ::= Statement
    |
        StatementList Statement
    ;

Statement
    ::= AssignmentStatement
    |
        ExitLoopStatement
    ;

AssignmentStatement
    ::= VarAccess EQ_OP VarAccess
    ;

VarAccess
    ::= DOLLAR IDENTIFIER
    ;

ExitLoopStatement
    ::= EXITLOOP
    |
        EXITLOOP VarAccess
    ;

据我了解,问题是在我遇到 EXITLOOP 之后,下一个标记可能是分配的开始或要退出的级别数。

有没有办法解决这个问题?

谢谢!

4

1 回答 1

2

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

在这个极其简单的情况下,您可以使用 LR(3) 解析器来解析您的语言,这意味着存在 LR(1) 语法(尽管它的可读性不是很高)。但是,当您向语言中添加更多语法时,您可能会发现所需的前瞻开始增加,甚至变得无界。(例如,如果您实现数组并允许下标是任意表达式,就会发生这种情况。)

只要该语言实际上不是模棱两可的,您仍然可以使用 GLR 解析器对其进行解析。不幸的是,CUP 不提供这个选项,我也不确定 bison 的 Java 框架是否允许它。

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

于 2016-11-09T17:23:17.450 回答