LALR(1) 函数参数的空列表

发布于 2024-08-18 10:41:43 字数 1293 浏览 8 评论 0原文

我有一个简单的 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确实是一个空的语句列表时,它无法在RPAREN和COMMA之间做出决定。

我想要实现的是能够解析没有(空)参数的函数调用。

其他一切都按预期进行。

谢谢

编辑:我已经编辑了我的原始帖子并发布了整个精简语法。

I have a simple LALR(1) grammar, but I'm encountering a problem.

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]

The dot marks the end of the rule, terminals between brackets have associativity assigned to them: ASSIGN is right-associative, COMMA is left-assoc.

But lemon says it can't reduce the rule "empty_stmt_list ::=." because it's not connected to the start symbol. I bet it is :-)

There is also a parsing conflict for "invoke", it cannot decide between RPAREN and COMMA when empty_stmt_list is indeed an empy list of statements.

What I'm trying to achieve is being able to parse function calls which have no (void) parameters.

Everything else works as expected.

Thanks

Edit: I have edited my original post and posted the entire stripped down grammar.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故人的歌 2024-08-25 10:41:43

您的第一个问题是,我认为这并不符合您的要求:

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 -> <代码>访问-><代码>retval-><代码>表达式-><代码>stmt-><代码>stmt_list >)。

这就解释了冲突;事实上, ns_identifier ::=. 规则在这种情况下受到青睐,因为它出现在语法中的较早位置(请参阅 文档解释了为什么它抱怨 maybe_empty_stmt_list ::=. 规则永远无法减少。

Your first problem is that I don't think this bit does what you want it to:

invoke ::= access LPAREN empty_stmt_list RPAREN.
empty_stmt_list ::=.
empty_stmt_list ::= stmt.
empty_stmt_list ::= empty_stmt_list COMMA stmt. [COMMA]

The invoke production will match access LPAREN COMMA stmt RPAREN, which I assume is not desirable (and is where the LPAREN/COMMA conflict is coming from).

You can fix that by doing it like like this, which makes use of your existing stmt_list rule:

invoke ::= access LPAREN maybe_empty_stmt_list RPAREN.
maybe_empty_stmt_list ::= .
maybe_empty_stmt_list ::= stmt_list.

That still reports a conflict (but only 1 now) and still complains that maybe_empty_stmt_list ::=. can't be reduced. So, looking in the XXX.out file to see what it is:

State 2:
...
     (16) ns_identifier ::= *
...
     (25) maybe_empty_stmt_list ::= *
...
                        RPAREN reduce 25  ** Parsing conflict **
....
                     {default} reduce 16

...it appears that the problem is with the ns_identifier ::=. rule. Working back through the productions involved, it's not too difficult to see that an empty ns_identifier can be reduced to stmt_list (via ns_identifier -> access -> retval -> expr -> stmt -> stmt_list).

That explains the conflict; and fact that the ns_identifier ::=. rule is favoured in this case because it appears earlier in the grammar (see the rules for resolving reduce-reduce conflicts in the documentation explains why it complains that the maybe_empty_stmt_list ::=. rule can never be reduced.

十级心震 2024-08-25 10:41:43

您可以尝试为 LPAREN/COMMA 添加优先规则,并检查它是否影响其他地方的语义。

You may try adding precedence rules for LPAREN/COMMA and check if it affects the semantics in other places.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文