使用链接比较运算符评估二进制表达式树

时间:2015-04-08 19:54:16

标签: data-structures compiler-construction tree bison

我正在构建一个二进制表达式树(用于玩具脚本语言),到目前为止,我的算术运算正常(即4 * (5 + 6));现在我想添加对比较运算符的支持。使用0 < 1这样的简单二进制比较很容易做到这一点,但是当我将它们链接在一起时,我遇到了问题。例如,这个表达式:

0 < 1 < 2

目前生成以下二进制表达式树:

    <
   / \
  <   2
 / \
0   1

我正在使用递归将树遍历到叶节点并返回值,因此首先处理0 < 1,然后(正确地)返回True。问题是,下一级别是比较True < 2,应该比较True && (1 < 2)

解决此问题的最佳方法是什么?我以为我最终可能不得不以不同的方式构建我的树。即。

       &&
      /  \
     /    \
    <      <
   / \    / \
  0   1  1   2

但我希望在我的野牛解析器解决方案中实现更优雅/稍微复杂一点的实现。

1 个答案:

答案 0 :(得分:1)

本质上,一系列链式比较是单个运算符,而不是一系列二元运算符。将a < b < c (a < b) && (b < c)置于b是不精确的,因为它会对T进行两次评估。因此,如果你的AST允许的话,你可能只是将它变成一个n-ary运算符。

如果您有一个有区别的联合类型,也可以使它与一系列二元运算符一起使用。在这种情况下,一个非常简单的区分联合就足够了。

false成为值为false或任何整数的类型。 (此处,0与任何整数都是 distinct ,因此它与<不同。)

现在,我们将integer a < integer b ==> T if a is less than b, then b; otherwise false T a < integer b ==> T if a is false, then false; otherwise a < b (as above) 定义如下:

T

对于链式比较的中间结果的任何使用,必须将false结果转换为布尔值;我们这样做是显而易见的:a < b == c < d # Chained comparison 映射到布尔值false,任何整数映射到布尔值true。

隐式转换为布尔值的结果是

(a < b) == (c < d)  # Comparison of two booleans

不同
{{1}}

这基本上是Python的语义,例如。 以上可以使用任何可订购类型替换整数。


为了实现链式比较,您需要在语法中正确管理带括号的比较。通常的简单AST构造只删除括号将无效。