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 | declare
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 declare: 'declare' property_list decl_type identifier';'
92 "PROPERTIES" => $_[2],
98 decl_type: decl_enum | decl_bitmap
107 decl_bitmap: 'bitmap'
113 typedef: 'typedef' property_list type identifier array_len ';'
116 "PROPERTIES" => $_[2],
123 type: struct | union | enum | bitmap | identifier
128 enum: 'enum' '{' enum_elements '}'
136 enum_element { [ $_[1] ] }
137 | enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
140 enum_element: identifier
141 | identifier '=' anytext { "$_[1]$_[2]$_[3]" }
144 bitmap: 'bitmap' '{' bitmap_elements '}'
152 bitmap_element { [ $_[1] ] }
153 | bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
156 bitmap_element: identifier '=' anytext { "$_[1] ( $_[3] )" }
159 struct: 'struct' '{' element_list1 '}'
166 empty_element: property_list ';'
170 "PROPERTIES" => $_[0],
175 base_or_empty: base_element ';' | empty_element;
177 optional_base_element:
178 property_list base_or_empty { $_[2]->{PROPERTIES} = util::FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
183 | union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
186 union: 'union' '{' union_elements '}'
193 base_element: property_list type pointers identifier array_len
197 "PROPERTIES" => $_[1],
207 | pointers '*' { $_[1]+1 }
212 | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
218 | base_element { [ $_[1] ] }
219 | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] }
225 | '[' anytext ']' { "$_[2]" }
231 | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); }
234 properties: property { $_[1] }
235 | properties ',' property { util::FlattenHash([$_[1], $_[3]]); }
238 property: identifier {{ "$_[1]" => "1" }}
239 | identifier '(' listtext ')' {{ "$_[1]" => "$_[3]" }}
244 | listtext ',' anytext { "$_[1] $_[3]" }
249 | commalisttext ',' anytext { "$_[1],$_[3]" }
254 | identifier | constant | text
255 | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
256 | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
257 | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
258 | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
259 | anytext '<' anytext { "$_[1]$_[2]$_[3]" }
260 | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
261 | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
262 | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
263 | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
264 | anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
265 | anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
268 identifier: IDENTIFIER
274 text: TEXT { "\"$_[1]\"" }
283 #####################################
290 if (exists $_[0]->YYData->{ERRMSG}) {
291 print $_[0]->YYData->{ERRMSG};
292 delete $_[0]->YYData->{ERRMSG};
295 my $line = $_[0]->YYData->{LINE};
296 my $last_token = $_[0]->YYData->{LAST_TOKEN};
297 my $file = $_[0]->YYData->{INPUT_FILENAME};
299 print "$file:$line: Syntax error near '$last_token'\n";
306 $parser->YYData->{INPUT}
310 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
312 for ($parser->YYData->{INPUT}) {
314 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
315 $parser->YYData->{LINE} = $1-1;
316 $parser->YYData->{INPUT_FILENAME} = $2;
319 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
320 $parser->YYData->{LINE} = $1-1;
321 $parser->YYData->{INPUT_FILENAME} = $2;
329 $parser->YYData->{LINE}++;
332 if (s/^\"(.*?)\"//) {
333 $parser->YYData->{LAST_TOKEN} = $1;
336 if (s/^(\d+)(\W|$)/$2/) {
337 $parser->YYData->{LAST_TOKEN} = $1;
338 return('CONSTANT',$1);
341 $parser->YYData->{LAST_TOKEN} = $1;
343 /^(coclass|interface|const|typedef|declare|union
344 |struct|enum|bitmap|void)$/x) {
347 return('IDENTIFIER',$1);
350 $parser->YYData->{LAST_TOKEN} = $1;
359 my $filename = shift;
361 my $saved_delim = $/;
364 if (! defined $cpp) {
367 my $data = `$cpp -xc $filename`;
370 $self->YYData->{INPUT} = $data;
371 $self->YYData->{LINE} = 0;
372 $self->YYData->{LAST_TOKEN} = "NONE";
374 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
376 foreach my $x (@{$idl}) {
377 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
378 # for 'object' interfaces
379 if (defined($x->{PROPERTIES}->{object})) {
380 foreach my $e (@{$x->{DATA}}) {
381 if($e->{TYPE} eq "FUNCTION") {
382 $e->{PROPERTIES}->{object} = 1;
383 unshift(@{$e->{DATA}},
384 { 'NAME' => 'ORPCthis',
386 'PROPERTIES' => { 'in' => '1' },
389 unshift(@{$e->{DATA}},
390 { 'NAME' => 'ORPCthat',
392 'PROPERTIES' => { 'out' => '1' },
400 if (defined($x->{BASE}) and $x->{BASE} ne "") {
401 my $parent = util::get_interface($idl, $x->{BASE});
403 if(not defined($parent)) {
404 die("No such parent interface " . $x->{BASE});
407 @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
409 $x->{INHERITED_DATA} = $x->{DATA};