%{
=head1 SYNOPSIS
This grammar deals with the famous ambiguous PL/I phrase:
if then=if then if=then
The (partial) solution uses C<YYExpect> in the lexical analyzer to predict the token
that fulfills the parser expectatives.
Compile it with:
eyapp -b '' PL_I_conflict.eyp
Run it with;
./PL_I_conflict.pm -t
or
./PL_I_conflict.pm -d -t
=cut
use base q{DebugTail};
use List::Util qw{first};
%}
%strict
%token ID
%tree bypass
%%
stmt:
ifstmt
| assignstmt
;
# Exercise: change this production
# for 'if' expr 'then' stmt
# and check with input 'if then=if then if=then'. The problem arises again
ifstmt:
%name IF
'if' expr 'then' expr
;
assignstmt:
id '=' expr
;
expr:
%name EQ
id '=' id
| id
;
id:
%name ID
ID
;
%%
# Adaptative lexer
__PACKAGE__->lexer(
sub {
my $parser = shift;
for (${$parser->input()}) { # contextualize
m{\G\s*(\#.*)?}gc;
m{\G([a-zA-Z_]\w*)}gc and do {
my $id = $1;
return ('if', 'if') if ($id eq 'if') && $parser->expects('if');
return ('then', 'then') if ($id eq 'then') && $parser->expects('then');
return ('ID', $id);
};
m{\G(.)}gc and return ($1, $1);
return('',undef);
}
}
);
my $prompt = 'Try input "if then=if then if=then" '.
'(press <CR><CTRL-D> to finish): ';
__PACKAGE__->main($prompt) unless caller();