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%%
21exp:
22	NUM
23	|
24	TEXT                { "\"$_[1]\"" }
25	|
26	func
27	|
28	var
29	|
30	'~' exp %prec INV   { "~$_[2]" }
31	|
32	exp '+' exp         { "$_[1] + $_[3]" }
33	|
34	exp '-' exp         { "$_[1] - $_[3]" }
35	|
36	exp '*' exp         { "$_[1] * $_[3]" }
37	|
38	exp '%' exp         { "$_[1] % $_[3]" }
39	|
40	exp '<' exp         { "$_[1] < $_[3]" }
41	|
42	exp '>' exp         { "$_[1] > $_[3]" }
43	|
44	exp '|' exp         { "$_[1] | $_[3]" }
45	|
46	exp '==' exp        { "$_[1] == $_[3]" }
47	|
48	exp '<=' exp        { "$_[1] <= $_[3]" }
49	|
50	exp '=>' exp        { "$_[1] => $_[3]" }
51	|
52	exp '<<' exp        { "$_[1] << $_[3]" }
53	|
54	exp '>>' exp        { "$_[1] >> $_[3]" }
55	|
56	exp '!=' exp        { "$_[1] != $_[3]" }
57	|
58	exp '||' exp        { "$_[1] || $_[3]" }
59	|
60	exp '&&' exp        { "$_[1] && $_[3]" }
61	|
62	exp '&' exp         { "$_[1] & $_[3]" }
63	|
64	exp '?' exp ':' exp { "$_[1]?$_[3]:$_[5]" }
65	|
66	'~' exp             { "~$_[1]" }
67	|
68	'!' exp             { "not $_[1]" }
69	|
70	exp '/' exp         { "$_[1] / $_[3]" }
71	|
72	'-' exp %prec NEG   { "-$_[2]" }
73	|
74	'&' exp %prec ADDROF { "&$_[2]" }
75	|
76	exp '^' exp         { "$_[1]^$_[3]" }
77	|
78	'(' exp ')'         { "($_[2])" }
79;
80
81possible_pointer:
82	VAR                              { $_[0]->_Lookup($_[1]) }
83	|
84	'*' possible_pointer %prec DEREF { $_[0]->_Dereference($_[2]); "*$_[2]" }
85;
86
87var:
88	possible_pointer    { $_[0]->_Use($_[1]) }
89	|
90	var '.'	VAR         { $_[0]->_Use("$_[1].$_[3]") }
91	|
92	'(' var ')'         { "($_[2])" }
93	|
94	var '->' VAR        { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
95;
96
97
98func:
99	VAR '(' opt_args ')' { "$_[1]($_[3])" }
100;
101
102opt_args:
103	#empty
104	{ "" }
105	|
106	args
107;
108
109exp_or_possible_pointer:
110	exp
111	|
112	possible_pointer
113;
114
115args:
116	exp_or_possible_pointer
117	|
118	exp_or_possible_pointer ',' args { "$_[1], $_[3]" }
119;
120
121%%
122
123package Parse::Pidl::Expr;
124
125sub _Lexer {
126	my($parser)=shift;
127
128	$parser->YYData->{INPUT}=~s/^[ \t]//;
129
130	for ($parser->YYData->{INPUT}) {
131		if (s/^(0x[0-9A-Fa-f]+)//) {
132			$parser->YYData->{LAST_TOKEN} = $1;
133			return('NUM',$1);
134		}
135		if (s/^([0-9]+(?:\.[0-9]+)?)//) {
136			$parser->YYData->{LAST_TOKEN} = $1;
137			return('NUM',$1);
138		}
139		if (s/^([A-Za-z_][A-Za-z0-9_]*)//) {
140			$parser->YYData->{LAST_TOKEN} = $1;
141			return('VAR',$1);
142		}
143		if (s/^\"(.*?)\"//) {
144			$parser->YYData->{LAST_TOKEN} = $1;
145			return('TEXT',$1); 
146		}
147		if (s/^(==|!=|<=|>=|->|\|\||<<|>>|&&)//s) {
148			$parser->YYData->{LAST_TOKEN} = $1;
149			return($1,$1);
150		}
151		if (s/^(.)//s) {
152			$parser->YYData->{LAST_TOKEN} = $1;
153			return($1,$1);
154		}
155	}
156}
157
158sub _Use($$)
159{
160	my ($self, $x) = @_;
161	if (defined($self->YYData->{USE})) {
162		return $self->YYData->{USE}->($x);
163	}
164	return $x;
165}
166
167sub _Lookup($$) 
168{
169	my ($self, $x) = @_;
170	return $self->YYData->{LOOKUP}->($x);
171}
172
173sub _Dereference($$)
174{
175	my ($self, $x) = @_;
176	if (defined($self->YYData->{DEREFERENCE})) {
177		$self->YYData->{DEREFERENCE}->($x);
178	}
179}
180
181sub _Error($)
182{
183	my ($self) = @_;
184	if (defined($self->YYData->{LAST_TOKEN})) {
185		$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."' near `". $self->YYData->{LAST_TOKEN} . "'");
186	} else {
187		$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."'");
188	}
189}
190
191sub Run {
192	my($self, $data, $error, $lookup, $deref, $use) = @_;
193
194	$self->YYData->{FULL_INPUT} = $data;
195	$self->YYData->{INPUT} = $data;
196	$self->YYData->{LOOKUP} = $lookup;
197	$self->YYData->{DEREFERENCE} = $deref;
198	$self->YYData->{ERROR} = $error;
199	$self->YYData->{USE} = $use;
200
201	return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error);
202}
203