Ваша первая проблема в том, что я не думаю, что этот бит делает то, что вы хотите:
invoke ::= access LPAREN empty_stmt_list RPAREN.
empty_stmt_list ::=.
empty_stmt_list ::= stmt.
empty_stmt_list ::= empty_stmt_list COMMA stmt. [COMMA]
Производство invoke
будет соответствовать access LPAREN COMMA stmt RPAREN
, что, как я полагаю, нежелательно (и именно отсюда возникает конфликт LPAREN / COMMA).
Вы можете исправить это, выполнив это следующим образом, используя существующее правило stmt_list
:
invoke ::= access LPAREN maybe_empty_stmt_list RPAREN.
maybe_empty_stmt_list ::= .
maybe_empty_stmt_list ::= stmt_list.
Это все еще сообщает о конфликте (но только 1 сейчас) и все еще жалуется, что maybe_empty_stmt_list ::=.
не может быть уменьшено. Итак, заглянув в файл XXX.out, вы увидите, что это такое:
State 2:
...
(16) ns_identifier ::= *
...
(25) maybe_empty_stmt_list ::= *
...
RPAREN reduce 25 ** Parsing conflict **
....
{default} reduce 16
... похоже, проблема в правиле ns_identifier ::=.
. Возвращаясь к описанным производственным процессам, нетрудно понять, что пустой ns_identifier
можно уменьшить до stmt_list
(через ns_identifier
-> access
-> retval
-> expr
-> * 1023. * -> stmt_list
).
Это объясняет конфликт; и тот факт, что правило ns_identifier ::=.
предпочтительнее в этом случае, потому что оно появляется раньше в грамматике (см. правила разрешения конфликтов уменьшения / уменьшения в документации , объясняет, почему оно жалуется, что правило maybe_empty_stmt_list ::=.
никогда не уменьшайся.