=head1 NAME
 
Parse::Eyapp::defaultactionsintro - Introduction to Default Actions and Grammar Reuse
 
=head1 Default Actions

=head2 Default actions

When no action is specified both C<yapp> and C<eyapp>
implicitly insert the semantic action C<{ $_[1] }>. 
In C<Parse::Eyapp> you can modify such behavior using the C<%defaultaction { Perl code }>
directive. The C<{ Perl code }> clause that follows the C<%defaultaction>
directive is
executed when reducing by any production for which no explicit
action was specified.

=head3 Translator from Infix to Postfix

See an example that translates an infix expression
like C<a=b*-3> into a postfix expression like C<a b 3 NEG * = >:

 # File Postfix.eyp (See the examples/ directory)
 %right  '='
 %left   '-' '+'
 %left   '*' '/'
 %left   NEG

 %defaultaction { return  "$left $right $op"; }

 %%
 line: $exp  { print "$exp\n" }
 ;

 exp:        $NUM  { $NUM }
         |   $VAR  { $VAR }
         |   VAR.left '='.op exp.right
         |   exp.left '+'.op exp.right
         |   exp.left '-'.op exp.right
         |   exp.left '*'.op exp.right
         |   exp.left '/'.op exp.right
         |   '-' $exp %prec NEG { "$exp NEG" }
         |   '(' $exp ')' { $exp }
 ;

 %%

 # Support subroutines as in the Synopsis example
 ...

The file containing the C<Eyapp> program must be compiled with C<eyapp>:

 nereida:~/src/perl/YappWithDefaultAction/examples> eyapp Postfix.eyp

Next, you have to write a client program:

 nereida:~/src/perl/YappWithDefaultAction/examples> cat -n usepostfix.pl
      1  #!/usr/bin/perl -w
      2  use strict;
      3  use Postfix;
      4
      5  my $parser = new Postfix();
      6  $parser->Run;

Now we can run the client program:

 nereida:~/src/perl/YappWithDefaultAction/examples> usepostfix.pl
 Write an expression: -(2*a-b*-3)
 2 a * b 3 NEG * - NEG

=head3 Default Actions, C<%name> and C<YYName>

In C<eyapp> each production rule has a name.
The name of a rule can be explicitly given by the programmer 
using the C<%name> directive. For example, in the piece of code
that follows the name C<ASSIGN> is given to the rule C<exp: VAR '=' exp>.

When no explicit name is given the rule has an implicit name.
The implicit name of a rule is shaped by concatenating
the name of the syntactic variable on its left, an underscore 
and the ordinal number of the production rule C<Lhs_#>
as it appears in the C<.output> file.
Avoid giving names matching such pattern to production rules.
The patterns
C</${lhs}_\d+$/> where C<${lhs}> is the name of the syntactic variable
are reserved for internal use by C<eyapp>.

  pl@nereida:~/LEyapp/examples$ cat -n Lhs.eyp
   1  # Lhs.eyp
   2
   3  %right  '='
   4  %left   '-' '+'
   5  %left   '*' '/'
   6  %left   NEG
   7
   8  %defaultaction {
   9    my $self = shift;
  10    my $name = $self->YYName();
  11    bless { children => [ grep {ref($_)} @_] }, $name;
  12  }
  13
  14  %%
  15  input:
  16              /* empty */
  17                { [] }
  18          |   input line
  19                {
  20                  push @{$_[1]}, $_[2] if defined($_[2]);
  21                  $_[1]
  22                }
  23  ;
  24
  25  line:     '\n'       { }
  26          | exp '\n'   {  $_[1] }
  27  ;
  28
  29  exp:
  30              NUM   { $_[1] }
  31          |   VAR   { $_[1] }
  32          |   %name ASSIGN
  33              VAR '=' exp
  34          |   %name PLUS
  35              exp '+' exp
  36          |   %name MINUS
  37              exp '-' exp
  38          |   %name TIMES
  39              exp '*' exp
  40          |   %name DIV
  41              exp '/' exp
  42          |   %name UMINUS
  43              '-' exp %prec NEG
  44          |  '(' exp ')'  { $_[2] }
  45  ;

Inside a semantic action
the name of the current rule can be recovered 
using the method C<YYName> of the parser object.

The default action (lines 8-12) computes as attribute of the left
hand side a reference to an object blessed in the name of the rule.
The object has an attribute C<children> which is a reference 
to the list of children of the node.
The call to C<grep> 

  11    bless { children => [ grep {ref($_)} @_] }, $name;

excludes children that aren't references. Notice that the lexical analyzer 
only returns references for the C<NUM> and C<VAR> terminals:

  59  sub _Lexer {
  60      my($parser)=shift;
  61
  62      for ($parser->YYData->{INPUT}) {
  63          s/^[ \t]+//;
  64          return('',undef) unless $_;
  65          s/^([0-9]+(?:\.[0-9]+)?)//
  66                  and return('NUM', bless { attr => $1}, 'NUM');
  67          s/^([A-Za-z][A-Za-z0-9_]*)//
  68                  and return('VAR',bless {attr => $1}, 'VAR');
  69          s/^(.)//s
  70                  and return($1, $1);
  71      }
  72      return('',undef);
  73  }

follows the client program:

  pl@nereida:~/LEyapp/examples$ cat -n uselhs.pl
       1  #!/usr/bin/perl -w
       2  use Lhs;
       3  use Data::Dumper;
       4
       5  $parser = new Lhs();
       6  my $tree = $parser->Run;
       7  $Data::Dumper::Indent = 1;
       8  if (defined($tree)) { print Dumper($tree); }
       9  else { print "Cadena no válida\n"; }

When executed with input C<a=(2+3)*b> the parser produces
the following tree:

  ASSIGN(TIMES(PLUS(NUM[2],NUM[3]), VAR[b]))

See the result of an execution:

  pl@nereida:~/LEyapp/examples$ uselhs.pl
  a=(2+3)*b
  $VAR1 = [
    bless( {
      'children' => [
        bless( { 'attr' => 'a' }, 'VAR' ),
        bless( {
          'children' => [
            bless( {
              'children' => [
                bless( { 'attr' => '2' }, 'NUM' ),
                bless( { 'attr' => '3' }, 'NUM' )
              ]
            }, 'PLUS' ),
            bless( { 'attr' => 'b' }, 'VAR' )
          ]
        }, 'TIMES' )
      ]
    }, 'ASSIGN' )
  ];

The name of a production rule can be changed at execution time.
See the following example:

  29  exp:
  30              NUM   { $_[1] }
  31          |   VAR   { $_[1] }
  32          |   %name ASSIGN
  33              VAR '=' exp
  34          |   %name PLUS
  35              exp '+' exp
  36          |   %name MINUS
  37              exp '-' exp
  38                {
  39                  my $self = shift;
  40                  $self->YYName('SUBSTRACT'); # rename it
  41                  $self->YYBuildAST(@_); # build the node
  42                }
  43          |   %name TIMES
  44              exp '*' exp
  45          |   %name DIV
  46              exp '/' exp
  47          |   %name UMINUS
  48              '-' exp %prec NEG
  49          |  '(' exp ')'  { $_[2] }
  50  ;

When the client program is executed we can see the presence
of the C<SUBSTRACT> nodes:

  pl@nereida:~/LEyapp/examples$ useyynamedynamic.pl
  2-b
  $VAR1 = [
    bless( {
      'children' => [
        bless( {
          'attr' => '2'
        }, 'NUM' ),
        bless( {
          'attr' => 'b'
        }, 'VAR' )
      ]
    }, 'SUBSTRACT' )
  ];




=head1 Grammar Reuse

=head2 An Action Method for each Production

Default actions provide a way to write reusable
grammars.  Here is one solution:

  pl@europa:~/LEyapp/examples/recycle$ cat -n Noactions.eyp
     1  %left   '+'
     2  %left   '*'
     3
     4  %defaultaction {
     5    my $self = shift;
     6
     7    my $class = $self->YYName;
     8
     9    $class->action(@_);
    10  }
    11
    12  %%
    13  exp:        %name NUM
    14                NUM
    15          |   %name PLUS
    16                exp '+' exp
    17          |   %name TIMES
    18                exp '*' exp
    19          |   '(' exp ')'
    20                { $_[2] }
    21  ;
    22
    23  %%
    24
    25  sub _Error {
    26    my($token)=$_[0]->YYCurval;
    27    my($what)= $token ? "input: '$token'" : "end of input";
    28    my @expected = $_[0]->YYExpect();
    29
    30    local $" = ', ';
    31    die "Syntax error near $what. Expected one of these tokens: @expected\n";
    32  }
    33
    34
    35  my $x = '';
    36
    37  sub _Lexer {
    38    my($parser)=shift;
    39
    40    for ($x) {
    41      s/^\s+//;
    42      $_ eq '' and return('',undef);
    43
    44      s/^([0-9]+(?:\.[0-9]+)?)//   and return('NUM',$1);
    45      s/^([A-Za-z][A-Za-z0-9_]*)// and return('VAR',$1);
    46      s/^(.)//s                    and return($1,$1);
    47    }
    48  }
    49
    50  sub Run {
    51    my($self)=shift;
    52    $x = shift;
    53    my $debug = shift;
    54
    55    $self->YYParse(
    56      yylex => \&_Lexer,
    57      yyerror => \&_Error,
    58      yydebug => $debug,
    59    );
    60  }

This grammar can be reused by a program that implements a calculator:

  pl@europa:~/LEyapp/examples/recycle$ cat -n calcu.pl
     1  #!/usr/bin/perl
     2  use warnings;
     3  use Noactions;
     4
     5  sub NUM::action {
     6    return $_[1];
     7  }
     8
     9  sub PLUS::action {
    10    $_[1]+$_[3];
    11  }
    12
    13  sub TIMES::action {
    14    $_[1]*$_[3];
    15  }
    16
    17  my $parser = Noactions->new();
    18  print "Write an expression: ";
    19  my $x;
    20  {
    21    local $/ = undef;
    22    $x = <>;
    23  }
    24  my $t = $parser->Run($x);
    25
    26  print "$t\n";

But it also can be used by a program that translates infix
to postfix expressions:

  pl@europa:~/LEyapp/examples/recycle$ cat -n postf.pl
     1  #!/usr/bin/perl
     2  use warnings;
     3  use Noactions;
     4
     5  sub NUM::action {
     6    return $_[1];
     7  }
     8
     9  sub PLUS::action {
    10    "$_[1] $_[3] +";
    11  }
    12
    13  sub TIMES::action {
    14    "$_[1] $_[3] *";
    15  }
    16
    17  my $parser = Noactions->new();
    18  print "Write an expression: ";
    19  my $x;
    20  {
    21    local $/ = undef;
    22    $x = <>;
    23  }
    24  my $t = $parser->Run($x);
    25
    26  print "$t\n";

=head2 Reusing Grammars Using Inheritance

An laternative method is to use inheritance. The
grammar inherits the action methods from the client:

  pl@europa:~/LEyapp/examples/recycle$ cat -n NoacInh.eyp
     1  %left   '+'
     2  %left   '*'
     3
     4  %defaultaction {
     5    my $self = shift;
     6
     7    my $action = $self->YYName;
     8
     9    $self->$action(@_);
    10  }
    11
    12  %%
    13  exp:        %name NUM
    14                NUM
    15          |   %name PLUS
    16                exp '+' exp
    17          |   %name TIMES
    18                exp '*' exp
    19          |   '(' exp ')'
    20                { $_[2] }
    21  ;
    22
    23  %%
    24
    25  sub _Error {
    26    my($token)=$_[0]->YYCurval;
    27    my($what)= $token ? "input: '$token'" : "end of input";
    28    my @expected = $_[0]->YYExpect();
    29
    30    local $" = ', ';
    31    die "Syntax error near $what. Expected one of these tokens: @expected\n";
    32  }
    33
    34
    35  my $x = '';
    36
    37  sub _Lexer {
    38    my($parser)=shift;
    39
    40    for ($x) {
    41      s/^\s+//;
    42      $_ eq '' and return('',undef);
    43
    44      s/^([0-9]+(?:\.[0-9]+)?)//   and return('NUM',$1);
    45      s/^([A-Za-z][A-Za-z0-9_]*)// and return('VAR',$1);
    46      s/^(.)//s                    and return($1,$1);
    47    }
    48  }
    49
    50  sub Run {
    51    my($self)=shift;
    52    $x = shift;
    53    my $debug = shift;
    54
    55    $self->YYParse(
    56      yylex => \&_Lexer,
    57      yyerror => \&_Error,
    58      yydebug => $debug,
    59    );
    60  }


This programs C<icalcu.pl> injects the actions
into the parser package, implementing this way a calculator:

  pl@europa:~/LEyapp/examples/recycle$ cat -n icalcu.pl
     1  #!/usr/bin/perl
     2  use warnings;
     3  use NoacInh;
     4
     5  package Actions;
     6  push @NoacInh::ISA, 'Actions';
     7
     8  sub NUM {
     9    return $_[1];
    10  }
    11
    12  sub PLUS {
    13    $_[1]+$_[3];
    14  }
    15
    16  sub TIMES {
    17    $_[1]*$_[3];
    18  }
    19
    20  package main;
    21
    22  my $parser = NoacInh->new();
    23  print "Write an expression: ";
    24  my $x;
    25  {
    26    local $/ = undef;
    27    $x = <>;
    28  }
    29  my $t = $parser->Run($x);
    30
    31  print "$t\n";

In the same way this program implements the translator:

  pl@europa:~/LEyapp/examples/recycle$ cat -n ipostf.pl
     1  #!/usr/bin/perl
     2  use warnings;
     3  use NoacInh;
     4
     5  package Actions;
     6  push @NoacInh::ISA, 'Actions';
     7
     8  sub NUM {
     9    return $_[1];
    10  }
    11
    12  sub PLUS {
    13    "$_[1] $_[3] +";
    14  }
    15
    16  sub TIMES {
    17    "$_[1] $_[3] *";
    18  }
    19
    20  package main;
    21
    22  my $parser = NoacInh->new();
    23  print "Write an expression: ";
    24  my $x;
    25  {
    26    local $/ = undef;
    27    $x = <>;
    28  }
    29  my $t = $parser->Run($x);
    30
    31  print "$t\n";

=head1 SEE ALSO

=over

=item * 
L<Parse::Eyapp>, 
L<Parse::Eyapp::eyapplanguageref>, 
L<Parse::Eyapp::debugingtut>,
L<Parse::Eyapp::translationschemestut>,
L<Parse::Eyapp::Driver>,
L<Parse::Eyapp::Node>,
L<Parse::Eyapp::YATW>,
L<Parse::Eyapp::Treeregexp>,
L<Parse::Eyapp::Scope>,
L<Parse::Eyapp::Base>,


=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/languageintro.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/debuggingtut.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/eyapplanguageref.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/Treeregexp.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/Node.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/YATW.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/Eyapp.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/Base.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/translationschemestut.pdf> 

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/MatchingTrees.pdf> 

=item * The tutorial I<Parsing Strings and Trees with> C<Parse::Eyapp>
(An Introduction to Compiler Construction in seven pages) in
L<http://nereida.deioc.ull.es/~pl/eyapsimple/> 

=item *
perldoc L<eyapp>, 

=item *
perldoc L<treereg>,

=item *
perldoc L<vgg>,

=item * The Syntax Highlight file for vim at L<http://www.vim.org/scripts/script.php?script_id=2453>
and L<http://nereida.deioc.ull.es/~vim/>

=item * I<Analisis Lexico y Sintactico>, (Notes for a course in compiler 
construction) by  Casiano Rodriguez-Leon. 
Available at  L<http://nereida.deioc.ull.es/~pl/perlexamples/>
Is the more complete and reliable source for Parse::Eyapp. However is in Spanish.

=item *
L<Parse::Yapp>,

=item *
Man pages of yacc(1),

=item *
Man pages of bison(1),

=item *
L<Language::AttributeGrammar>

=item *
L<Parse::RecDescent>.

=item *
L<HOP::Parser>

=item *
L<HOP::Lexer>

=item * ocamlyacc tutorial at 
L<http://plus.kaist.ac.kr/~shoh/ocaml/ocamllex-ocamlyacc/ocamlyacc-tutorial/ocamlyacc-tutorial.html>

=back

=head1 REFERENCES

=over

=item *
The classic Dragon's book I<Compilers: Principles, Techniques, and Tools> 
by Alfred V. Aho, Ravi Sethi and
Jeffrey D. Ullman (Addison-Wesley 1986)

=back



=head1 AUTHOR
 
Casiano Rodriguez-Leon (casiano@ull.es)

=head1 ACKNOWLEDGMENTS

This work has been supported by CEE (FEDER) and the Spanish Ministry of
I<Educacion y Ciencia> through I<Plan Nacional I+D+I> number TIN2005-08818-C04-04
(ULL::OPLINK project L<http://www.oplink.ull.es/>). 
Support from Gobierno de Canarias was through GC02210601
(I<Grupos Consolidados>).
The University of La Laguna has also supported my work in many ways
and for many years.

A large percentage of  code is verbatim taken from L<Parse::Yapp> 1.05.
The author of L<Parse::Yapp> is Francois Desarmenien.
 
I wish to thank Francois Desarmenien for his L<Parse::Yapp> module, 
to my students at La Laguna and to the Perl Community. Special thanks to 
my family and Larry Wall.

=head1 LICENCE AND COPYRIGHT
 
Copyright (c) 2006-2008 Casiano Rodriguez-Leon (casiano@ull.es). All rights reserved.

Parse::Yapp copyright is of Francois Desarmenien, all rights reserved. 1998-2001
 
These modules are free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L<perlartistic>.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 





