减少/减少与无类型变量和函数调用的冲突
我想创建一个动态类型语言的解析器。减少/减少与无类型变量和函数调用的冲突
在我的野牛档案我有一个规则为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
由terms
,factors
的建立,等等。
a 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
运行它。
任何人都可以给我一个关于如何解决冲突和/或究竟是什么导致冲突的提示。
在此先感谢。
编译期间键入检查的最佳方法是对AST进行分析。为了提供准确的错误消息,您需要保留AST中每个标记的位置信息,但这通常很有用。
构建AST之后进行语义分析的优点是代码更清晰,因为它不会将语义分析与其他任务混合在一起。它还允许您使用更多信息,例如类型声明。但是,如果您不想这样做,则还可以在每个生产的操作中进行类型检查。这扩大了整个语法的语义分析,恕我直言很难理解,验证,测试和维护。尽管如此,这是可能的。
将语义检查转换为语法错误确实是最糟糕的做法。它不必要地使语法复杂化,并且使得生成好的错误消息变得更加困难,因为类型错误实际上不是语法错误,并且大多数尝试用您的语言编写代码的人会因语法错误而在语义上接收语法错误而感到困惑无意义的构造。
尽管如此,这是可能的。但是,您需要非常小心以避免语法歧义,这通常会显示为减少/减少冲突,这正是您所看到的。 (您没有提供足够的语法来诊断确切的问题,但是您可以自己做,通过将-v
标志的文法处理为bison
,然后检查生成的.output
文件,该文件将向您显示存在的状态冲突。)
冲突最可能的原因是单位生产的解决方案,在x_expression
和y_expression
都可能的情况下(无需查看先行令牌)。在这里,您可能需要执行x_expression: x_factor
或y_expression: y_factor
之一的制作,这意味着您可能需要x_factor: runtimetyped
或y_factor: runtimetyped
之一,并且可能无法做出该决定。 (这是LALR(1)
状态合并可能造成“神秘”冲突的情况之一。)
感谢您的回答和解释。我将减少语法复杂度并在解析后添加语义检查。那么应该可以只使用一个'表达式'来消除模糊性。 – linluk 2014-11-24 07:33:00