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 | bitmap | 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 bitmap: 'bitmap' '{' bitmap_elements '}'
128 bitmap_element { [ $_[1] ] }
129 | bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
132 bitmap_element: identifier '=' anytext { "$_[1] ( $_[3] )" }
135 struct: 'struct' '{' element_list1 '}'
142 union: 'union' '{' union_elements '}'
150 union_element { [ $_[1] ] }
151 | union_elements union_element { push(@{$_[1]}, $_[2]); $_[1] }
155 '[' 'case' '(' anytext ')' ']' base_element ';'
157 "TYPE" => "UNION_ELEMENT",
161 | '[' 'case' '(' anytext ')' ']' ';'
166 | '[' 'default' ']' base_element ';'
168 "TYPE" => "UNION_ELEMENT",
172 | '[' 'default' ']' ';'
179 base_element: property_list type pointers identifier array_len
183 "PROPERTIES" => $_[1],
193 | pointers '*' { $_[1]+1 }
200 | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
206 | base_element { [ $_[1] ] }
207 | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] }
213 | '[' anytext ']' { "$_[2]" }
219 | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); }
222 properties: property { $_[1] }
223 | properties ',' property { util::FlattenHash([$_[1], $_[3]]); }
226 property: identifier {{ "$_[1]" => "1" }}
227 | identifier '(' listtext ')' {{ "$_[1]" => "$_[3]" }}
232 | listtext ',' anytext { "$_[1] $_[3]" }
237 | commalisttext ',' anytext { "$_[1],$_[3]" }
242 | identifier | constant | text
243 | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
244 | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
245 | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
246 | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
247 | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
248 | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
249 | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
250 | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
251 | anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
252 | anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
255 identifier: IDENTIFIER
261 text: TEXT { "\"$_[1]\"" }
270 #####################################
277 if (exists $_[0]->YYData->{ERRMSG}) {
278 print $_[0]->YYData->{ERRMSG};
279 delete $_[0]->YYData->{ERRMSG};
282 my $line = $_[0]->YYData->{LINE};
283 my $last_token = $_[0]->YYData->{LAST_TOKEN};
284 my $file = $_[0]->YYData->{INPUT_FILENAME};
286 print "$file:$line: Syntax error near '$last_token'\n";
293 $parser->YYData->{INPUT}
297 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
299 for ($parser->YYData->{INPUT}) {
301 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
302 $parser->YYData->{LINE} = $1-1;
303 $parser->YYData->{INPUT_FILENAME} = $2;
306 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
307 $parser->YYData->{LINE} = $1-1;
308 $parser->YYData->{INPUT_FILENAME} = $2;
316 $parser->YYData->{LINE}++;
319 if (s/^\"(.*?)\"//) {
320 $parser->YYData->{LAST_TOKEN} = $1;
323 if (s/^(\d+)(\W|$)/$2/) {
324 $parser->YYData->{LAST_TOKEN} = $1;
325 return('CONSTANT',$1);
328 $parser->YYData->{LAST_TOKEN} = $1;
330 /^(coclass|interface|const|typedef|union
331 |struct|enum|bitmap|void|case|default)$/x) {
334 return('IDENTIFIER',$1);
337 $parser->YYData->{LAST_TOKEN} = $1;
346 my $filename = shift;
348 my $saved_delim = $/;
351 if (! defined $cpp) {
354 my $data = `$cpp -xc $filename`;
357 $self->YYData->{INPUT} = $data;
358 $self->YYData->{LINE} = 0;
359 $self->YYData->{LAST_TOKEN} = "NONE";
361 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
363 foreach my $x (@{$idl}) {
364 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
365 # for 'object' interfaces
366 if (defined($x->{PROPERTIES}->{object})) {
367 foreach my $e (@{$x->{DATA}}) {
368 if($e->{TYPE} eq "FUNCTION") {
369 $e->{PROPERTIES}->{object} = 1;
370 unshift(@{$e->{DATA}},
371 { 'NAME' => 'ORPCthis',
373 'PROPERTIES' => { 'in' => '1' },
376 unshift(@{$e->{DATA}},
377 { 'NAME' => 'ORPCthat',
379 'PROPERTIES' => { 'out' => '1' },
387 if (defined($x->{BASE}) and $x->{BASE} ne "") {
388 my $parent = util::get_interface($idl, $x->{BASE});
390 if(not defined($parent)) {
391 die("No such parent interface " . $x->{BASE});
394 @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
396 $x->{INHERITED_DATA} = $x->{DATA};