Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Compiler construction Bison中的计算器,以及double或int值_Compiler Construction_Calculator_Bison_Yacc - Fatal编程技术网

Compiler construction Bison中的计算器,以及double或int值

Compiler construction Bison中的计算器,以及double或int值,compiler-construction,calculator,bison,yacc,Compiler Construction,Calculator,Bison,Yacc,我想用flex/bison创建一个计算器。我创建了以下%union: %union{ int intValue; double realValue; char * numType; } 因此,当我想简化为一个规则,如term:primary时,我会检查numType是否为“INT”或“REAL”,我会这样做: $<realValue>$=$<realValue>1; $<numType>$=$<numType>1;

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

%union{
     int intValue;
     double realValue;
     char * numType;
}
因此,当我想简化为一个规则,如
term:primary
时,我会检查numType是否为“INT”或“REAL”,我会这样做:

$<realValue>$=$<realValue>1; $<numType>$=$<numType>1;
a: primary ;
我必须多次检查术语是否为real或int,以便将它们放入$realValue$或$intValue$。问题是:bison/yacc是否有可能或有任何功能可以减少所有这些检查

比如说

%type <intValue,realValue>

从现在起,当a被用来简化为另一个规则并访问a时,就会访问realValue或intValue(有值的那一个)。或者类似的东西

这实际上是一个C问题——没有C没有这样的动态类型,所以只要您使用bison生成C解析器,就不能这样做。如果你使用C++,你可以做一些有限的动态类型,但是你不能在 %Ung/<代码>中放置很多C++类型,因此可能会造成其他困难。 另外,请注意,
%union
是一个union——一次只能在其中使用一个值。所以当你做
$$=$1$$=$1;,第二个赋值覆盖(并损坏)第一个赋值。如果要使用规则存储多个值,则需要在联合中放置一个结构:

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

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

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

因此,您不能同时在
intValue
中保存整数,也不能同时在
numType
中保存
char*
。这是一个或另一个,决不是两个都有

Bison不会强迫您使用
联合
类型作为语义类型。您可以使用自己的数据结构。但是野牛的
机制对你没有帮助;你需要自己做所有的工作。(虽然这并不比你正在尝试的工作多多少,但你最终会写下如下内容:

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;
                      }
                    }

你能解释一下我如何在规则中使用你的工会吗?当然可以举个例子。
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;
                      }
                    }