Using bison
Table of Contents
From pull parser to push parser
I found kinda difficult to know what things I had to change when I made my parser a push re-entrant parser, that is why I am documenting this changes; yes, the c source code generated by bison is the real documentation but I spent a lot of time reading the manual, so I think the manual needs documentation for a push parser. Disclaimer, I did not find in the manual some of the documentation that is written in the next sections of this blog, but it may be that I ignore something or it may be that I did not understand it as it should be; I also cover documentation that is already in the manual but I also is wrote it here because it has information scattered in different manual sections, which is why I am unifying that information in one place.
I hope this blog can help someone, I will be publishing my project soon, or at least I hope so!
Before continuing reading I encourage you to read Bison's manual before, since this blog uses terminology used in the manual.
Changes in lexer yylex
Non re-entrant
Prototype for pull parser: int yylex(void)
.
This is the default function used by yyparse
to lexically analyze an
input stream, this function is a MUST when the parser is a pull
parser.
The variables yylval
and yylloc
are global variables and can be
used within yylex
. Refer to bison's manual for the reference of
these variables.
Re-entrant and Push
Prototype for re-entrant parser: int yylex(YYSTYPE *)
or int
yylex(YYSTYPE *, YYLTYPE *)
.
Since the parser is re-entrant we Must pass variables as arguments because we cannot use global variables and also bison do not generate global variables for a re-entrant parser. These arguments can be the ones in the prototype or more, I did not add syntax for that prototype since it is user defined, see Section 4.3.6 of bison's manual.
I am going to focus on the two main arguments of a lexer for a
re-entrant parser, the one with YYSTYPE
type has the same function
as yylval
which means it can be name to yylval
and your parser
should work without more changes; the one with YYLTYPE
is optional,
and depends if you do not use locations in the grammar file, and it
has the same function as yylloc
.
The name of yylex
can be changed to any name if the parser is a push
parser, otherwise it must stay as yylex
since it is the default
function name that yyparse
uses.
Changes in yypush_parse
This is the biggest complaint, I did not find any information about the arguments in the manual, however, the C code generated has everything I needed, but the manual should cover this.
Prototype for re-entrant and push parser: yypush_parse(yypstate *,
int, YYSTYPE *)
.
The argument with type yypstate *
is parser instance, the argument
with type int
is one of the possibles values returned by the lexer,
and the argument with type YYSTYPE
is the value returned by the
argument with the same type in the lexer. This functions allows to
manually set the conditions for the lexer and then use the lexer.
The return value is YYPUSH_MORE
until it finds an error (memory
exhaustion, or other, see the C code) or the third argument is
YYEOF
.