我有一个简单的LALR(1)语法,但是遇到问题。
start ::= spec.
spec ::= MOD STRING top_stmt.
spec ::= top_stmt.
top_stmt ::= stmt.
top_stmt ::= conditional.
stmt ::= expr.
stmt ::= assignment.
conditional ::= IF stmt_list.
expr ::= retval.
expr ::= NOT retval.
retval ::= access.
retval ::= invoke.
access ::= ns_identifier OBJECT_OPERATOR property_chain.
access ::= ns_identifier.
ns_identifier ::= identifier.
ns_identifier ::= ns_identifier NS_SEPARATOR identifier.
ns_identifier ::=.
property_chain ::= property_chain OBJECT_OPERATOR identifier.
property_chain ::= identifier.
identifier ::= VARIABLE.
identifier ::= STRING.
assignment ::= access ASSIGN expr. [ASSIGN]
stmt_list ::= stmt.
stmt_list ::= stmt_list COMMA stmt. [COMMA]
invoke ::= access LPAREN empty_stmt_list RPAREN.
empty_stmt_list ::=.
empty_stmt_list ::= stmt.
empty_stmt_list ::= empty_stmt_list COMMA stmt. [COMMA]
点标记规则的结尾,括号之间的端子具有关联性:ASSIGN是右关联,COMMA是左关联。
但是lemon说它不能减少规则“ empty_stmt_list :: =”。因为它没有连接到开始符号。我敢打赌 :-)
“调用”还存在解析冲突,当empty_stmt_list确实是一个Empy语句列表时,它无法在RPAREN和COMMA之间进行决定。
我要实现的目标是能够解析没有(无效)参数的函数调用。
其他所有工作均按预期进行。
谢谢
编辑:我已经编辑了原始帖子,并发布了完整的语法摘要。
最佳答案
您的第一个问题是,我认为这不符合您的要求:
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
-> -> stmt
)。这就解释了冲突;以及
stmt_list
规则在这种情况下受到青睐的事实,因为它出现在语法的前面(请参见documentation中解决reduce-reduce冲突的规则,解释了为什么它抱怨永远无法简化ns_identifier ::=.
规则。