Why is yylval null?

2019-05-10 03:24发布

问题:

I'm trying to write my first parser with Flex & Bison. When parsing numbers, I'm trying to save their values into the yylval structure. The problem is, yylval is null when the lexer reaches a number, which causes a segmentation fault.

(Related point of confusion: why is it that in most Flex examples (e.g. here), yylval is a structure, rather than a pointer to a structure? I couldn't get yylval to be recognized in test.l without %option bison-bridge, and that option made yylval a pointer. Also, I tried initializing yylval in main of test.y, but yylval = malloc(...) gives a type mismatch-- as if yylval is not a pointer...?)

test.l

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include "svg.tab.h"
%}

%option bison-bridge
%option noyywrap

%%

[0-9]+  { yylval->real = atof(yytext); return REAL; }

. { return *yytext; }

%%

test.y:

%{
    #include <stdio.h>
    void yyerror(char *);   
%}

%union {
    double real;
}

%token <real> REAL

%%
...

Build command:

bison -d test.y && flex test.l && gcc lex.yy.c test.tab.c

回答1:

Normally, yylval is a global struct and not a pointer, and if you remove the %option bison-bridge from your test.l file, that's what you get (you'll need to change yylval->real to yylval.real as well to make it work).

The %option bison-bridge in flex is meant to match up to %define api.pure in bison, which uses a different API for communicating between yyparse and yylex (yylval becomes a pointer argument to yylex instead of a global var).

So your basic problem is an incompatible API between flex and bison -- you need to specify the pure api/bison-bridge in BOTH or NEITHER -- if you do it in one and not the other, things break.