用于收集参数的 Bison 语法

发布于 2024-09-15 07:45:50 字数 325 浏览 9 评论 0原文

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

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

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

I have a bison grammar for collecting arguments of a function. This is what it is so far:

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

How can I create an array of integers without a fixed length that can be used like a normal C array in Bison?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挖个坑埋了你 2024-09-22 07:45:50

你不能。

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

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

如果您知道数据是什么类型,则可以使用 int* 或任何您想要的。然后只需使用realloc来扩展它。 “size”是数组的当前大小,capacity是
分配空间的大小。 (我们这样做是为了不再重新分配 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) 中访问元素。

You can't.

However, you can create something similar using data structures.

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

If you know what type data is, you can use int* or whatever you want. Then just use realloc to expand it. "size" is the current size of the array, and capacity is the
size of the allocated space. (We do this so we don't keep reallocing 1 more block - Its
better to alloc chunks of blocks at a time).

You can also use what is called a linked list, which looks something like this:

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

Again, you could use int if you already know the data (I used a pointer in the example because all pointers are the same length in bytes).

Usually its more efficient to add to the beginning of a list. However, I find it nice when using bison to have another struct:

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

Because then you can add the end without performance issues and keep the normal order.

In bison, we can do something like

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

(All code here is untested and might need slight modifications)

You can do the vector method here in a similar way to how I expanded the linked list - Just realloc and add in the last value. I think vectors might be more efficient, but a linked list might work well too.

Linked List has O(1) for adding and removing elements and is faster at that than a vector (no need to continually move blocks around when you run out of space). Its also just as fast to iterate, as both are O(n). You have to be careful about accessing a particular element, as that requires iteration, which is O(n) in a linked list. A vector can access an element in O(1).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文