Re: Threadsafe parser generators?

Michael Meissner <meissner@cygnus.com>
15 Dec 1996 15:45:41 -0500

          From comp.compilers

Related articles
Threadsafe parser generators? c.coles@slh0633.wins.icl.co.uk (Wilf Coles) (1996-12-07)
Re: Threadsafe parser generators? jlilley@empathy.com (1996-12-09)
Re: Threadsafe parser generators? Martin.Jourdan@inria.fr (1996-12-10)
Re: Threadsafe parser generators? car@mothra.lbl.gov (Chuck Rendleman) (1996-12-14)
Re: Threadsafe parser generators? meissner@cygnus.com (Michael Meissner) (1996-12-15)
Re: Threadsafe parser generators? paulpaul@knoware.nl (1996-12-15)
Re: Threadsafe parser generators? c.coles@slh0633.wins.icl.co.uk (Wilf Coles) (1996-12-24)
| List of all articles for this month |

From: Michael Meissner <meissner@cygnus.com>
Newsgroups: comp.compilers
Date: 15 Dec 1996 15:45:41 -0500
Organization: Compilers Central
References: 96-12-059
Keywords: yacc, parallel

John commented on the question of threadsafe parsers:


| [Doesn't bison do this if you set the reentrant flag? -John]


Here is the documentation for Bison regarding threadsafe calls:


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 two communication variables become local
variables in `yyparse', and a different calling convention is used for
the lexical analyzer function `yylex'. *Note Calling Conventions for
Pure Parsers: Pure Calling, for the details of this. The variable
`yynerrs' also becomes local in `yyparse' (*note The Error Reporting
Function `yyerror': Error Reporting.). The convention for calling
`yyparse' itself is unchanged.


Calling Conventions 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 A Pure (Reentrant) Parser: 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. */
              ...
          }


      If the grammar file does not use the `@' constructs to refer to
textual positions, then the type `YYLTYPE' will not be defined. In
this case, omit the second argument; `yylex' will be called with only
one argument.


      You can pass parameter information to a reentrant parser in a
reentrant way. Define the macro `YYPARSE_PARAM' as a variable name.
The resulting `yyparse' function then accepts one argument, of type
`void *', with that name.


      When you call `yyparse', pass the address of an object, casting the
address to `void *'. The grammar actions can refer to the contents of
the object by casting the pointer value back to its proper type and
then dereferencing it. Here's an example. Write this in the parser:


          %{
          struct parser_control
          {
              int nastiness;
              int randomness;
          };


          #define YYPARSE_PARAM parm
          %}


Then call the parser like this:


          struct parser_control
          {
              int nastiness;
              int randomness;
          };


          ...


          {
              struct parser_control foo;
              ... /* Store proper data in `foo'. */
              value = yyparse ((void *) &foo);
              ...
          }


In the grammar actions, use expressions like this to refer to the data:


          ((struct parser_control *) parm)->randomness


      If you wish to pass the additional parameter data to `yylex', define
the macro `YYLEX_PARAM' just like `YYPARSE_PARAM', as shown here:


          %{
          struct parser_control
          {
              int nastiness;
              int randomness;
          };


          #define YYPARSE_PARAM parm
          #define YYLEX_PARAM parm
          %}


      You should then define `yylex' to accept one additional
argument--the value of `parm'. (This makes either two or three
arguments in total, depending on whether an argument of type `YYLTYPE'
is passed.) You can declare the argument as a pointer to the proper
object type, or you can declare it as `void *' and access the contents
as shown above.


--
Michael Meissner, Cygnus Support (East Coast)
4th floor, 955 Massachusetts Avenue, Cambridge, MA 02139, USA
meissner@cygnus.com, 617-354-5416 (office), 617-354-7161 (fax)


--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.