# Lhs.eyp %right '=' %left '-' '+' %left '*' '/' %left NEG %defaultaction { my $self = shift; my $name = $self->YYName(); bless { children => [ grep {ref($_)} @_] }, $name; } %% input: /* empty */ { [] } | input line { push @{$_[1]}, $_[2] if defined($_[2]); $_[1] } ; line: '\n' { } | exp '\n' { $_[1] } ; exp: NUM { $_[1] } | VAR { $_[1] } | %name ASSIGN VAR '=' exp | %name PLUS exp '+' exp | %name MINUS exp '-' exp { my $self = shift; $self->YYName('SUBTRACT'); # rename it $self->YYBuildAST(@_); # build the node } | %name TIMES exp '*' exp | %name DIV exp '/' exp | %name UMINUS '-' exp %prec NEG | '(' exp ')' { $_[2] } ; %% 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; for ($parser->YYData->{INPUT}) { s/^[ \t]+//; return('',undef) unless $_; s/^([0-9]+(?:\.[0-9]+)?)// and return('NUM', bless { attr => $1}, 'NUM'); s/^([A-Za-z][A-Za-z0-9_]*)// and return('VAR',bless {attr => $1}, 'VAR'); s/^(.)//s and return($1, $1); } return('',undef); } sub Run { my($self)=shift; $self->YYData->{INPUT} = <>; return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); }