可以将其视为更多元素的集合,这些元素不一定都是同一类型。我有以下代码:
// The struct I'll use inside Bison to dynamically create collections:
typedef struct ListElementType {
union value {
int intVal;
float floatVal;
char* charptrVal;
} value;
struct ListElementType* next;
} ListElementType;
然后在野牛我有:
%union
{
int int_type;
char char_type;
float float_type;
char* charptr_type;
ListElementType* listElementType;
}
//----------------------------------------------------
%token <charptr_type> STRING
%token <int_type> INTEGER
%token <float_type> REAL
%type<listElementType> ElementList
//----------------------------------------------------
//----------------------------------------------------
ElementList
: ElementList ',' LiteralType
{
$$ = malloc(sizeof(listElementType));
$$->next = $1;
$$->value = $3;
}
| LiteralType
{
$$ = malloc(sizeof(listElementType));
$$->next = 0;
$$->value = $1;
}
;
//----------------------------------------------------
LiteralType
: STRING
| INTEGER
| REAL
;
这里有一些事情/问题。但首先,尝试生成这样的解析器 Bison 表示递归生产中的 $3 和基本 /terminal 案例中的 $1 没有声明的类型。正如我所看到的,它们实际上确实有声明类型。它们是 LiteralType,因此,可以是字符串、整数或浮点数,应该通过将最后一个终端产品留空来自动设置(假设我做的第一件事是通过从全局联合中选择适当的来明确它们的类型) .
其次,我不希望 Bison 抱怨没有声明的类型,而是因为我分配给 $$->value 而存在冲突或歧义,但 $2,$1 可能具有三个可能值中的任何一个(取决于哪个联合成员被分配到各自的作品中)。对于这种情况,我将 ListElementType 结构中的值成员设为联合。我在想而不是试图利用结构的第一个成员将位于结构地址本身的“标签”位置以及联合的成员都从联合的 mem 地址开始尝试直接分配而不管类型。类似于(void )$$ = $2 的东西,无论 $2 碰巧是什么。
所以,我将代码更改为:
//----------------------------------------------------
ElementList
: ElementList ',' LiteralType
{
$$ = malloc(sizeof(listElementType));
$$->next = $1;
*$$ = (void*)$3;
}
| LiteralType
{
$$ = malloc(sizeof(listElementType));
$$->next = 0;
$$->value = $1;
}
;
//----------------------------------------------------
LiteralType
: STRING
{
$<charptr_type>$ = $1;
}
| INTEGER
{
$<int_type>$ = $1;
}
| REAL
{
$<float_type>$ = $1;
}
;
现在我已经明确地为 INT、REAL 和 STRING 案例设置了联合。我认为这没有必要,但如果我错了,请有人纠正我。而且,我也尝试了无类型联合赋值,但仍然出现相同的错误:$3 和 $1 没有声明的类型。
所以我的想法,问题:
我是否必须创建单独的 StringList、IntList 和 RealList 产品,其中唯一改变的是右侧非终结符是列表中元素的特定类型,如下所示:
//----------------------------------------------------
ElementList
: IntElementList
| RealElementList
;
IntElementList
: IntElementList ',' INTEGER
{
$$ = malloc(sizeof(listElementType));
$$->next = $1;
$$->intVal = $3;
}
| INTEGER
{
$$ = malloc(sizeof(listElementType));
$$->next = 0;
$$->intVal = $1;
}
RealElementList
: RealElementList ',' REAL
{
$$ = malloc(sizeof(listElementType));
$$->next = $1;
$$->floatVal = $3;
}
| REAL
{
$$ = malloc(sizeof(listElementType));
$$->next = 0;
$$->floatVal = $1;
}
;
或者有没有办法声明 LiteralType 可以具有三个值中的任何一个,然后尝试提取无类型联合分配?
或者整个方法是错误的,有更好的方法吗?