我有一个简单的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 :: =”。因为它没有连接到开始符号。我打赌它是: - )
“invoke”也存在解析冲突,当empty_stmt_list确实是一个empy语句列表时,它无法在RPAREN和COMMA之间做出决定。
我想要实现的是能够解析没有(void)参数的函数调用。
其他一切都按预期工作。
由于
编辑:我编辑了我原来的帖子并发布了整个剥离的语法。
答案 0 :(得分:4)
你的第一个问题是我不认为这一点符合你的要求:
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
- > {{ 1}} - > retval
- > expr
- > stmt
)。
这解释了冲突;事实上stmt_list
规则在这种情况下是有利的,因为它出现在语法的早期(参见documentation中解决减少 - 减少冲突的规则解释了为什么它抱怨ns_identifier ::=.
规则永远不会减少。
答案 1 :(得分:0)
您可以尝试为LPAREN / COMMA添加优先规则,并检查它是否会影响其他地方的语义。