GNU Bison
GNU Bison, commonly known as Bison, is a parser generator that is part of the GNU Project. Bison reads a specification of a context-free language, warns about any parsing ambiguities, and generates a parser which reads sequences of tokens and decides whether the sequence conforms to the syntax specified by the grammar. The generated parsers are portable: they do not require any specific compilers. Bison by default generates LALR parsers but it can also generate canonical LR, IELR and GLR parsers.
In POSIX mode, Bison is compatible with Yacc, but also has several extensions over this earlier program, including:
- generation of counterexamples for conflicts,
- location tracking,
- rich and internationalizable syntax error messages in the generated parsers,
- customizable syntax error generation,
- reentrant parsers,
- push parsers, with autocompletion,
- support for named references,
- several types of reports on the generated parser,
- support for several programming languages,
- etc.
Bison was originally written by Robert Corbett in 1985. Later, in 1989, Robert Corbett released another parser generator named Berkeley Yacc. Bison was made Yacc-compatible by Richard Stallman.
Bison is free software and is available under the GNU General Public License, with an exception allowing its generated code to be used without triggering the copyleft requirements of the licence.
Some Bison Features
Counterexample Generation
One delicate issue with LR parser generators is the resolution of conflicts. Resolving conflicts usually requires the analysis of the parser automaton as described in the reports, and some expertise from the user. Counterexamples help understanding quickly some conflicts, and can even actually prove that the problem is that the grammar is actually ambiguous.For instance on a grammar suffering from the infamous dangling else problem, Bison reports
Reentrancy
Reentrancy is a feature which has been added to Bison and does not exist in Yacc.Normally, Bison generates a parser which is not reentrant. In order to achieve reentrancy the declaration
%define api.pure
must be used. More details on Bison reentrancy can be found in the Bison manual.Several Output Languages
Bison can generate code for C, C++ and Java. An experimental backend for D is also available.For using the Bison generated parser from other languages a language binding tool such as SWIG can be used.
License and distribution of generated code
Because Bison generates source code that in turn gets added to the source code of other software projects, it raises some simple but interesting copyright questions.A GPL-compatible license is not required
The code generated by Bison includes significant amounts of code from the Bison project itself. The Bison package is distributed under the terms of the GNU General Public License but an exception has been added so that the GPL does not apply to output.Earlier releases of Bison stipulated that parts of its output were also licensed under the GPL, due to the inclusion of the yyparse function from the original source code in the output.
Distribution of packages using Bison
Free software projects that use Bison may have a choice of whether to distribute the source code which their project feeds into Bison, or the resulting C code made output by Bison. Both are sufficient for a recipient to be able to compile the project source code. However, distributing only the input carries the minor inconvenience that the recipients must have a compatible copy of Bison installed so that they can generate the necessary C code when compiling the project. And distributing only the C code in output, creates the problem of making it very difficult for the recipients to modify the parser since this code was written neither by a human nor for humans - its purpose is to be fed directly into a C compiler.These problems can be avoided by distributing both the input files and the generated code. Most people will compile using the generated code, no different from any other software package, but anyone who wants to modify the parser component can modify the input files first and re-generate the generated files before compiling. Projects distributing both usually do not have the generated files in their revision control systems. The files are only generated when making a release.
Some licenses, such as the GPL, require that the source code be in "the preferred form of the work for making modifications to it". GPL'd projects using Bison must thus distribute the files which are the input for Bison. Of course, they can also include the generated files.
Use
Because Bison was written as a replacement for Yacc, and is largely compatible, the code from a lot of projects using Bison could equally be fed into Yacc. This makes it difficult to determine if a project "uses" Bison-specific source code or not. In many cases, the "use" of Bison could be trivially replaced by the equivalent use of Yacc or one of its other derivatives.Bison does have features not found in Yacc, so some projects can be truly said to "use" Bison, since Yacc would not suffice.
The following list is of projects which are known to "use" Bison in the looser sense, that they use free software development tools and distribute code which is intended to be fed into Bison or a Bison-compatible package.
- Bison's own grammar parser is generated by Bison
- The Ruby programming language
- The PHP programming language
- GCC started out using Bison, but switched to a hand-written recursive-descent parser for C++ in 2004, and for C and Objective-C in 2006
- The Go programming language used Bison, but switched to a hand-written scanner and parser in version 1.5.
- Bash shell uses a yacc grammar for parsing the command input.
- LilyPond
- PostgreSQL
- MySQL
- GNU Octave uses a Bison-generated parser.
- Perl 5 uses a Bison-generated parser starting in 5.10.
A complete reentrant parser example
/*
* Expression.h
* Definition of the structure used to build the syntax tree.
*/
- ifndef __EXPRESSION_H__
- define __EXPRESSION_H__
* @brief The operation type
*/
typedef enum tagEOperationType
EOperationType;
/**
* @brief The expression structure
*/
typedef struct tagSExpression
SExpression;
/**
* @brief It creates an identifier
* @param value The number value
* @return The expression or NULL in case of no memory
*/
SExpression *createNumber;
/**
* @brief It creates an operation
* @param type The operation type
* @param left The left operand
* @param right The right operand
* @return The expression or NULL in case of no memory
*/
SExpression *createOperation;
/**
* @brief Deletes a expression
* @param b The expression
*/
void deleteExpression;
- endif /* __EXPRESSION_H__ */
/*
* Expression.c
* Implementation of functions used to build the syntax tree.
*/
- include "Expression.h"
- include
* @brief Allocates space for expression
* @return The expression or NULL if not enough memory
*/
static SExpression *allocateExpression
SExpression *createNumber
SExpression *createOperation
void deleteExpression
The tokens needed by the Bison parser will be generated using flex.
%option outfile="Lexer.c" header-file="Lexer.h"
%option warn nodefault
%option reentrant noyywrap never-interactive nounistd
%option bison-bridge
%%
"*"
"+"
""
.
%%
int yyerror
The names of the tokens are typically neutral: "TOKEN_PLUS" and "TOKEN_STAR", not "TOKEN_ADD" and "TOKEN_MULTIPLY". For instance if we were to support the unary "+", it would be wrong to name this "+" "TOKEN_ADD". In a language such as C, "int *ptr" denotes the definition of a pointer, not a product: it would be wrong to name this "*" "TOKEN_MULTIPLY".
Since the tokens are provided by flex we must provide the means to communicate between the parser and the lexer. The data type used for communication, YYSTYPE, is set using Bison %union declaration.
Since in this sample we use the reentrant version of both flex and yacc we are forced to provide parameters for the yylex function, when called from yyparse. This is done through Bison %lex-param and %parse-param declarations.
%code requires
%output "Parser.c"
%defines "Parser.h"
%define api.pure
%lex-param
%parse-param
%parse-param
%union
%token TOKEN_LPAREN ""
%token TOKEN_PLUS "+"
%token TOKEN_STAR "*"
%token
%type
/* Precedence and associativity:
a+b+c is +c: left associativity
a+b*c is a+: the precedence of "*" is higher than that of "+". */
%left "+"
%left "*"
%%
input
: expr
;
expr
: expr "+" expr
| expr "*" expr
| ""
| "number"
;
%%
The code needed to obtain the syntax tree using the parser generated by Bison and the scanner generated by flex is the following.
/*
* main.c file
*/
- include "Expression.h"
- include "Parser.h"
- include "Lexer.h"
- include
SExpression *getAST
int evaluate
int main
A simple makefile to build the project is the following.
- Makefile
CC = g++
CFLAGS = -g -ansi
test: $
$ $ $ -o test
Lexer.c: Lexer.l
flex Lexer.l
Parser.c: Parser.y Lexer.c
bison Parser.y
clean:
rm -f *.o *~ Lexer.c Lexer.h Parser.c Parser.h test