0

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

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

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

我还想在编译时做一些基本的类型检查。fe我不想允许这样的事情

x = "string" + 42 <= true;

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

但是像

s = "string";
i = 42;
b = true;
x = s + i <= b;

应该会产生运行时错误。

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

expression : bool_expression
           | math_expression
           | string_expression
           ;

并且其中任何一个expressions都是由terms,等建立的factors
afactor也可以总是runtimetyped导致reduce/reduce错误的 a。

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

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

提前致谢。

4

1 回答 1

1

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

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

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

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

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

于 2014-11-23T17:21:33.440 回答