1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
#! /usr/local/bin/perl -w
use Parse::RecDescent;
$text = "1 + 2 * 3 ** 4";
$grammar = q{
<autotree>
expr : <leftop: conj /\|\|/ conj>
conj : <leftop: addn /&&/ addn>
addn : <leftop: mult /[+-]/ mult >
mult : <leftop: expo /[*\/\%]/ expo >
expo : <leftop: value /\^|\*\*/ value >
value : /\d+(\.\d+)?/
};
my $extract_tree = Parse::RecDescent->new($grammar);
my $tree = $extract_tree->expr($text);
use Data::Dumper 'Dumper';
print Dumper $tree;
print $tree->eval();
package expr;
use List::Util 'reduce';
sub eval { reduce {$_[0] || $_[1]} map $_->eval(), @{$_[0]{__DIRECTIVE1__}} }
package conj ;
use List::Util 'reduce';
sub eval { reduce {$_[0] && $_[1]} map $_->eval(), @{$_[0]{__DIRECTIVE1__}} }
package addn ;
use List::Util 'reduce';
sub eval { reduce {$_[0] + $_[1]} map $_->eval(), @{$_[0]{__DIRECTIVE1__}} }
package mult ;
use List::Util 'reduce';
sub eval { reduce {$_[0] * $_[1]} map $_->eval(), @{$_[0]{__DIRECTIVE1__}} }
package expo ;
use List::Util 'reduce';
sub eval { reduce {$_[0] ** $_[1]} map $_->eval(), @{$_[0]{__DIRECTIVE1__}} }
package value ;
sub eval { return $_[0]{__VALUE__} }
|