|
Packit |
292bd0 |
#
|
|
Packit |
292bd0 |
# Module Parse::Yapp.pm.
|
|
Packit |
292bd0 |
#
|
|
Packit |
292bd0 |
# Copyright © 1998, 1999, 2000, 2001, Francois Desarmenien.
|
|
Packit |
292bd0 |
# Copyright © 2017 William N. Braswell, Jr.
|
|
Packit |
292bd0 |
# All Rights Reserved.
|
|
Packit |
292bd0 |
#
|
|
Packit |
292bd0 |
# See the Copyright section at the end of the Parse/Yapp.pm pod section
|
|
Packit |
292bd0 |
# for usage and distribution rights.
|
|
Packit |
292bd0 |
#
|
|
Packit |
292bd0 |
#
|
|
Packit |
292bd0 |
package Parse::Yapp;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
use strict;
|
|
Packit |
292bd0 |
use vars qw($VERSION @ISA);
|
|
Packit |
292bd0 |
@ISA = qw(Parse::Yapp::Output);
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
use Parse::Yapp::Output;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
# CORRELATION #py001: $VERSION must be changed in both Parse::Yapp & Parse::Yapp::Driver
|
|
Packit |
292bd0 |
our $VERSION = '1.21';
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
1;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
__END__
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=encoding UTF-8
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 NAME
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Parse::Yapp - Perl extension for generating and using LALR parsers.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 SYNOPSIS
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
yapp -m MyParser grammar_file.yp
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
...
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
use MyParser;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$parser=new MyParser();
|
|
Packit |
292bd0 |
$value=$parser->YYParse(yylex => \&lexer_sub, yyerror => \&error_sub);
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$nberr=$parser->YYNberr();
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$parser->YYData->{DATA}= [ 'Anything', 'You Want' ];
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$data=$parser->YYData->{DATA}[0];
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 DESCRIPTION
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Parse::Yapp (Yet Another Perl Parser compiler) is a collection of modules
|
|
Packit |
292bd0 |
that let you generate and use yacc like thread safe (reentrant) parsers with
|
|
Packit |
292bd0 |
perl object oriented interface.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
The script yapp is a front-end to the Parse::Yapp module and let you
|
|
Packit |
292bd0 |
easily create a Perl OO parser from an input grammar file.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head2 The Grammar file
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=over 4
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Comments>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Through all your files, comments are either Perl style, introduced by I<#>
|
|
Packit |
292bd0 |
up to the end of line, or C style, enclosed between I</*> and I<*/>.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Tokens and string literals>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Through all the grammar files, two kind of symbols may appear:
|
|
Packit |
292bd0 |
I<Non-terminal> symbols, called also I<left-hand-side> symbols,
|
|
Packit |
292bd0 |
which are the names of your rules, and I<Terminal> symbols, called
|
|
Packit |
292bd0 |
also I<Tokens>.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Tokens are the symbols your lexer function will feed your parser with
|
|
Packit |
292bd0 |
(see below). They are of two flavours: symbolic tokens and string
|
|
Packit |
292bd0 |
literals.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Non-terminals and symbolic tokens share the same identifier syntax:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
[A-Za-z][A-Za-z0-9_]*
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
String literals are enclosed in single quotes and can contain almost
|
|
Packit |
292bd0 |
anything. They will be output to your parser file double-quoted, making
|
|
Packit |
292bd0 |
any special character as such. '"', '$' and '@' will be automatically
|
|
Packit |
292bd0 |
quoted with '\', making their writing more natural. On the other hand,
|
|
Packit |
292bd0 |
if you need a single quote inside your literal, just quote it with '\'.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
You cannot have a literal I<'error'> in your grammar as it would
|
|
Packit |
292bd0 |
confuse the driver with the I<error> token. Use a symbolic token instead.
|
|
Packit |
292bd0 |
In case you inadvertently use it, this will produce a warning telling you
|
|
Packit |
292bd0 |
you should have written it I<error> and will treat it as if it were the
|
|
Packit |
292bd0 |
I<error> token, which is certainly NOT what you meant.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Grammar file syntax>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
It is very close to yacc syntax (in fact, I<Parse::Yapp> should compile
|
|
Packit |
292bd0 |
a clean I<yacc> grammar without any modification, whereas the opposite
|
|
Packit |
292bd0 |
is not true).
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
This file is divided in three sections, separated by C<%%>:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
header section
|
|
Packit |
292bd0 |
%%
|
|
Packit |
292bd0 |
rules section
|
|
Packit |
292bd0 |
%%
|
|
Packit |
292bd0 |
footer section
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=over 4
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item B<The Header Section> section may optionally contain:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=over
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item *
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
One or more code blocks enclosed inside C<%{> and C<%}> just like in
|
|
Packit |
292bd0 |
yacc. They may contain any valid Perl code and will be copied verbatim
|
|
Packit |
292bd0 |
at the very beginning of the parser module. They are not as useful as
|
|
Packit |
292bd0 |
they are in yacc, but you can use them, for example, for global variable
|
|
Packit |
292bd0 |
declarations, though you will notice later that such global variables can
|
|
Packit |
292bd0 |
be avoided to make a reentrant parser module.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item *
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Precedence declarations, introduced by C<%left>, C<%right> and C<%nonassoc>
|
|
Packit |
292bd0 |
specifying associativity, followed by the list of tokens or litterals
|
|
Packit |
292bd0 |
having the same precedence and associativity.
|
|
Packit |
292bd0 |
The precedence being the latter declared will be having the highest level.
|
|
Packit |
292bd0 |
(see the yacc or bison manuals for a full explanation of how they work,
|
|
Packit |
292bd0 |
as they are implemented exactly the same way in Parse::Yapp)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item *
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
C<%start> followed by a rule's left hand side, declaring this rule to
|
|
Packit |
292bd0 |
be the starting rule of your grammar. The default, when C<%start> is not
|
|
Packit |
292bd0 |
used, is the first rule in your grammar section.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item *
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
C<%token> followed by a list of symbols, forcing them to be recognized
|
|
Packit |
292bd0 |
as tokens, generating a syntax error if used in the left hand side of
|
|
Packit |
292bd0 |
a rule declaration.
|
|
Packit |
292bd0 |
Note that in Parse::Yapp, you I<don't> need to declare tokens as in yacc: any
|
|
Packit |
292bd0 |
symbol not appearing as a left hand side of a rule is considered to be
|
|
Packit |
292bd0 |
a token.
|
|
Packit |
292bd0 |
Other yacc declarations or constructs such as C<%type> and C<%union> are
|
|
Packit |
292bd0 |
parsed but (almost) ignored.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item *
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
C<%expect> followed by a number, suppress warnings about number of Shift/Reduce
|
|
Packit |
292bd0 |
conflicts when both numbers match, a la bison.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=back
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=back
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item B<The Rule Section> contains your grammar rules:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
A rule is made of a left-hand-side symbol, followed by a C<':'> and one
|
|
Packit |
292bd0 |
or more right-hand-sides separated by C<'|'> and terminated by a C<';'>:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
exp: exp '+' exp
|
|
Packit |
292bd0 |
| exp '-' exp
|
|
Packit |
292bd0 |
;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
A right hand side may be empty:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
input: #empty
|
|
Packit |
292bd0 |
| input line
|
|
Packit |
292bd0 |
;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
(if you have more than one empty rhs, Parse::Yapp will issue a warning,
|
|
Packit |
292bd0 |
as this is usually a mistake, and you will certainly have a reduce/reduce
|
|
Packit |
292bd0 |
conflict)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
A rhs may be followed by an optional C<%prec> directive, followed
|
|
Packit |
292bd0 |
by a token, giving the rule an explicit precedence (see yacc manuals
|
|
Packit |
292bd0 |
for its precise meaning) and optional semantic action code block (see
|
|
Packit |
292bd0 |
below).
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
exp: '-' exp %prec NEG { -$_[1] }
|
|
Packit |
292bd0 |
| exp '+' exp { $_[1] + $_[3] }
|
|
Packit |
292bd0 |
| NUM
|
|
Packit |
292bd0 |
;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Note that in Parse::Yapp, a lhs I<cannot> appear more than once as
|
|
Packit |
292bd0 |
a rule name (This differs from yacc).
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<The footer section>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
may contain any valid Perl code and will be appended at the very end
|
|
Packit |
292bd0 |
of your parser module. Here you can write your lexer, error report
|
|
Packit |
292bd0 |
subs and anything relevant to you parser.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Semantic actions>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Semantic actions are run every time a I<reduction> occurs in the
|
|
Packit |
292bd0 |
parsing flow and they must return a semantic value.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
They are (usually, but see below C<In rule actions>) written at
|
|
Packit |
292bd0 |
the very end of the rhs, enclosed with C<{ }>, and are copied verbatim
|
|
Packit |
292bd0 |
to your parser file, inside of the rules table.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Be aware that matching braces in Perl is much more difficult than
|
|
Packit |
292bd0 |
in C: inside strings they don't need to match. While in C it is
|
|
Packit |
292bd0 |
very easy to detect the beginning of a string construct, or a
|
|
Packit |
292bd0 |
single character, it is much more difficult in Perl, as there
|
|
Packit |
292bd0 |
are so many ways of writing such literals. So there is no check
|
|
Packit |
292bd0 |
for that today. If you need a brace in a double-quoted string, just
|
|
Packit |
292bd0 |
quote it (C<\{> or C<\}>). For single-quoted strings, you will need
|
|
Packit |
292bd0 |
to make a comment matching it I<in th right order>.
|
|
Packit |
292bd0 |
Sorry for the inconvenience.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
{
|
|
Packit |
292bd0 |
"{ My string block }".
|
|
Packit |
292bd0 |
"\{ My other string block \}".
|
|
Packit |
292bd0 |
qq/ My unmatched brace \} /.
|
|
Packit |
292bd0 |
# Force the match: {
|
|
Packit |
292bd0 |
q/ for my closing brace } /
|
|
Packit |
292bd0 |
q/ My opening brace { /
|
|
Packit |
292bd0 |
# must be closed: }
|
|
Packit |
292bd0 |
}
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
All of these constructs should work.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
In Parse::Yapp, semantic actions are called like normal Perl sub calls,
|
|
Packit |
292bd0 |
with their arguments passed in C<@_>, and their semantic value are
|
|
Packit |
292bd0 |
their return values.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$_[1] to $_[n] are the parameters just as $1 to $n in yacc, while
|
|
Packit |
292bd0 |
$_[0] is the parser object itself.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Having $_[0] being the parser object itself allows you to call
|
|
Packit |
292bd0 |
parser methods. That's how the yacc macros are implemented:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
yyerrok is done by calling $_[0]->YYErrok
|
|
Packit |
292bd0 |
YYERROR is done by calling $_[0]->YYError
|
|
Packit |
292bd0 |
YYACCEPT is done by calling $_[0]->YYAccept
|
|
Packit |
292bd0 |
YYABORT is done by calling $_[0]->YYAbort
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
All those methods explicitly return I<undef>, for convenience.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
YYRECOVERING is done by calling $_[0]->YYRecovering
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Four useful methods in error recovery sub
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$_[0]->YYCurtok
|
|
Packit |
292bd0 |
$_[0]->YYCurval
|
|
Packit |
292bd0 |
$_[0]->YYExpect
|
|
Packit |
292bd0 |
$_[0]->YYLexer
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
return respectivly the current input token that made the parse fail,
|
|
Packit |
292bd0 |
its semantic value (both can be used to modify their values too, but
|
|
Packit |
292bd0 |
I<know what you are doing> ! See I<Error reporting routine> section for
|
|
Packit |
292bd0 |
an example), a list which contains the tokens the parser expected when
|
|
Packit |
292bd0 |
the failure occurred and a reference to the lexer routine.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Note that if C<$_[0]-E<gt>YYCurtok> is declared as a C<%nonassoc> token,
|
|
Packit |
292bd0 |
it can be included in C<$_[0]-E<gt>YYExpect> list whenever the input
|
|
Packit |
292bd0 |
try to use it in an associative way. This is not a bug: the token
|
|
Packit |
292bd0 |
IS expected to report an error if encountered.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
To detect such a thing in your error reporting sub, the following
|
|
Packit |
292bd0 |
example should do the trick:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
grep { $_[0]->YYCurtok eq $_ } $_[0]->YYExpect
|
|
Packit |
292bd0 |
and do {
|
|
Packit |
292bd0 |
#Non-associative token used in an associative expression
|
|
Packit |
292bd0 |
};
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Accessing semantics values on the left of your reducing rule is done
|
|
Packit |
292bd0 |
through the method
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$_[0]->YYSemval( index )
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
where index is an integer. Its value being I<1 .. n> returns the same values
|
|
Packit |
292bd0 |
than I<$_[1] .. $_[n]>, but I<-n .. 0> returns values on the left of the rule
|
|
Packit |
292bd0 |
being reduced (It is related to I<$-n .. $0 .. $n> in yacc, but you
|
|
Packit |
292bd0 |
cannot use I<$_[0]> or I<$_[-n]> constructs in Parse::Yapp for obvious reasons)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
There is also a provision for a user data area in the parser object,
|
|
Packit |
292bd0 |
accessed by the method:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$_[0]->YYData
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
which returns a reference to an anonymous hash, which let you have
|
|
Packit |
292bd0 |
all of your parsing data held inside the object (see the Calc.yp
|
|
Packit |
292bd0 |
or ParseYapp.yp files in the distribution for some examples).
|
|
Packit |
292bd0 |
That's how you can make you parser module reentrant: all of your
|
|
Packit |
292bd0 |
module states and variables are held inside the parser object.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Note: unfortunately, method calls in Perl have a lot of overhead,
|
|
Packit |
292bd0 |
and when YYData is used, it may be called a huge number
|
|
Packit |
292bd0 |
of times. If your are not a *real* purist and efficiency
|
|
Packit |
292bd0 |
is your concern, you may access directly the user-space
|
|
Packit |
292bd0 |
in the object: $parser->{USER} wich is a reference to an
|
|
Packit |
292bd0 |
anonymous hash array, and then benchmark.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If no action is specified for a rule, the equivalant of a default
|
|
Packit |
292bd0 |
action is run, which returns the first parameter:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
{ $_[1] }
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<In rule actions>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
It is also possible to embed semantic actions inside of a rule:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
typedef: TYPE { $type = $_[1] } identlist { ... } ;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
When the Parse::Yapp's parser encounter such an embedded action, it modifies
|
|
Packit |
292bd0 |
the grammar as if you wrote (although @x-1 is not a legal lhs value):
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
@x-1: /* empty */ { $type = $_[1] };
|
|
Packit |
292bd0 |
typedef: TYPE @x-1 identlist { ... } ;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
where I<x> is a sequential number incremented for each "in rule" action,
|
|
Packit |
292bd0 |
and I<-1> represents the "dot position" in the rule where the action arises.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
In such actions, you can use I<$_[1]..$_[n]> variables, which are the
|
|
Packit |
292bd0 |
semantic values on the left of your action.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Be aware that the way Parse::Yapp modifies your grammar because of
|
|
Packit |
292bd0 |
I<in rule actions> can produce, in some cases, spurious conflicts
|
|
Packit |
292bd0 |
that wouldn't happen otherwise.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Generating the Parser Module>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Now that you grammar file is written, you can use yapp on it
|
|
Packit |
292bd0 |
to generate your parser module:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
yapp -v Calc.yp
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
will create two files F<Calc.pm>, your parser module, and F<Calc.output>
|
|
Packit |
292bd0 |
a verbose output of your parser rules, conflicts, warnings, states
|
|
Packit |
292bd0 |
and summary.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
What your are missing now is a lexer routine.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<The Lexer sub>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
is called each time the parser need to read the next token.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
It is called with only one argument that is the parser object itself,
|
|
Packit |
292bd0 |
so you can access its methods, specially the
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$_[0]->YYData
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
data area.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
It is its duty to return the next token and value to the parser.
|
|
Packit |
292bd0 |
They C<must> be returned as a list of two variables, the first one
|
|
Packit |
292bd0 |
is the token known by the parser (symbolic or literal), the second
|
|
Packit |
292bd0 |
one being anything you want (usually the content of the token, or the
|
|
Packit |
292bd0 |
literal value) from a simple scalar value to any complex reference,
|
|
Packit |
292bd0 |
as the parsing driver never use it but to call semantic actions:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
( 'NUMBER', $num )
|
|
Packit |
292bd0 |
or
|
|
Packit |
292bd0 |
( '>=', '>=' )
|
|
Packit |
292bd0 |
or
|
|
Packit |
292bd0 |
( 'ARRAY', [ @values ] )
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
When the lexer reach the end of input, it must return the C<''>
|
|
Packit |
292bd0 |
empty token with an undef value:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
( '', undef )
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Note that your lexer should I<never> return C<'error'> as token
|
|
Packit |
292bd0 |
value: for the driver, this is the error token used for error
|
|
Packit |
292bd0 |
recovery and would lead to odd reactions.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Now that you have your lexer written, maybe you will need to output
|
|
Packit |
292bd0 |
meaningful error messages, instead of the default which is to print
|
|
Packit |
292bd0 |
'Parse error.' on STDERR.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
So you will need an Error reporting sub.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Error reporting routine>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If you want one, write it knowing that it is passed as parameter
|
|
Packit |
292bd0 |
the parser object. So you can share information with the lexer
|
|
Packit |
292bd0 |
routine quite easily.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
You can also use the C<$_[0]-E<gt>YYErrok> method in it, which will
|
|
Packit |
292bd0 |
resume parsing as if no error occurred. Of course, since the invalid
|
|
Packit |
292bd0 |
token is still invalid, you're supposed to fix the problem by
|
|
Packit |
292bd0 |
yourself.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
The method C<$_[0]-E<gt>YYLexer> may help you, as it returns a reference
|
|
Packit |
292bd0 |
to the lexer routine, and can be called as
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
($tok,$val)=&{$_[0]->Lexer}
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
to get the next token and semantic value from the input stream. To
|
|
Packit |
292bd0 |
make them current for the parser, use:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
($_[0]->YYCurtok, $_[0]->YYCurval) = ($tok, $val)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
and know what you're doing...
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Parsing>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Now you've got everything to do the parsing.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
First, use the parser module:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
use Calc;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Then create the parser object:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$parser=new Calc;
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Now, call the YYParse method, telling it where to find the lexer
|
|
Packit |
292bd0 |
and error report subs:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$result=$parser->YYParse(yylex => \&Lexer,
|
|
Packit |
292bd0 |
yyerror => \&ErrorReport);
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
(assuming Lexer and ErrorReport subs have been written in your current
|
|
Packit |
292bd0 |
package)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
The order in which parameters appear is unimportant.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Et voila.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
The YYParse method will do the parse, then return the last semantic
|
|
Packit |
292bd0 |
value returned, or undef if error recovery cannot recover.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If you need to be sure the parse has been successful (in case your
|
|
Packit |
292bd0 |
last returned semantic value I<is> undef) make a call to:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$parser->YYNberr()
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
which returns the total number of time the error reporting sub has been called.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Error Recovery>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
in Parse::Yapp is implemented the same way it is in yacc.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Debugging Parser>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
To debug your parser, you can call the YYParse method with a debug parameter:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
$parser->YYParse( ... , yydebug => value, ... )
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
where value is a bitfield, each bit representing a specific debug output:
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Bit Value Outputs
|
|
Packit |
292bd0 |
0x01 Token reading (useful for Lexer debugging)
|
|
Packit |
292bd0 |
0x02 States information
|
|
Packit |
292bd0 |
0x04 Driver actions (shifts, reduces, accept...)
|
|
Packit |
292bd0 |
0x08 Parse Stack dump
|
|
Packit |
292bd0 |
0x10 Error Recovery tracing
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
To have a full debugging output, use
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
debug => 0x1F
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
Debugging output is sent to STDERR, and be aware that it can produce
|
|
Packit |
292bd0 |
C<huge> outputs.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Standalone Parsers>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
By default, the parser modules generated will need the Parse::Yapp
|
|
Packit |
292bd0 |
module installed on the system to run. They use the Parse::Yapp::Driver
|
|
Packit |
292bd0 |
which can be safely shared between parsers in the same script.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
In the case you'd prefer to have a standalone module generated, use
|
|
Packit |
292bd0 |
the C<-s> switch with yapp: this will automagically copy the driver
|
|
Packit |
292bd0 |
code into your module so you can use/distribute it without the need
|
|
Packit |
292bd0 |
of the Parse::Yapp module, making it really a C<Standalone Parser>.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If you do so, please remember to include Parse::Yapp's copyright notice
|
|
Packit |
292bd0 |
in your main module copyright, so others can know about Parse::Yapp module.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=item C<Source file line numbers>
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
by default will be included in the generated parser module, which will help
|
|
Packit |
292bd0 |
to find the guilty line in your source file in case of a syntax error.
|
|
Packit |
292bd0 |
You can disable this feature by compiling your grammar with yapp using
|
|
Packit |
292bd0 |
the C<-n> switch.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=back
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 BUGS AND SUGGESTIONS
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If you find bugs, think of anything that could improve Parse::Yapp
|
|
Packit |
292bd0 |
or have any questions related to it, feel free to contact the author.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 AUTHOR
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
William N. Braswell, Jr. <wbraswell_cpan@NOSPAM.nym.hush.com>
|
|
Packit |
292bd0 |
(Remove "NOSPAM".)
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 SEE ALSO
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
yapp(1) perl(1) yacc(1) bison(1).
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=head1 COPYRIGHT
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
The Parse::Yapp module and its related modules and shell scripts are copyright:
|
|
Packit |
292bd0 |
Copyright © 1998, 1999, 2000, 2001, Francois Desarmenien.
|
|
Packit |
292bd0 |
Copyright © 2017 William N. Braswell, Jr.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
You may use and distribute them under the terms of either
|
|
Packit |
292bd0 |
the GNU General Public License or the Artistic License,
|
|
Packit |
292bd0 |
as specified in the Perl README file.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
If you use the "standalone parser" option so people don't need to install
|
|
Packit |
292bd0 |
Parse::Yapp on their systems in order to run you software, this copyright
|
|
Packit |
292bd0 |
noticed should be included in your software copyright too, and the copyright
|
|
Packit |
292bd0 |
notice in the embedded driver should be left untouched.
|
|
Packit |
292bd0 |
|
|
Packit |
292bd0 |
=cut
|