1 ########################
2 # IDL Parse::Yapp parser
3 # Copyright (C) Andrew Tridgell <tridge@samba.org>
4 # released under the GNU GPL version 2 or later
8 # the precedence actually doesn't matter at all for this grammer, but
9 # by providing a precedence we reduce the number of conflicts
11 %left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
19 | idl interface { push(@{$_[1]}, $_[2]); $_[1] }
20 | idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
23 coclass: property_list 'coclass' identifier '{' interfaces '}' optional_semicolon
26 "PROPERTIES" => $_[1],
34 | interfaces interface { push(@{$_[1]}, $_[2]); $_[1] }
37 interface: property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
39 "TYPE" => "INTERFACE",
40 "PROPERTIES" => $_[1],
49 | ':' identifier { $_[2] }
53 definition { [ $_[1] ] }
54 | definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
58 definition: function | const | typedef
61 const: 'const' identifier identifier '=' anytext ';'
68 | 'const' identifier identifier array_len '=' anytext ';'
79 function: property_list type identifier '(' element_list2 ')' ';'
83 "RETURN_TYPE" => $_[2],
84 "PROPERTIES" => $_[1],
89 typedef: 'typedef' property_list type identifier array_len ';'
92 "PROPERTIES" => $_[2],
99 type: struct | union | enum | identifier
104 enum: 'enum' '{' enum_elements '}'
112 enum_element { [ $_[1] ] }
113 | enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
116 enum_element: identifier
117 | identifier '=' anytext { "$_[1]$_[2]$_[3]" }
120 struct: 'struct' '{' element_list1 '}'
127 union: 'union' '{' union_elements '}'
135 union_element { [ $_[1] ] }
136 | union_elements union_element { push(@{$_[1]}, $_[2]); $_[1] }
140 '[' 'case' '(' anytext ')' ']' base_element ';'
142 "TYPE" => "UNION_ELEMENT",
146 | '[' 'case' '(' anytext ')' ']' ';'
151 | '[' 'default' ']' base_element ';'
153 "TYPE" => "UNION_ELEMENT",
157 | '[' 'default' ']' ';'
164 base_element: property_list type pointers identifier array_len
168 "PROPERTIES" => $_[1],
178 | pointers '*' { $_[1]+1 }
185 | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
191 | base_element { [ $_[1] ] }
192 | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] }
198 | '[' anytext ']' { "$_[2]" }
204 | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); }
207 properties: property { $_[1] }
208 | properties ',' property { util::FlattenHash([$_[1], $_[3]]); }
211 property: identifier {{ "$_[1]" => "1" }}
212 | identifier '(' listtext ')' {{ "$_[1]" => "$_[3]" }}
217 | listtext ',' anytext { "$_[1] $_[3]" }
222 | commalisttext ',' anytext { "$_[1],$_[3]" }
227 | identifier | constant | text
228 | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
229 | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
230 | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
231 | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
232 | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
233 | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
234 | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
235 | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
236 | anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
237 | anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
240 identifier: IDENTIFIER
246 text: TEXT { "\"$_[1]\"" }
255 #####################################
262 if (exists $_[0]->YYData->{ERRMSG}) {
263 print $_[0]->YYData->{ERRMSG};
264 delete $_[0]->YYData->{ERRMSG};
267 my $line = $_[0]->YYData->{LINE};
268 my $last_token = $_[0]->YYData->{LAST_TOKEN};
269 my $file = $_[0]->YYData->{INPUT_FILENAME};
271 print "$file:$line: Syntax error near '$last_token'\n";
278 $parser->YYData->{INPUT}
282 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
284 for ($parser->YYData->{INPUT}) {
286 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
287 $parser->YYData->{LINE} = $1-1;
288 $parser->YYData->{INPUT_FILENAME} = $2;
291 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
292 $parser->YYData->{LINE} = $1-1;
293 $parser->YYData->{INPUT_FILENAME} = $2;
301 $parser->YYData->{LINE}++;
304 if (s/^\"(.*?)\"//) {
305 $parser->YYData->{LAST_TOKEN} = $1;
308 if (s/^(\d+)(\W|$)/$2/) {
309 $parser->YYData->{LAST_TOKEN} = $1;
310 return('CONSTANT',$1);
313 $parser->YYData->{LAST_TOKEN} = $1;
315 /^(coclass|interface|const|typedef|union
316 |struct|enum|void|case|default)$/x) {
319 return('IDENTIFIER',$1);
322 $parser->YYData->{LAST_TOKEN} = $1;
331 my $filename = shift;
333 my $saved_delim = $/;
336 if (! defined $cpp) {
339 my $data = `$cpp -xc $filename`;
342 $self->YYData->{INPUT} = $data;
343 $self->YYData->{LINE} = 0;
344 $self->YYData->{LAST_TOKEN} = "NONE";
346 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
348 foreach my $x (@{$idl}) {
349 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
350 # for 'object' interfaces
351 if (defined($x->{PROPERTIES}->{object})) {
352 foreach my $e (@{$x->{DATA}}) {
353 if($e->{TYPE} eq "FUNCTION") {
354 $e->{PROPERTIES}->{object} = 1;
355 unshift(@{$e->{DATA}},
356 { 'NAME' => 'ORPCthis',
358 'PROPERTIES' => { 'in' => '1' },
361 unshift(@{$e->{DATA}},
362 { 'NAME' => 'ORPCthat',
364 'PROPERTIES' => { 'out' => '1' },
372 if (defined($x->{BASE}) and $x->{BASE} ne "") {
373 my $parent = util::get_interface($idl, $x->{BASE});
375 if(not defined($parent)) {
376 die("No such parent interface " . $x->{BASE});
379 @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
381 $x->{INHERITED_DATA} = $x->{DATA};