# Default lexical analyzer
%lexer {
m{\G(\s+)}gc and $self->tokenline($1 =~ tr{\n}{});
m{\G(type|\.\.|\-|\+|\;|\/|\,|\=|\(|\*|\))}gc and return ($1, $1);
/\G([A-Za-z]\w*)/gc and return ('ID', $1);
/\G(\d+)/gc and return ('NUM', $1);
return ('', undef) if ($_ eq '') || (defined(pos($_)) && (pos($_) >= length($_)));
/\G\s*(\S+)/;
my $near = substr($1,0,10);
die( "Error inside the lexical analyzer near '". $near
."'. Line: ".$self->line()
.". File: '".$self->YYFilename()."'. No match found.\n");
}
%{
my $enum = 0;
sub rangeORenum {
# Goal. Towrite this code as:
# $enum = $self->YYPreParse('enum');
# Will parse using as start symbol 'enum', without changing the
# parsing position. Returns true if it matches. Has the same effect
# than the following code:
use Enum;
my $self = shift;
my $np = Enum->new();
my $pos = pos(${$self->{INPUT}});
$np->input($self->input());
$enum = 1;
eval {
$np->YYParse( yyerror => sub { $enum = 0; });
};
}
%}
%conflict rangeORenum {
if ($enum) { $self->YYSetReduce([',', ')'], 'ID:ENUM' ); }
else { $self->YYSetReduce([',', ')'], 'ID:RANGE' ); }
}
%token ID = /([A-Za-z]\w*)/
%token NUM = /(\d+)/
%left ','
%left '-' '+'
%left '*' '/'
#%expect-rr 2
%%
type_decl : 'type' ID '=' type ';'
;
type :
%name ENUM
# %code rangeORenum
PRErangeORenum '(' id_list ')'
| %name RANGE
# %code rangeORenum
PRErangeORenum expr '..' expr
;
enum:
'(' ids ')' ';'
;
ids :
ID
| ids ',' ID
;
PRErangeORenum:
/* empty */
{
goto &rangeORenum;
}
;
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 COMMA expr ',' expr
| %name ID:RANGE
ID %PREC rangeORenum
| %name NUM NUM
;
%%
=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 something like:
eyapp -TC pascalenumeratedvsrangesolvedviapreconflictsolver.eyp
Run it with this options:
$ ./pascalenumeratedvsrangesolvedviapreconflictsolver.pm -t -i -m 1 -c 'type e = (x, y, z);'
Try also these inputs:
type e = (x) .. (y);
type r = (x) .. y ;
type r = (x+2)*3 .. y/2 ;
type e = (x, y, z);
type e = (x);
type e = (x, y, z) .. (u+v);
=cut