用于收集论据的Bison语法

时间:2010-08-19 17:58:25

标签: c arrays bison flex-lexer mutable

我有一个用于收集函数参数的bison语法。这就是目前为止:

args: arg               {$$ = intArray($1);} //pseudo-code function
    | args arg          {$$ = $1 + $2;}       //pseudo-code array addition
arg : NUM               {$$ = $1;}
    | exp               {$$ = $1;}

如何创建一个没有固定长度的整数数组,可以像Bison中的普通C数组一样使用?

1 个答案:

答案 0 :(得分:4)

你不能。

但是,您可以使用数据结构创建类似的内容。

struct vector {
     void* data;
     size_t size;
     size_t capacity
};

如果你知道什么类型的数据,你可以使用int*或任何你想要的。然后使用realloc展开它。 “size”是数组的当前大小,而容量是 分配空间的大小。 (我们这样做,所以我们不再重新分配1个块 - 它 最好一次分配一块块。)

您还可以使用所谓的链接列表,如下所示:

struct linked_list_node {
     void* data;
     struct linked_list_node* next;
};

同样,如果您已经知道数据,可以使用int(我在示例中使用了一个指针,因为所有指针的长度都是相同的字节长度)。

通常更有效地添加到列表的开头。但是,当我使用bison来获得另一个结构时,我觉得很好:

struct linked_list {
     struct linked_list_node* start;
     struct linked_list_node* end;
};

因为那样你可以在没有性能问题的情况下添加结尾并保持正常的顺序。

在野牛中,我们可以做类似

的事情
args: /* empty */ {
     struct linked_list* list = malloc(sizeof(struct linked_list));
     struct linked_list_node* node = malloc(sizeof(struct linked_list_node));
     list->start = node;
     list->end = node;

     $$ = list;
}
|
args arg {
     struct linked_list_node* node = malloc(sizeof(struct linked_list_node));
     int val = $2; /* assuming arg is of type int */
     node->data = &val;

     struct linked_list* list = $1;
     list->end->next = node;
     list->end = node;

     $$ = list;
}
;

(此处的所有代码均未经过测试,可能需要稍作修改)

你可以在这里以与扩展链表的方式类似的方式执行向量方法 - 只需重新分配并添加最后一个值。我认为向量可能更有效率,但链表也可能效果很好。

链接列表有O(1)用于添加和删除元素,并且比向量更快(无需在空间用完时不断移动块)。它的迭代速度也同样快,因为它们都是O(n)。您必须小心访问特定元素,因为这需要迭代,即链接列表中的O(n)。向量可以访问O(1)中的元素。