package GenSupport; use strict; use warnings; use Getopt::Long; use Test::LectroTest::Generator qw(:all); use Parse::Eyapp::TokenGen; my %st; # Symbol Table sub defined_variable { my ($parser, $var) = @_; $st{$var} = 1; } #my $WHITESPACES = String( length=>[0,1], charset=>" \t\n", size => 100 ); sub evaluate_using_perl { # if possible my $perlexp = shift; $perlexp =~ s/\b([a-zA-Z])/\$$1/g; # substitute A by $A everywhere $perlexp =~ s/\^/**/g; # substitute power operator: ^ by ** my $res = eval "no warnings; no strict;$perlexp"; if ($@ =~ /Illegal division/) { $res = "error. Division by zero."; } elsif ($@) { # Our calc notation is incompatible with perl in a few gotchas # Perl interprets -- in a different way $@ =~ m{(.*)}; # Show only the first line of error message $res = "Calculator syntax differs from Perl. Can't compute the result: $1"; } $res; } sub main { my $package = shift; my $debug = shift || 0; my $numtimes = shift || 1; my $result = GetOptions ( "debug!" => \$debug, "times=i" => \$numtimes, ); $debug = 0x1F if $debug; my $gen = $package->new(); # set_tokenweightsandgenerators receives the parser object and the pairs # token => [weight, generator] or token => weight # and sets the weight and generator attributes of the tokens. for (1..$numtimes) { my $exp = $gen->generate( yylex => { NUM => [ 2, Int(range=>[0, 9], sized=>0)], VAR => [ 0, # At the beginning, no variables are defined Gen { return Elements(keys %st)->generate if keys %st; return Int(range=>[0, 9], sized=>0)->generate; }, ], VARDEF => [ 2, String( length=>[1,2], charset=>"A-NP-Z", size => 100 ) ], '=' => 2, '-' => 1, '+' => 2, '*' => 4, '/' => 2, '^' => 0.5, ';' => 1, '(' => 1, ')' => 2, '' => 2, 'error' => 0, }, yydebug => $debug, # 0x1F ); my $res = evaluate_using_perl($exp); print "\n# result: $res\n$exp\n"; } } 1;