yydestruct слишком мало аргументов для вызова функции (flex и bison) - PullRequest
1 голос
/ 11 июля 2020

Я пытаюсь создать реентерабельный анализатор flex и bison, но у меня возникла странная ошибка:

too few arguments to function call, expected 5, have 4

Я вижу, что код, созданный Bison, выглядит так:

static void
yydestruct (const char *yymsg,
            yysymbol_kind_t yykind, YYSTYPE *yyvaluep, void *scanner, struct BisonOutput *out)
{  ...some code... }

и

int
yyparse (void *scanner, struct BisonOutput *out)
{
  ...some code...
 yydestruct ("Cleanup: discarding lookahead",
                  yytoken, &yylval, out);   // <--- here void*scanner parameter is clearly missing 
  ...some code...
}

Мой код такой:

%define api.pure full
%lex-param {void *scanner}
%parse-param {void *scanner, struct BisonOutput *out}
%{
struct BisonOutput{
    int out; 
};
#include "syntax_parser.h"
#include "lex.yy.h"
#include <stdio.h>
%}
%define api.value.type union
%token <int> NUM
...bunch of other tokens...
%%
...bunch of grammar rules...
%%
... main function and such ...

А код Flex следующий:

%{ 
#include "syntax_parser.h"
%} 
%option reentrant  bison-bridge noyywrap
blanks          [ \t\n]+ 
number          [0-9]+
%option noyywrap  
%% 
... bunch of rules ...

Я действительно потерялся. Почему Bison не подключает scanner к yydestruct, несмотря на то, что явно использует его в yyparse?

1 Ответ

2 голосов
/ 11 июля 2020

Вам не разрешается указывать два параметра в объявлении %*-param. Правильный способ создания нужного набора параметров:

%param { void* scanner }
%parse-param { struct BisonOutput* out }

Bison на самом деле не анализирует код между { и }. Все, что он делает, это идентифицирует последний идентификатор, который, как он предполагает, является именем параметра. Также предполагается, что код является синтаксически правильным объявлением одного параметра, и он вставлен как таковой в прототипы. Поскольку на самом деле это два параметра, его можно без проблем вставить в прототип, но поскольку в вызовы функции вставляется только один аргумент, они не соответствуют прототипу.

(Действительно, void* scanner должно быть yyscan_t scanner с предшествующим typedef void* yyscan_t;. Но, возможно, это не совсем лучше.)

Вы также можете рассмотреть возможность помещения объявления struct BisonOutput в %code requires (или %code provides), чтобы он автоматически включался в файл заголовка, созданный bison.

...