UP | HOME

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.