Sophie

Sophie

distrib > Mageia > 4 > x86_64 > by-pkgid > ddfdf0b0f2e10c06cbb5bbb1f4ee8dd8 > files > 166

perl-Parse-Eyapp-1.182.0-3.mga4.x86_64.rpm

%{
our $VERSION = '0.01';
use base q{DebugTail}; 
%}

%strict
%token ID INT NUM

%right '='
%left '+'

%tree bypass

%expect 0 1  # 0 shift-reduce conflicts, 1 reduce-reduce conflict

%%
prog:
    %name EMPTY
    /* empty */
  | %name PROG
    prog stmt
;

stmt: 
    %name EXP
    expr ';' 
  | %name DECL
    decl    
;

expr:
    %name EXPID
    ID decexpconflict
  | %name NUM 
    NUM
  | %name TYPECAST
    INT '(' expr ')' /* typecast */ 
  | %name PLUS
    expr '+' expr
  | %name ASSIGN
    expr '=' expr
;

decl:
    %name DECLARATOR
    INT declarator ';'
  | %name DECLARATORINIT
    INT declarator '=' expr ';'
;

declarator:
    %name DECID
    ID decexpconflict
  | '(' declarator ')'
;

decexpconflict:
    /* empty. Just to solve the reduce-reduce conflict */
      {
        my $self = shift;

        if (${$self->input()} =~ m{^[)\s]*[;=]\s*}) {
          $self->YYSetReduce(')', 'DECID' );
        }
        else {
          $self->YYSetReduce(')', 'EXPID' ); 
        }
      }
;

%%

__PACKAGE__->lexer( 
  sub {
    my $self = shift;
    
    for (${$self->input()}) {
      s{^(\s*)}{};

      return ('', undef) unless $_;

      return ('INT', $1) if s{^(int\b)}{};

      return ('ID',  $1) if (s{^([a-zA-Z_]\w*)}{});

      return ('NUM', $1) if s/^(\d+)//;

      return ($1,    $1) if s/^(.)//;
    }

    return ('',undef);
  }
);

unless (caller()) {
  my $prompt = 'Try first "int (x) = 2;" then "int (x) + 2;" '.
               '(press <CR><CTRL-D> to finish): ';
  __PACKAGE__->main($prompt) 
}

####################################################

=head1 SYNOPSIS

Compile it with
 
   eyapp -b '' Cplusplus

Run it with:

   ./Cplusplus.pm -t

try with inputs:

     int (x) = 2;
     int (x) + 2;

the result will be the generated abstract sytax tree

=head1  C++ Ambiguities

This grammar models a problematic part of the C++ grammar—the ambiguity between certain
declarations and statements. For example,

     int (x) = y+z;

parses as either an expr or a stmt.


Eyapp detects this as a reduce/reduce conflict:

  State 17 contains 1 reduce/reduce conflict

  State 17:

	expr -> ID .	(Rule 5)
	declarator -> ID .	(Rule 11)

	')'	[reduce using rule 11 (declarator)]
	$default	reduce using rule 5 (expr)

The C++ rule is: take it as a declaration if it looks as a declaration,
otherwise is an expression.

This Eyapp parser solves the problem by dynamically changing the parser.

=head1 SEE ALSO

=over 2

=item * The file C<Cplusplus2.eyp> in C<examples/debuggintut>

=item * L<http://www.gnu.org/software/bison/manual/html_mono/bison.html#GLR-Parsers>

=item * L<http://en.wikipedia.org/wiki/Significantly_Prettier_and_Easier_C%2B%2B_Syntax>

=item * L<http://www.csse.monash.edu.au/~damian/papers/PS/ModestProposal.ps> 

=item * L<http://www.nobugs.org/developer/parsingcpp/>

=item * Edward Willink's "Meta-Compilation for C++" PhD thesis at L<http://www.computing.surrey.ac.uk/Research/CSRG/fog/FogThesis.pdf>

=back

=cut