# $Id: README,v 1.2 1998/04/29 06:34:46 jake Exp $ ------------------------ Perl 5 Byacc Patches 0.6 ------------------------ This is a set of patches to perl-byacc1.8.2 which cause it to generate a Perl 5 class implementing a parser (instead of a file full of global data and procedures). It's nice if you want to be squeaky clean, and very nice if you have a need for multiple parsers or multiple instances of a parser in one program. How to install it ----------------- 1. Get perl-byacc1.8.2 and unpack it. See http://www.perl.com/CPAN/src/misc/perl-byacc1.8.2.tar.gz 2. Patch byacc with cd perl-byacc1.8.2 patch < ../perl5-byacc-patches-0.6/patch 3. Compile perl-byacc1.8.2 as usual. How to use it ------------- You invoke byacc a little differently: 1. -P now takes a package name argument, and the output file is written as {package name}.pm. 2. You can pass a -5 argument to get a somewhat faster parser under Perl 5.005 (using 'my Dog $spot' and 'use fields'). By the way, parsers generated with these patches are thread-safe (all package variables are static data), although of course you will break that if you do something non-thread-safe in your lexer or actions. You must write your parser a little differently: 1. Your &yylex and &yyerror procedures can (optionally) take an extra argument, which is passed from &yyparse (see below). 2. Your &yylex procedure no longer side-effects $yylval; instead, it must return a list containing the token and the value. 3. Your top-level rule can assign a value to $$, and this value will be returned as the value of &yyparse (see below). And you must write the code that uses the parser differently too: 1. Use 'use Parser' (or whatever package you put in -P) instead of 'require "y.tab.pl"'. 2. Create a new parser object with $p = Parser->new($yylex, $yyerror, $yydebug); The first two arguments are references to your &yylex and &yyerror procedures, respectively. The third is true or false to enable or disable debugging output. Although you may wind up sticking your &yylex and &yyerror in the parser package in most cases, this is more composable if you want to do something weird. 3. Start a parse by calling $val = $p->yyparse($s); Here $s is an optional "stream" argument which represents the state of the text you're scanning. Depending on what you want to do, this could be a filehandle reference, a string, some object you cooked up, or whatever. The argument is passed down to &yylex and &yyerror. &yylex should use it to get characters, and &yyerror should examine it to generate a meaningful message. 4. $p->yyparse returns the value that your top-level rule assigned to $$, instead of true or false to indicate success or failure. This obviates the need to side-effect global variables to return values from the parser. You should use exceptions to handle error conditions. Example ------- I've include two examples: an ultra-simple calculator and a random text generator. Type 'make' to build the parsers. Copying ------- This code is in the public domain--use it and redistribute it as you like. I would appreciate acknowledgement of some kind (or at the very least an email) if you use it in something that is widely used or distributed. Bugs and feedback ----------------- Send them to Jake Donham (donham@linex.com). I'd love to hear from you if you find these patches useful.