The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
%{
=head1 SYNOPSIS

See 

=over 2

=item * File pascalenumeratedvsrange.eyp in examples/debuggintut/

=item * The Bison manual L<http://www.gnu.org/software/bison/manual/html_mono/bison.html>

=back

Compile it with:

            eyapp -b '' pascalenumeratedvsrangesolvedviadyn.eyp

run it with this options:

            ./pascalenumeratedvsrangesolvedviadyn.pm -t

Try these inputs:

                type r = (x) ..  y ;
                type r = (x+2)*3 ..  y/2 ;
                type e = (x, y, z);
                type e = (x);

=cut

my $ID = qr{[A-Za-z][A-Za-z0-9_]*};
             # Identifiers separated by commas
my $IDLIST = qr{ \s*(?:\s*,\s* $ID)* \s* }x;
             # list followed by a closing par and a semicolon 
my $RESTOFLIST = qr{$IDLIST \) \s* ; }x;
%}

%conflict rangeORenum {
          my $parser = shift;
          if (${$parser->input()} =~ m{\G(?= $RESTOFLIST)}gcx) {
              $parser->YYSetReduce(')', 'ID:ENUM' );
            }
            else {
              $parser->YYSetReduce(')', 'ID:RANGE' );
            }
      }

%namingscheme {
  #Receives a Parse::Eyapp object describing the grammar
  my $self = shift;

  $self->tokennames(
    '(' => 'LP',
    '..' => 'DOTDOT',
    ',' => 'COMMA',
    ')' => 'RP',
    '+' => 'PLUS',
    '-' => 'MINUS',
    '*' => 'TIMES',
    '/' => 'DIV',
  );

  # returns the handler that will give names
  # to the right hand sides
  \&give_rhs_name;
}

#%strict

%token ID NUM DOTDOT TYPE
%left   '-' '+'
%left   '*' '/'

%expect 0 1

%tree

%%

type_decl : TYPE ID '=' type ';'
;

type : 
      %name ENUM
      '(' id_list ')'
    | %name RANGE
      expr DOTDOT expr
;

id_list : 
      %name ID:ENUM
      ID                      %PREC rangeORenum
    | id_list ',' ID
;

expr : '(' expr ')'
    | expr '+' expr
    | expr '-' expr
    | expr '*' expr
    | expr '/' expr
    | %name ID:RANGE
      ID                     %PREC rangeORenum
    | NUM
;

%%

__PACKAGE__->lexer(
  sub {
    my $parser = shift;

    for (${$parser->input()}) {    # contextualize
      m{\G(\s*)}gc;
      $parser->tokenline($1 =~ tr{\n}{});

      m{\Gtype\b}gic                 and return ('TYPE', 'TYPE');

      m{\G($ID)}gc                   and return ('ID',  $1);

      m{\G([0-9]+)}gc                and return ('NUM', $1);

      m{\G\.\.}gc                    and return ('DOTDOT',  '..');

      m{\G(.)}gc                     and return ($1,    $1);

      return('',undef);
    }
  }
);

unless (caller()) {
  $Parse::Eyapp::Node::INDENT = 1;
  my $prompt = << 'EOP';
Try this input:
    type 
    r
    =
    (x)
    ..
    y
    ;

Here are other inputs you can try:

    type r = (x+2)*3 ..  y/2 ;
    type e = (x, y, z);
    type e = (x);

Press CTRL-D (CTRL-W in windows) to produce the end-of-file
EOP
  __PACKAGE__->main($prompt); 
}