【问题标题】:Calculator in Bison , and double or int valuesBison 中的计算器,以及 double 或 int 值
【发布时间】:2015-03-03 00:27:48
【问题描述】:

我想使用 flex/bison 创建一个计算器。我创建了以下%union

%union{
     int intValue;
     double realValue;
     char * numType;
}

因此,当我想简化为 term: primary 之类的规则时,我会检查 numType 是“INT”还是“REAL”,然后执行以下操作:

$<realValue>$=$<realValue>1; $<numType>$=$<numType>1;

(对于 intValue 也是一样的)。现在的问题是,当我有这样的规则时:

term:
  expr '+' expr |
  expr '*' expr |                          
  ...

如果条款是实数还是整数,我必须检查太多次才能将它们放入 $realValue$ 或 $intValue$。问题是:bison/yacc 是否有可能或有任何功能可以减少所有这些检查?

例如像

%type <intValue,realValue>

您可以在其中为类型分配两个值,例如,如果您有这样的规则:

a: primary ;

从现在开始,当 a 用于归约到另一个规则并访问 a 时,将访问 realValue 或 intValue(具有值的那个)。或者类似的东西......?

【问题讨论】:

    标签: compiler-construction calculator bison yacc


    【解决方案1】:

    这确实是一个 C 问题——没有 C 没有那样的动态类型,所以只要你使用 bison 生成 C 解析器,你就不能这样做。如果你改用 C++,你可以做一些有限的动态类型,但你不能把很多 C++ 类型放在一个%union 中,这样可能会导致其他困难。

    另外,请注意%union 是一个联合——您一次只能在其中使用一个值。因此,当您执行$&lt;realValue&gt;$=$&lt;realValue&gt;1; $&lt;numType&gt;$=$&lt;numType&gt;1; 时,第二个分配会覆盖(并破坏)第一个分配。如果要使用规则存储多个值,则需要将结构放入 union:

    %union {
        enum type_t { INT, DOUBLE } type;
        struct {
            type_t type;
            int value;
        } intval;
        struct {
            type_t type;
            double value;
        } floatval;
    }
    

    但正如您所注意到的,检查所有地方的类型标签是很困难的。

    【讨论】:

    • 你能解释一下我如何在规则中使用你的工会吗?当然是举例。
    【解决方案2】:

    bison/yacc 所做的只是生成一个 C 程序。它们不会改变 C 的语义。联合仍然是联合,因此它们只能容纳 一个 其替代成员,而且没有固有的方法来判断包含哪种类型。

    所以你不能同时在intValue 中保存一个整数,在numType 中也保存一个char*。它是一个或另一个,永远不会两者兼而有之。

    Bison 不会强迫您使用 union 类型作为语义类型。您可以使用自己的 tagged union 数据结构。但是野牛的&lt;type&gt; 机制对你没有帮助;您需要自己完成所有工作。 (虽然这并没有比你尝试的多很多;你最终会写出这样的东西:

    expr: expr '+' expr { if ($1.type == INT && $3.type == INT) {
                            $$.type = INT;
                            $$.intValue = $1.intValue + $3.intvalue;
                          } else {
                            double v1 = $1.type == INT ? (double)$1.intValue
                                                       : $1.realValue;
                            double v2 = $3.type == INT ? (double)$3.intValue
                                                       : $3.realValue;
                            $$.type = REAL;
                            $$.realValue = v1 + v2;
                          }
                        }
    

    【讨论】:

      猜你喜欢
      • 2013-07-30
      • 1970-01-01
      • 2014-05-26
      • 2014-01-25
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多