首页 > 解决方案 > 如何使用 yacc 解析 if /else 语句

问题描述

我正在尝试创建一个 .y 文件来设计基本编程语言,其中终端值只是真假。但是,我很难为 if 语句定义规则。if 语句的语法是这样的;

a=TRUE
if TRUE: print(a)

我的 BNF 就像;

statement : assignment | ifstatement | print
ifstatement : IF expression COLON statement                {if($2==true){$$ = $4;}}

其中 IF 是关键字 if 的标记,COLON 是 ':'。但是当我编译我的文件时,我得到了以下错误;

'ifstatement' 的 $4 没有声明类型 ifstatement:IF 表达式冒号语句 {if($2==true){$$ = $4;}}

所以,我的问题是除了{if($2==true){$$ = $4;}}之外的 if else 语句我应该使用什么规则?

标签: cparsingtokenyacclex

解决方案


bison 抱怨的问题是您分配给$$,这是 的语义值ifstatement,但您没有告诉 bison 的类型ifstatement是什么。就像在 C 中一样,如果你有一个变量,你需要声明它的类型。

这假定您已经告诉 bison 并非所有语法符号都具有相同的类型。换句话说,您有一个%union声明,它为您正在使用的所有不同类型指定标签名称。%token然后,您需要声明所有具有 using和%type声明值的标记和非终结符的类型。

您的操作if($2==true){$$ = $4;}要求$$( ifexpression)、$2( expression) 和$4( statement) 都已声明类型。如果野牛只抱怨其中一个,那么您知道如何声明类型,因为已经声明了其他两个。否则,如果你有很多这样的错误,那么你应该查看野牛手册中的相关部分。您可能还想阅读有关语义值的整章。

但是,以上都没有解决该操作的真正问题,这与您解释程序代码的方法有关。如果条件实际上为真,if则期望语句仅评估其分支。true但是请注意$4,无论条件是否为真,在执行您的操作之前已经计算了 的值。该操作所做的只是将已经计算的 值转发statement到 的值中ifstatement。另外,请注意,$$如果条件为 ,则未分配任何内容false。所以它的值要么是 of$4要么是未初始化的,在后一种情况下,尝试使用它的值将是未定义的行为。

这就是为什么在解析期间无法评估任何非平凡语言的原因。条件块只能在条件语句被解析后才能评估,因此需要推迟它们的评估。重复的块——for例如while语句——必须被多次评估,尽管它们只被解析一次。


推荐阅读