野牛:结构不好

Bison: Bad if structure

本文关键字:结构 野牛      更新时间:2023-10-16

我已经在bison中做了一个完整的解析器(当然还有flex中的完整词法分析器(,我昨天才注意到我的解析器有问题。在 If 结构中。

以下是我在解析器中的规则: http://pastebin.com/TneESwUx

在这里无法识别单个 IF,如果我将"%prec IFX"替换为"END",通过添加新的标记"END"("end" return END; 在 flex 中(,它可以工作。但我不想有一个新的"结束"关键字,这就是我不使用此解决方案的原因。

请帮助我。

'处理这种规则的正确方法不是优先级,而是重构使用可选的 else-part,以便解析器可以使用令牌前瞻来决定如何解析。 我会设计成这样:

stmt      : IF '(' expression ')' stmts else_part
          | /* other statement productions here */
else_part : /* optional */
          | ELSE stmts
stmts     : stmt
          | '{' stmt_list '}'
          | '{' '}'
stmt_list : stmt
          | stmt_list ';' stmt

(这种特殊大小写stmts而不是允许stmt包含块的方法在制作方面可能不是最佳的,并且可能会在您的语言中引入奇怪之处,但没有更多细节,很难确定。 bison可以生成一份报告,向您显示它生成的解析器的工作原理;你可能想研究它。 还要注意意外的转移/减少冲突,尤其是任何减少/减少冲突。

注意 shift/reduce 冲突在这种语法中是完全正常的; LALR(1( 解析器的要点是将这些冲突作为一个特性, 通过单个标记来解决冲突。 它们被专门报告,以便您可以更轻松地检测您想要的那些,您通过错误分解语法引入的。

你的IfExpression也需要重构以匹配;诀窍是else_part应该产生某种条件表达式来$$,并且在IF的生产中你测试$6(对应于else_part(并调用适当的IfExpression构造函数。

你的语法模棱两可,所以你必须忍受转移/减少冲突。END 令牌通过确保 IF 语句始终正确闭合(如一对括号(来消除歧义。

括号在这里是一个很好的类比。假设你有这样的语法:

maybe_closed_parens : '(' stuff
                    | '(' stuff ')'
                    ;

stuff本身生成一些语法符号,其中之一是 maybe_closed_parens

所以如果你有像 ((((((whatever 这样的输入,这是正确的。括号不必关闭。但是,如果您添加)呢?它正在关闭哪(

这很像无法分辨哪个IFELSE匹配。

如果将END添加到IF的语法中(无论是否存在ELSE(,那么这就像有一个右括号。 IFEND就像().

当然,您在风格上不希望在您的语言中END这个词是正确的,因为您已经有了卷曲的支撑块,这基本上是 Pascal's BEGINEND 的替代拼写。您的}已经是一个END关键字。

因此,您可以做的是强加一个规则,即IF只接受复合语句(即完全大括号(:

if_statement : IF condition compound_statement
             | IF condition compound_statement ELSE compound_statement

现在不可能有歧义,比如 if x 如果 y w else z,因为大括号必须存在:if x { if y { w } else { z } } or if x { if y { w } } else { z } .

我似乎记得 Perl 是做出这种选择的语言的一个例子。这不是一个坏主意,因为它不仅消除了你的歧义,更重要的是它消除了程序中的歧义。

我看到您的语法中没有compound_statement短语结构规则,因为您的语句会生成一个用{括起来的短语,并直接}。如果你采用这种方法,你将不得不破解它。