yydestruct слишком мало аргументов для вызова функции (flex&bison)

Я пытаюсь сделать реентерабельный анализатор 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?


person alagris    schedule 11.07.2020    source источник
comment
Что такое syntax_parser.h и lex.yy.h?   -  person rici    schedule 11.07.2020


Ответы (1)


Вы не можете поместить два параметра в объявление %*-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 заголовочный файл.

person rici    schedule 11.07.2020