The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# file: GeneratorD.eyp
# compile with: eyapp -C GeneratorD.eyp
# then run: ./Generator.pm
# division checked
%left   '-' '+'
%left   '*' '/'
%right  '^'

%defaultaction {
  my $parser = shift;

  return Paste(@_);
}

%{
use Test::LectroTest::Generator qw(:all);
use base q{Parse::Eyapp::TokenGen};
%}

%%

exp:
    NUM                
  | exp '+' exp        
  | exp '-' exp        
  | exp '*' exp        
  | exp.n '/' exp.d 
      {
        Gen(
          sub {
            my ($denexp, $e);
            do {
              $denexp = $d->generate(); # generate an expression
              $e = eval($denexp);       # evaluate it
            } while ($e == 0);
            return $n->generate()."/$denexp";
          }
        )
      }
  | exp '^' exp        
  | '('   { $_[0]->pushdeltaweight('(' => -1, ')' => +1, '+' => +1, ); } 
      $exp 
    ')'
      {
         $_[0]->popweight; 
         Paste(Unit("("), $exp, Unit(")"))
      }
;

%%

use Getopt::Long;
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 $parser = $package->new();


  my $expg = $parser->YYParse( 
      # LexerGen receives the pairs 
      #   token => [weight, generator] or token => weight
      # and sets the weight and generator attributes of the tokens.
      yylex => $parser->LexerGen(
        NUM => [ 2, Int(range=>[0, 9], sized=>0)],
        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
    );

  for (1..$numtimes) {
    my $exp = $expg->generate();

    print "$exp\n";

  }
}