Compiler construction Bison中的计算器,以及double或int值
我想用flex/bison创建一个计算器。我创建了以下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;
%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++,你可以做一些有限的动态类型,但是你不能在
%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;
}
}