Я хочу, чтобы 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);
Я должен сделать дубликаты литеральных строк, переданных парсеру, потому что они могут содержать escape-последовательности, которые я должен сначала декодировать. Но кто отвечает за освобождение памяти после синтаксического анализа? К счастью, на помощь приходит Lemon со своей директивой %destructor
, так что я могу написать:
%token_destructor TOK_LITERAL { free($$); }
Но на самом деле я не хочу жестко запрограммировать использование malloc
, strdup
и free
в моем парсере и лексере. Я хочу иметь возможность передавать функции распределителя и освобождения в качестве параметров, но использовать их не только в parserInit
и parserFree
, но и для выделения и освобождения токенов.
Как я могу объявить дополнительный параметр для parserAlloc
, чтобы одновременно передавать и malloc
, и free
? В Lemon есть директива %extra_argument
, но она заставляет меня передавать свой параметр каждый раз, когда я подаю токен.