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