我正在使用 Java CUP 为 Java 子集实现解析器。
语法就像
vardecl ::= type ID
type ::= ID | INT | FLOAT | ...
exp ::= ID | exp LBRACKET exp RBRACKET | ...
stmt ::= ID ASSIGN exp SEMI
这工作正常,但是当我添加
stmt ::= ID ASSIGN exp SEMI
|ID LBRACKET exp RBRACKET ASSIGN exp SEMI
CUP 不起作用,警告是:
Warning : *** Shift/Reduce conflict found in state #122
between exp ::= identifier (*)
and statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI
under symbol LBRACKET
Resolved in favor of shifting.
Warning : *** Reduce/Reduce conflict found in state #42
between type ::= identifier (*)
and exp ::= identifier (*)
under symbols: {}
Resolved in favor of the first production.
Warning : *** Shift/Reduce conflict found in state #42
between type ::= identifier (*)
and statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI
under symbol LBRACKET
Resolved in favor of shifting.
Warning : *** Shift/Reduce conflict found in state #42
between exp ::= identifier (*)
and statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI
under symbol LBRACKET
Resolved in favor of shifting.
我认为有两个问题:
1.type ::= ID
并且exp ::= ID
,当解析器看到一个 ID 时,它想要减少它,但它不知道要减少哪个,type
或者exp
.
stmt ::= ID LBRACKET exp RBRACKET ASSIGN exp SEMI
用于分配数组中的元素,例如arr[key] = value;
exp :: exp LBRACKET exp RBRACKET
用于从数组中获取元素的表达式,例如arr[key]
所以在这种情况下arr[key]
,当解析器看到 时arr
,它知道它是一个ID,但它不知道它是否应该转移或减少到exp
。
但是,我不知道如何解决这个问题,如果你有的话,请给我一些建议,非常感谢。