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 %%
16 input: #empty
17 | input line { push(@{$_[1]},$_[2]); $_[1] }
18 ;
19
20 line: '\n' { $_[1] }
21 | exp '\n' { print "$_[1]\n" }
22 | error '\n' { $_[0]->YYErrok }
23 ;
24
25 exp: 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
46 sub _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
56 sub _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
75 sub Run {
76 my($self)=shift;
77 $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error) #, yydebug => 0x10 );
78 }
79
Casiano Rodríguez León
