减少/减少与无类型变量和函数调用的冲突

时间:2014-11-23 10:14:39

标签: compiler-construction bison yacc dynamic-typing reduce-reduce-conflict

我想为动态类型语言创建一个解析器。

在我的野牛文件中,我有runtimetyped的规则,它是变量名或函数调用。

runtimetyped : T_ID { $$ = create_identifier($1); }
             | call { $$ = $1; }
             ;

我还想在编译时进行一些基本的类型检查。 F.E.我不想允许像

这样的东西
x = "string" + 42 <= true;

在源代码中,我想创建一个编译时错误。

但是像

这样的东西
s = "string";
i = 42;
b = true;
x = s + i <= b;

应该产生运行时错误。

我的方法是在语法中有不同的表达方式:

expression : bool_expression
           | math_expression
           | string_expression
           ;

以及其中任何expressions都由termsfactors等构建。
factor始终也可能是runtimetyped,导致reduce/reduce错误。

math_factor : numeric_literal                   { $$ = $1; }
            | runtimetyped                      { $$ = $1; }
            | T_LPAREN math_expression T_RPAREN { $$ = $2; }
            ;

bool_factor : T_BOOL                            { $$ = create_bool($1); }
            | runtimetyped                      { $$ = $1; }
            | compare                           { $$ = $1; }
            | T_LPAREN bool_expression T_RPAREN { $$ = $2; }
            ;

string_expression : T_STRING                                    { $$ = $1; }
                  | runtimetyped                                { $$ = $1; }
                  | string_expression T_STROP string_expression { $$ = create_expression($2, $1, $3); }
                  ;

我用bison -v parser.y运行它。

任何人都可以告诉我如何解决冲突和/或究竟是什么导致冲突。

提前感谢。

1 个答案:

答案 0 :(得分:1)

在编译期间键入检查的最佳方法是对AST进行分析传递。为了提供准确的错误消息,您需要保留AST中每个令牌的位置信息,但这通常很有用。

在构建AST之后进行语义分析的优点是代码更清晰,因为它不会将语义分析与其他任务混合在一起。它还允许您使用更多信息,例如类型声明。但是,如果您不想这样做,您还可以在每个生产的操作中进行类型检查。这将语义分析扩展到整个语法,恕我直言更难理解,验证,测试和维护。不过,有可能。

将语义检查转换为语法错误实际上是最糟糕的做事方式。它不必要地使语法复杂化,并且使得生成良好的错误消息变得更加困难,因为类型错误实际上不是语法错误,并且大多数尝试用您的语言编写代码的人会因为语法错误而在语法上接受语法错误而感到困惑无意义的构造。

尽管如此,这是可能的。但是,您需要非常小心地避免语法模糊,这通常会表现为减少/减少冲突,这正是您所看到的。 (您没有提供足够的语法来诊断确切的问题,但您可以通过使用-v标志处理语法bison来自己完成,然后检查生成的.output } file,它将显示存在冲突的状态。)

冲突的最可能原因是单位制作的解决,在x_expressiony_expression都可能的情况下(不看前瞻标记)。在这里,您可能需要执行其中一个作品x_expression: x_factory_expression: y_factor,这反过来意味着您可能需要x_factor: runtimetypedy_factor: runtimetyped中的一个,但可能无法做出决定。 (这是LALR(1)州合并可能造成“神秘”冲突的案例之一。)