Я реализую синтаксический анализатор для подмножества Java, используя Java CUP.
Грамматика похожа на
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
, когда анализатор видит идентификатор, онхочет уменьшить его, но не знает, какое уменьшить, type
или exp
.
stmt ::= ID LBRACKET exp RBRACKET ASSIGN exp SEMI
для назначения элемента в массиве, например
arr[key] = value;
exp :: exp LBRACKET exp RBRACKET
для выражения получения элемента из массива, например
arr[key]
Таким образом, в случае arr[key]
, когда анализатор видит arr
, он знает, что это идентификатор, но не знает, должен ли он сдвигаться или уменьшаться до exp
.
Однако яПонятия не имею, как это исправить, пожалуйста, дайте мне несколько советов, если у вас есть, большое спасибо.