【问题标题】:reduce/reduce conflict with untyped variables and function calls减少/减少与无类型变量和函数调用的冲突
【发布时间】:2014-11-23 10:14:38
【问题描述】:

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

在我的野牛文件中,我有一个 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 运行它。

谁能给我一个关于如何解决这个冲突和/或究竟是什么导致冲突的提示。

提前致谢。

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    冲突最可能的原因是单元生产的解决,在x_expressiony_expression 都可能出现的上下文中(不查看前瞻标记)。在这里,您可能需要执行x_expression: x_factory_expression: y_factor 之一,这反过来意味着您可能需要x_factor: runtimetypedy_factor: runtimetyped 之一,并且可能无法做出该决定。 (这是LALR(1) 状态合并会造成“神秘”冲突的情况之一。)

    【讨论】:

    • 感谢您的回答和解释。我将降低语法复杂性并在解析后添加语义检查。那么应该可以只使用一个expressiontype 来消除歧义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多