/* a token and a syntactic with the same name: "type" */
%{
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 {
if (/\G(?= $RESTOFLIST)/gcx) { $self->YYSetReduce(')', 'ID:ENUM' ); }
else { $self->YYSetReduce(')', 'ID:RANGE' ); }
}
%lexer {
/\G(\s+)/gc and $self->tokenline($1 =~ tr{\n}{});
/\Gtype\b/gic and return ('type', 'type');
/\G($ID)/gc and return ('ID', $1);
/\G([0-9]+)/gc and return ('NUM', $1);
/\G\.\./gc and return ('..', '..');
/\G(.)/gc and return ($1, $1);
}
%strict
%token ID NUM
%left '-' '+'
%left '*' '/'
%expect-rr 1
%%
type_decl : 'type' ID '=' type ';'
;
type :
%name ENUM
'(' id_list ')'
| %name RANGE
expr '..' expr
;
id_list :
%name ID:ENUM
ID %PREC rangeORenum
| id_list ',' ID
;
expr : '(' expr ')' { $_[2] } /* bypass */
| %name PLUS expr '+' expr
| %name MINUS expr '-' expr
| %name TIMES expr '*' expr
| %name DIV expr '/' expr
| %name ID:RANGE
ID %PREC rangeORenum
| %name NUM NUM
;
%%
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);
}
=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