gpt4 book ai didi

Lemon 中 token 析构函数的自定义释放函数

转载 作者:行者123 更新时间:2023-11-30 15:10:07 26 4
gpt4 key购买 nike

我希望 Lemon 解析一个简单的类似 C 的表达式,支持对一组具有已知名称的预定义变量进行整数和字符串比较。为了简单起见,我们假设它仅支持字符串比较。因此,以下字符串是我正在讨论的表达式类型的一个很好的示例:

a == "literal_1" || a == "literal_2"

因此,我的词法分析器必须按以下顺序向解析器提供值:

void *p = parserAlloc(malloc);
parser(p, TOK_VARIABLE_A, NULL);
parser(p, TOK_OPERATOR_EQ, NULL);
parser(p, TOK_LITERAL, strdup("literal_1"));
parser(p, TOK_OPERATOR_OR, NULL);
parser(p, TOK_VARIABLE_A, NULL);
parser(p, TOK_OPERATOR_EQ, NULL);
parser(p, TOK_LITERAL, strdup("literal_2"));
parserFree(p, free);

我必须复制传递给解析器的文字字符串,因为它们可能包含我必须首先解码的转义序列。但是谁负责解析完成后释放内存呢?幸运的是,Lemon 用它的 %destructor 指令来救援,所以我可以写:

%token_destructor TOK_LITERAL { free($$); }

但事实上,我不想在我的解析器和词法分析器中硬编码 mallocstrdupfree 的用法。我希望能够将分配器和解除分配器函数作为参数传递,但不仅在 parserInitparserFree 中使用它们,而且还用于 token 分配和解除分配。

如何为 parserAlloc 声明附加参数以同时传递 mallocfree? Lemon 中有 %extra_argument 指令,但它让我在每次提供 token 时传递参数。

最佳答案

parserAlloc的malloc参数没有存储在任何地方,因为柠檬生成的解析器从不分配内存。 [注 1] 当然,free 函数也不会存储在任何地方,因为直到您调用 parserFree 时才会提供它。

通常,您也不需要在解析器操作中使用分配函数,但如果您使用 %destructor/%token-destructor,那么您将需要一个免费功能。唯一有记录的机制是额外参数功能,正如您所说,它需要在每次调用解析器时提供参数。这有点烦人,特别是因为解析器立即将其存储到解析器状态结构中(即 parse 的第一个参数),但事实就是如此。更改很容易,而且 Lemon 不受任何阻碍,因此您可以进行所需的更改。但按照规定,%extra-argument 是唯一的方法。

如果您在操作中需要同时分配和释放函数,无论出于何种原因,您可以将 %extra-argument 设为指向结构的指针(这实际上是 的正常情况>%额外参数);该结构将包含指向这两个函数的指针。或者,您可以使用具有标准 realloc 接口(interface)的函数:realloc(NULL, sz) 相当于 malloc(sz)realloc(p, 0) 相当于 free(p) (只要 p 不为 NULL)。有关详细信息,请参阅 man realloc。这不会打扰柠檬解析器,因为它从不使用 malloc 或 free。

注释

  1. 这并不完全正确。据我所知,有一个未记录的功能:如果设置 %stack-size 0,那么生成的解析器将在溢出之前重新分配解析器堆栈,而不是抛出错误。在这种情况下,解析器使用标准库 realloc 来分配或重新分配堆栈,而不是提供给 parserAlloc 的 malloc 函数,并且 parserFree 释放具有标准库free的堆栈,而不是作为参数传递的函数。

关于Lemon 中 token 析构函数的自定义释放函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36367787/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com