使用左递归语法在yacc中构建链接列表

时间:2015-07-20 10:06:22

标签: yacc

我想在yacc中构建一个链接的数据列表。 我的语法读起来像这样:

list: item
  | list ',' item
  ;

我已在声明部分中放置了适当的结构。但我无法找到从这些数据中获取链表的方法。我必须存储递归获取的数据,然后将其重定向用于其他目的。

基本上我正在寻找像这样的解决方案: https://stackoverflow.com/a/1429820/5134525 但是这个解决方案适用于正确的递归,并且不适用于左侧。

3 个答案:

答案 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)方法。