yacc/bison question
Michael Meissner
meissner at osf.org
Sun Oct 7 11:11:47 AEST 1990
In article <122 at bwilab3.UUCP> chris at bwilab3.UUCP (Chris Curtin)
writes:
| I am looking for a way to have multiple yacc/bison routines in a program. I
| also need to be able to name them anything, not just yyparse1 etc.
|
| I know that doing a global replace with the preprocessor will not work because
| of the use of globals in calls to library routines.
|
| If this is possible it will make my life much easier and produce better quality
| code. (Now I have to hand parse all input and it gets tedious and error prone).
This seems to come up regularly on comp.compilers and comp.lang.misc,
which might have been better groups to ask.
In any case, bison has extensions to handle this with no problem --
RTFM. The traditional ways to do it with yacc are to go through and
change the names with either sed or the preprocessor. With sed, you
just change all 'yy' and 'YY' to some other prefix. With the
preprocessor, you use #defines, and you can get burned if your vendor
changes the yacc skeleton file and some new name is added.
The relavant sections from the bison manual are quoated below (to get
a different named file, just use the -o <file> option, and -d and -v
will adjust themselves accordingly):
File: bison.info Node: Multiple Parsers, Prev: Declarations, Up: Grammar File
Multiple Parsers in the Same Program
====================================
Most programs that use Bison parse only one language and therefore contain
only one Bison parser. But what if you want to parse more than one
language with the same program? Here is what you must do:
* Make each parser a pure parser (*Note Pure Decl::). This gets rid of
global variables such as `yylval' which would otherwise conflict
between the various parsers, but it requires an alternate calling
convention for `yylex' (*Note Pure Calling::).
* In each grammar file, define `yyparse' as a macro, expanding
into the name you want for that parser. Put this definition in
the C declarations section (*Note C Declarations::). For example:
%{
#define yyparse parse_algol
%}
Then use the expanded name `parse_algol' in other source files to
call this parser.
* If you want different lexical analyzers for each grammar, you can
define `yylex' as a macro, just like `yyparse'. Use
the expanded name when you define `yylex' in another source
file.
If you define `yylex' in the grammar file itself, simply
make it static, like this:
%{
static int yylex ();
%}
%%
... GRAMMAR RULES ...
%%
static int
yylex (yylvalp, yyllocp)
YYSTYPE *yylvalp;
YYLTYPE *yyllocp;
{ ... }
* If you want a different `yyerror' function for each grammar,
you can use the same methods that work for `yylex'.
File: bison.info Node: Pure Decl, Prev: Start Decl, Up: Declarations, Next: Decl Summary
Requesting a Pure (Reentrant) Parser
------------------------------------
A "reentrant" program is one which does not alter in the course of
execution; in other words, it consists entirely of "pure" (read-only)
code. Reentrancy is important whenever asynchronous execution is possible;
for example, a nonreentrant program may not be safe to call from a signal
handler. In systems with multiple threads of control, a nonreentrant
program must be called only within interlocks.
The Bison parser is not normally a reentrant program, because it uses
statically allocated variables for communication with `yylex'. These
variables include `yylval' and `yylloc'.
The Bison declaration `%pure_parser' says that you want the parser
to be reentrant. It looks like this:
%pure_parser
The effect is that the the two communication variables become local
variables in `yyparse', and a different calling convention is used for
the lexical analyzer function `yylex'. *Note Pure Calling::, for the
details of this. The variable `yynerrs' also becomes local in
`yyparse' (*Note Error Reporting::). The convention for calling
`yyparse' itself is unchanged.
File: bison.info Node: Pure Calling, Prev: Token Positions, Up: Lexical
Calling Convention for Pure Parsers
-----------------------------------
When you use the Bison declaration `%pure_parser' to request a pure,
reentrant parser, the global communication variables `yylval' and
`yylloc' cannot be used. (*Note Pure Decl::.) In such parsers the
two global variables are replaced by pointers passed as arguments to
`yylex'. You must declare them as shown here, and pass the
information back by storing it through those pointers.
yylex (lvalp, llocp)
YYSTYPE *lvalp;
YYLTYPE *llocp;
{
...
*lvalp = value; /* Put value onto Bison stack. */
return INT; /* Return the type of the token. */
...
}
--
Michael Meissner email: meissner at osf.org phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142
Do apple growers tell their kids money doesn't grow on bushes?
More information about the Comp.unix.programmer
mailing list