Parse-Eyapp
view release on metacpan or search on metacpan
lib/Parse/Eyapp/eyapplanguageref.pod view on Meta::CPAN
To solve a shift-reduce conflict between a production C<A --E<gt> SOMETHING>
and a token C<'a'> you can follow this procedure:
=over
=item 1. Edit the C<.output> file
=item 2. Search for the state where the conflict between the production and the token
is. In our example it looks like:
pl@nereida:~/src/perl/YappWithDefaultAction/examples$ sed -ne '56,65p' ambiguities.output
State 5:
exp -> exp . '-' exp (Rule 2)
exp -> exp '-' exp . (Rule 2)
'-' shift, and go to state 3
'-' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp)
=item 3. Inside the state there has to be a production of the type C<A --E<gt> SOMETHING.>
(with the dot at the end)
indicating that a reduction must take place. There has to be also another production
of the form C<A --E<gt> prefix . suffix>, where suffix can I<start> with the involved
token C<'a'>.
=item 4. Decide what action shift or reduce matches the kind of trees you want.
In this example we want C<NUM - NUM - NUM> to produce a tree like
C<MINUS(MINUS(NUM, NUM), NUM)> and not C<MINUS(NUM, MINUS(NUM, NUM))>. We want the
conflict in C<exp - exp.- NUM> to be solved in favor of the reduction
by C<exp: exp '-' exp>.
This is achieved by declaring C<%left '-'>.
=back
=head2 Error Recovery
The token name C<error> is reserved for error handling. This name can
be used in grammar productions; it suggests places where errors are
expected, and recovery can take place:
line:
'\n' { undef }
| exp '\n' { print "$_[1]\n" if defined($_[1]); $_[1] }
| error '\n'
{
$_[0]->YYErrok;
undef
}
The parser pops its stack until
it enters a state where the token C<error> is legal. It then shifts
the token C<error> and proceeds to discard tokens until finding
one that is acceptable. In the example
all the tokens until finding a C<'\n'> will be skipped.
If no special error productions have been specified,
the processing will halt.
In order to prevent a cascade of error messages, the parser, after
detecting an error, remains in error state until three tokens have been
successfully read and shifted. If an error is detected when the parser
is already in error state, no message is given, and the input token is
quietly deleted. The method C<YYErrok> used in the example
communicates to the parser
that a satisfactory recovery has been reached
and that it can safely emit new error
messages.
You cannot have a literal I<'error'> in your grammar as it would
confuse the driver with the I<error> token. Use a symbolic token instead.
=head1 THE TAIL
The tail section contains Perl code. Usually it is empty, but you
can if you want put here your own lexical analyzer and
error management subroutines.
An example of this is in
files C<examples/eyapplanguageref/List3_tree_d_sem.yp> (the grammar)
and C<use_list3_tree_d_dem.pl> (the client).
=head1 THE LEXICAL ANALYZER
The Lexical Analyzer
is called each time the parser needs a new token.
It is called with only one argument (the parser object)
and returns a pair
containing the next token and its associated attribute.
The fact that is a method of the parser object means that the parser
methods are accessible inside the lexical analyzer.
When the lexical analyzer reaches the end of input, it must return the
pair C<('', undef)>
=head2 Automatic Generation of Lexical Analyzers
By default a lexical analyzer is built.
The C<eyapp> option C<-l>
can be used to inhibit the generation of
the default lexical analyzer. In such case,
one must be explictly provided.
=head3 No token Definitions
When no token definitions are given in the head section,
the default lexical analyzer simply assumes
that the token is the string literal. See this example in
file C<examples/lexergeneration/simple.yp>:
pl@nereida:~/LEyapp/examples/lexergeneration$ cat simple.yp
%%
A: a
| A d
;
%%
The grammar does not describes the lexical analyzer nor the error default subroutine.
( run in 0.740 second using v1.01-cache-2.11-cpan-e93a5daba3e )