我想在yacc
中构建一个链接的数据列表。
我的语法读起来像这样:
list: item
| list ',' item
;
我已在声明部分中放置了适当的结构。但我无法找到从这些数据中获取链表的方法。我必须存储递归获取的数据,然后将其重定向用于其他目的。
基本上我正在寻找像这样的解决方案: https://stackoverflow.com/a/1429820/5134525 但是这个解决方案适用于正确的递归,并且不适用于左侧。
答案 0 :(得分:1)
如果您使用左递归规则,则需要在列表末尾而不是开头推送新项目。
如果您的链接列表实现不支持push_back
,则在前面推送连续项,并在完成后反转列表。
答案 1 :(得分:1)
这在很大程度上取决于您如何实现链接列表,但是一旦拥有了链接列表,它就是直截了当的。类似的东西:
struct list_node {
struct list_node *next;
value_t value;
};
struct list {
struct list_node *head, **tail;
};
struct list *new_list() {
struct list *rv = malloc(sizeof(struct list));
rv->head = 0;
rv->tail = &rv->head;
return rv; }
void push_back(struct list *list, value_t value) {
struct list_node *node = malloc(sizeof(struct list_node));
node->next = 0;
node->value = value;
*list->tail = node;
list->tail = &node->next; }
允许您将yacc代码编写为:
list: item { push_back($$ = new_list(), $1); }
| list ',' item { push_back($$ = $1, $3); }
;
当然,您应该添加对内存不足的检查,并在这种情况下正常退出。
答案 2 :(得分:0)
很简单。
list
: item
{
$$ = new MyList<SomeType>();
$$.add($1);
}
| list ',' item
{
$1.add($3);
$$ = $1;
}
;
假设您使用的是C ++,而您没有说明,并且假设您有一些MyList<T>
类,并使用add(T)
方法。