1# 2# Calc.yp 3# 4# Parse::Yapp input grammar example. 5# 6# This file is PUBLIC DOMAIN 7# 8# 9%right '=' 10%left '-' '+' 11%left '*' '/' 12%left NEG 13%right '^' 14 15%% 16input: #empty 17 | input line { push(@{$_[1]},$_[2]); $_[1] } 18; 19 20line: '\n' { $_[1] } 21 | exp '\n' { print "$_[1]\n" } 22 | error '\n' { $_[0]->YYErrok } 23; 24 25exp: NUM 26 | VAR { $_[0]->YYData->{VARS}{$_[1]} } 27 | VAR '=' exp { $_[0]->YYData->{VARS}{$_[1]}=$_[3] } 28 | exp '+' exp { $_[1] + $_[3] } 29 | exp '-' exp { $_[1] - $_[3] } 30 | exp '*' exp { $_[1] * $_[3] } 31 | exp '/' exp { 32 $_[3] 33 and return($_[1] / $_[3]); 34 $_[0]->YYData->{ERRMSG} 35 = "Illegal division by zero.\n"; 36 $_[0]->YYError; 37 undef 38 } 39 | '-' exp %prec NEG { -$_[2] } 40 | exp '^' exp { $_[1] ** $_[3] } 41 | '(' exp ')' { $_[2] } 42; 43 44%% 45 46sub _Error { 47 exists $_[0]->YYData->{ERRMSG} 48 and do { 49 print $_[0]->YYData->{ERRMSG}; 50 delete $_[0]->YYData->{ERRMSG}; 51 return; 52 }; 53 print "Syntax error.\n"; 54} 55 56sub _Lexer { 57 my($parser)=shift; 58 59 $parser->YYData->{INPUT} 60 or $parser->YYData->{INPUT} = <STDIN> 61 or return('',undef); 62 63 $parser->YYData->{INPUT}=~s/^[ \t]//; 64 65 for ($parser->YYData->{INPUT}) { 66 s/^([0-9]+(?:\.[0-9]+)?)// 67 and return('NUM',$1); 68 s/^([A-Za-z][A-Za-z0-9_]*)// 69 and return('VAR',$1); 70 s/^(.)//s 71 and return($1,$1); 72 } 73} 74 75sub Run { 76 my($self)=shift; 77 $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); 78} 79 80my($calc)=new Calc; 81$calc->Run; 82