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.