#!/usr/bin/perl
#####
# from http://www.adp-gmbh.ch/perl/rec_descent.html
###############
use strict;
use warnings;

use Parse::RecDescent;

my $grammar = q {
                                         { my %vars }
start:          statements               

statements:     statement ';' statements { print "statement;statements " 
					    . "(" . $item[1] . ', ' . $item[3]. ")\n";
					   $return = $item[3]  }
              | statement                { print "statement '" . $item[1]. "'\n";
					   $return = $item[1]  }

statement:      variable '=' statement   { $vars{$item[1]} = $item[3];
					   print "variable=statement (" 
				            . "item1='" . $item[1]. "', " 
				            . "item3='" . $item[3]. "', " 
				            . "vars{item1}='" . $vars{$item[1]} . "')\n";
                                           $return = $vars{$item[1]} }
              | expression               { print "expression '" . $item[1] . "'\n";
					   $return = $item[1]  }

expression:     term '+' expression      { $item[1] + $item[3] }
              | term '-' expression      { $item[1] - $item[3] }
              | term			 { $item[1] }

term:           factor '*' term          { $item[1] * $item[3] }
              | factor '/' term          { $item[1] / $item[3] }
              | factor			 { $item[1] }

factor:         number
              | variable                 { $vars{$item[1]} ||= 0 }
              | '+' factor               { $item[2] }
              | '-' factor               { -1 * $item[2] }
              | '(' statement ')'        { $item[2] }

number:         /\d+/                    { $item[1] }

variable:       /[a-z]+/i		 { $item[1] }

};

my $parser = Parse::RecDescent->new($grammar);

my @text = ( # "three=3;six=2*three;eight=three+5;2+eight*six+50",
	     # "x",
	     # "x+1",
	     # "x=0; x+1",
	     "x=0; x=x+1",
	     # "x=0; x=x+1; x",
	     # "x=0; x=x+1; x+1",
	    );
for my $text (@text){
  my $result = $parser->start($text);
  print "result of '$text' is $result .\n";
}



