#!/usr/bin/perl -w use strict; use Parse::Eyapp; use Data::Dumper; use Language::AttributeGrammar; my $grammar = q{ %{ # use Data::Dumper; %} %right '=' %left '-' '+' %left '*' '/' %left NEG %tree bypass alias %% line: $exp { $_[1] } ; exp: %name NUM $NUM | %name VAR $VAR | %name ASSIGN $VAR '=' $exp | %name PLUS exp.left '+' exp.right | %name MINUS exp.left '-' exp.right | %name TIMES exp.left '*' exp.right | %name DIV exp.left '/' exp.right | %no bypass UMINUS '-' $exp %prec NEG | '(' $exp ')' { $_[2] } /* Let us simplify a bit the tree */ ; %% sub _Error { exists $_[0]->YYData->{ERRMSG} and do { print $_[0]->YYData->{ERRMSG}; delete $_[0]->YYData->{ERRMSG}; return; }; print "Syntax error.\n"; } sub _Lexer { my($parser)=shift; $parser->YYData->{INPUT} or $parser->YYData->{INPUT} = or return('',undef); $parser->YYData->{INPUT}=~s/^\s+//; for ($parser->YYData->{INPUT}) { s/^([0-9]+(?:\.[0-9]+)?)// and return('NUM',$1); s/^([A-Za-z][A-Za-z0-9_]*)// and return('VAR',$1); s/^(.)//s and return($1,$1); } } sub Run { my($self)=shift; $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error, #yydebug =>0xFF ); } }; # end grammar $Data::Dumper::Indent = 1; Parse::Eyapp->new_grammar( input=>$grammar, classname=>'Rule6', firstline =>7, outputfile => 'Calc.pm', ); my $parser = Rule6->new(); $parser->YYData->{INPUT} = "a = -(2*3+5-1)\n"; my $t = $parser->Run; print "\n***** Before ******\n"; print $t->str."\n"; print Dumper($t); my $attgram = new Language::AttributeGrammar <<'EOG'; # Compute the expression NUM: $/.val = { $ } TIMES: $/.val = { $.val * $.val } PLUS: $/.val = { $.val + $.val } MINUS: $/.val = { $.val - $.val } UMINUS: $/.val = { -$.val } ASSIGN: $/.val = { $.val } EOG my $res = $attgram->apply($t, 'val'); $Data::Dumper::Indent = 1; print "\n***** After ******\n"; print $t->str."\n"; print Dumper($t); print Dumper($res);