/* 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 =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