If statement 如何使用yacc正确实现if语句?

If statement 如何使用yacc正确实现if语句?,if-statement,yacc,lex,If Statement,Yacc,Lex,我试图在yacc中实现一个if语句。几个月前我已经写了一些代码,但我不确定我做了什么。 这就是我要做的: if(condition_1) { z=constant_1; } else_if(condition_2) {z=constant_2;} else_if ... … … else_if(condition_N-1) {z=constant_N-1;} else { z=constant_N;} 其中条件\u 1..N-1必须仅涉及var操作(,=,!=

我试图在yacc中实现一个if语句。几个月前我已经写了一些代码,但我不确定我做了什么。 这就是我要做的:

  if(condition_1) { z=constant_1; } 
  else_if(condition_2) {z=constant_2;}
  else_if ...
  … 
  … 
  else_if(condition_N-1) {z=constant_N-1;}
  else { z=constant_N;}
其中
条件\u 1..N-1
必须仅涉及
var操作(,=,!=)-var

var operation constatnt
就像x一样,您的代码可以正常工作,但它的工作方式可能出乎意料,并且不是非常通用

实际上,语法中的
else
是误导性的。人们通常会期望

if      (condition1) { statement1; }
else if (condition2) { statement2; }
else                { statement3; }
如果
condition1
为false,则仅测试
condition2
,如果两个条件均为false,则仅执行
statement3
。但是你的代码不会短路。对每个测试进行评估,
else
子句是无条件的。看看代码,就好像
else
s不存在一样

然而,代码是有效的。为什么呢?这是因为它是反向执行的。实际上,评估过程就像上面写的一样进行

{ statement3; }
if (condition2) { statement2; }
if (condition1) { statement1; }
这仅仅是因为所有语句都被限制为设置
z
的值。因此,执行的最后一条语句将获胜,并且向后执行求值将精确地生成正确的答案

只要你明白它是如何工作的,那没关系。但这不是很普遍,也不是很有效

首先,它是如何工作的。粗略地说,上下文无关语法可以用两种方式表示列表:

left_list : element | left_list element
right_list: element | element right_list
这两个公式识别相同的输入,但它们表示不同的解析。在操作符的情况下,我们称之为左关联和右关联。对于列表,不同之处在于元素添加到列表中的方式:在
左侧列表中,连续元素添加到列表的末尾,而在
右侧列表中,元素添加到列表的开头

如果向上述产品添加了创建列表的操作,则必须将
元素
推到
左列表
的末尾,但将
元素
移到
右列表
的开头。但这不仅仅是新元素被添加到列表的哪一边。这也是副作用评估的顺序

重要的一点是,内部列表是在它出现在产品中时完全构建的。在
left_list
的情况下,这种构造发生在
元素
被解析之前,因此
left_list
操作中的副作用从左到右进行评估。在
right\u list
的情况下,构造发生在末尾,因此所有的求值都会堆积起来,直到最终的
right\u list:element
生产减少。只有这样,当其他操作从堆栈中弹出时,才能对其进行评估

(这不会影响
元素
元素
的操作中副作用的顺序始终从左到右处理。)

语法中有两种类型的列表:程序本身和
if
语句。程序是一个左侧的规则列表,副作用在规则操作中,从左到右进行评估。但是
if
语句是正确的子句列表(其中递归以不同的元素终止,
else
子句),副作用在列表操作中。这就是为什么它会反向计算

现在,如果目的是只解析一次输入并对其求值,那么很明显,解析整个表达式然后扔掉所有东西,但第一个成功的条件并不完全有效。当遇到真实情况时,最好停止。此外,从左到右评估并在发现真实情况时停止将避免出现副作用而不仅仅是抵消以前的副作用时出现的问题。因此,更普遍的解决方案不会依赖于反向评估


此外,正确的递归产品确实使用堆栈。如果
If
语句有很多子句,它将使用很多解析器堆栈。它甚至可能超过解析器的堆栈限制。

您的代码可以工作,但是它的工作方式可能是意外的,并且不是非常通用

实际上,语法中的
else
是误导性的。人们通常会期望

if      (condition1) { statement1; }
else if (condition2) { statement2; }
else                { statement3; }
如果
condition1
为false,则仅测试
condition2
,如果两个条件均为false,则仅执行
statement3
。但是你的代码不会短路。对每个测试进行评估,
else
子句是无条件的。看看代码,就好像
else
s不存在一样

然而,代码是有效的。为什么呢?这是因为它是反向执行的。实际上,评估过程就像上面写的一样进行

{ statement3; }
if (condition2) { statement2; }
if (condition1) { statement1; }
这仅仅是因为所有语句都被限制为设置
z
的值。因此,执行的最后一条语句将获胜,并且向后执行求值将精确地生成正确的答案

只要你明白它是如何工作的,那没关系。但这不是很普遍,也不是很有效

首先,它是如何工作的。粗略地说,上下文无关语法可以用两种方式表示列表:

left_list : element | left_list element
right_list: element | element right_list
这两个公式识别相同的输入,但它们表示不同的解析。在操作符的情况下,我们称之为左关联和右关联。对于列表,不同之处在于元素添加到列表中的方式:在
左侧列表中,连续元素添加到列表的末尾,而在
右侧列表中,元素添加到列表的开头

如果向上述产品添加了创建列表的操作,则必须将
元素
推到
左列表
的末尾,但将
元素
移到
右列表
的开头。但这不仅仅是名单的哪一边是新的