如何使用yacc解析/ else语句

时间:2019-04-07 20:22:44

标签: c parsing token yacc lex

我正在尝试创建一个.y文件,以设计基本编程语言,其中终端值仅是true和false。但是,我很难为if语句定义规则。 if语句的语法类似;

a=TRUE
if TRUE: print(a)

我的BNF就像;

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

其中IF是关键字if和':'的冒号的标记。但是当我编译文件时,出现以下错误;

  

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

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

>

1 个答案:

答案 0 :(得分:3)

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

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

您的操作if($2==true){$$ = $4;}要求$$ifexpression),$2expression)和$4statement)全部都有声明的类型。如果野牛只抱怨其中的一种,那么您知道如何声明类型,因为另外两种已经声明过了。否则,如果您有许多此类错误,则应查看relevant section in the bison manual。您可能还需要阅读semantic values上的整个章节。

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

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