58704ff89e0eda41020789c9be3e0d25a0be8fb6
[samba.git] / source4 / pidl / expr.yp
1 # expr.yp
2 # Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
3 # Published under the GNU GPL
4
5 %left   '->'
6 %right  '!' '~' 
7 %left   '*' '/' '%'
8 %left   '+' '-'
9 %left   '<<' '>>'
10 %left   '>' '<'
11 %left   '==' '!=' 
12 %left   '&'
13 %left   '|'
14 %left   '&&'
15 %left   '||'
16 %left   '?' ':'
17 %left   NEG DEREF ADDROF INV
18 %left   '.'
19
20 %%
21 exp:        NUM
22                 |       TEXT                            { "\"$_[1]\"" }
23                 |       func
24                 |       exp '.' VAR                     { "$_[1].$_[3]" }
25         |   VAR                 { $_[0]->_Lookup($_[1]) }
26         |   '*' exp %prec DEREF { $_[0]->_Dereference($_[2]); "*$_[2]" }
27         |   '~' exp %prec INV   { "~$_[2]" }
28         |   exp '+' exp         { "$_[1] + $_[3]" }
29         |   exp '-' exp         { "$_[1] - $_[3]" }
30         |   exp '*' exp         { "$_[1] * $_[3]" }
31         |   exp '%' exp         { "$_[1] % $_[3]" }
32         |   exp '<' exp         { "$_[1] < $_[3]" }
33         |   exp '>' exp         { "$_[1] > $_[3]" }
34         |   exp '|' exp         { "$_[1] | $_[3]" }
35         |   exp '==' exp         { "$_[1] == $_[3]" }
36         |   exp '<=' exp         { "$_[1] <= $_[3]" }
37         |   exp '=>' exp         { "$_[1] => $_[3]" }
38         |   exp '<<' exp         { "$_[1] << $_[3]" }
39         |   exp '>>' exp         { "$_[1] >> $_[3]" }
40         |   exp '!=' exp         { "$_[1] != $_[3]" }
41         |   exp '||' exp        { "$_[1] || $_[3]" }
42         |   exp '&&' exp        { "$_[1] && $_[3]" }
43         |   exp '&' exp         { "$_[1] & $_[3]" }
44                 |       exp '->' VAR            { $_[1]."->".$_[3] }
45                 |       exp '?' exp ':' exp { "$_[1]?$_[3]:$_[5]" }
46                 |       '~' exp                         { "~$_[1]" }
47                 |       '!' exp                         { "not $_[1]" }
48         |   exp '/' exp         { "$_[1] / $_[3]" }
49         |   '-' exp %prec NEG   { "-$_[2]" }
50         |   '&' exp %prec ADDROF { "&$_[2]" }
51         |   exp '^' exp         { "$_[1]^$_[3]" }
52         |   '(' exp ')'         { "($_[2])" }
53 ;
54
55 func: VAR '(' opt_args ')' { "$_[1]($_[3])" };
56 opt_args: { "" } | args;
57 args: exp | exp ',' args { "$_[1], $_[3]" };
58
59 %%
60
61 package Parse::Pidl::Expr;
62
63 sub _Lexer {
64     my($parser)=shift;
65
66     $parser->YYData->{INPUT}=~s/^[ \t]//;
67
68     for ($parser->YYData->{INPUT}) {
69         if (s/^(0x[0-9A-Fa-f]+)//) {
70                         $parser->YYData->{LAST_TOKEN} = $1;
71             return('NUM',$1);
72                 }
73         if (s/^([0-9]+(?:\.[0-9]+)?)//) {
74                         $parser->YYData->{LAST_TOKEN} = $1;
75             return('NUM',$1);
76                 }
77         if (s/^([A-Za-z_][A-Za-z0-9_]*)//) {
78                         $parser->YYData->{LAST_TOKEN} = $1;
79                 return('VAR',$1);
80                 }
81                 if (s/^\"(.*?)\"//) {
82                         $parser->YYData->{LAST_TOKEN} = $1;
83                         return('TEXT',$1); 
84                 }
85                 if (s/^(==|!=|<=|>=|->|\|\||<<|>>|&&)//s) {
86                         $parser->YYData->{LAST_TOKEN} = $1;
87             return($1,$1);
88                 }
89         if (s/^(.)//s) {
90                         $parser->YYData->{LAST_TOKEN} = $1;
91             return($1,$1);
92                 }
93     }
94 }
95
96 sub _Lookup($$) 
97 {
98         my ($self, $x) = @_;
99         return $self->YYData->{LOOKUP}->($x);
100 }
101
102 sub _Dereference($$)
103 {
104         my ($self, $x) = @_;
105         if (defined($self->YYData->{DEREFERENCE})) {
106                 $self->YYData->{DEREFERENCE}->($x);
107         }
108 }
109
110 sub _Error($)
111 {
112         my ($self) = @_;
113         $self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."' near `". $self->YYData->{LAST_TOKEN} . "'");
114 }
115
116 sub Run {
117     my($self, $data, $error, $lookup, $deref) = @_;
118     $self->YYData->{FULL_INPUT} = $data;
119     $self->YYData->{INPUT} = $data;
120     $self->YYData->{LOOKUP} = $lookup;
121     $self->YYData->{DEREFERENCE} = $deref;
122     $self->YYData->{ERROR} = $error;
123     return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error);
124 }