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 ';'
71 function: property_list type identifier '(' element_list2 ')' ';'
75 "RETURN_TYPE" => $_[2],
76 "PROPERTIES" => $_[1],
81 typedef: 'typedef' type identifier array_len ';'
90 type: struct | union | enum | identifier
95 enum: 'enum' '{' enum_elements '}'
103 enum_element { [ $_[1] ] }
104 | enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
107 enum_element: identifier
108 | identifier '=' anytext { "$_[1]$_[2]$_[3]" }
111 struct: property_list 'struct' '{' element_list1 '}'
114 "PROPERTIES" => $_[1],
119 union: property_list 'union' '{' union_elements '}'
122 "PROPERTIES" => $_[1],
128 union_element { [ $_[1] ] }
129 | union_elements union_element { push(@{$_[1]}, $_[2]); $_[1] }
133 '[' 'case' '(' anytext ')' ']' base_element ';'
135 "TYPE" => "UNION_ELEMENT",
139 | '[' 'case' '(' anytext ')' ']' ';'
144 | '[' 'default' ']' base_element ';'
146 "TYPE" => "UNION_ELEMENT",
150 | '[' 'default' ']' ';'
157 base_element: property_list type pointers identifier array_len
161 "PROPERTIES" => $_[1],
171 | pointers '*' { $_[1]+1 }
178 | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
184 | base_element { [ $_[1] ] }
185 | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] }
191 | '[' anytext ']' { "$_[2]" }
197 | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); }
200 properties: property { $_[1] }
201 | properties ',' property { util::FlattenHash([$_[1], $_[3]]); }
204 property: identifier {{ "$_[1]" => "1" }}
205 | identifier '(' listtext ')' {{ "$_[1]" => "$_[3]" }}
210 | listtext ',' anytext { "$_[1] $_[3]" }
215 | commalisttext ',' anytext { "$_[1],$_[3]" }
220 | identifier | constant | text
221 | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
222 | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
223 | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
224 | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
225 | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
226 | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
227 | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
228 | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
229 | anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
232 identifier: IDENTIFIER
238 text: TEXT { "\"$_[1]\"" }
247 #####################################
254 if (exists $_[0]->YYData->{ERRMSG}) {
255 print $_[0]->YYData->{ERRMSG};
256 delete $_[0]->YYData->{ERRMSG};
259 my $line = $_[0]->YYData->{LINE};
260 my $last_token = $_[0]->YYData->{LAST_TOKEN};
261 my $file = $_[0]->YYData->{INPUT_FILENAME};
263 print "$file:$line: Syntax error near '$last_token'\n";
270 $parser->YYData->{INPUT}
274 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
276 for ($parser->YYData->{INPUT}) {
278 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
279 $parser->YYData->{LINE} = $1-1;
280 $parser->YYData->{INPUT_FILENAME} = $2;
283 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
284 $parser->YYData->{LINE} = $1-1;
285 $parser->YYData->{INPUT_FILENAME} = $2;
293 $parser->YYData->{LINE}++;
296 if (s/^\"(.*?)\"//) {
297 $parser->YYData->{LAST_TOKEN} = $1;
300 if (s/^(\d+)(\W|$)/$2/) {
301 $parser->YYData->{LAST_TOKEN} = $1;
302 return('CONSTANT',$1);
305 $parser->YYData->{LAST_TOKEN} = $1;
307 /^(coclass|interface|const|typedef|union
308 |struct|enum|void|case|default)$/x) {
311 return('IDENTIFIER',$1);
314 $parser->YYData->{LAST_TOKEN} = $1;
323 my $filename = shift;
325 my $saved_delim = $/;
328 if (! defined $cpp) {
331 my $data = `$cpp -xc $filename`;
334 $self->YYData->{INPUT} = $data;
335 $self->YYData->{LINE} = 0;
336 $self->YYData->{LAST_TOKEN} = "NONE";
338 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
340 foreach my $x (@{$idl}) {
341 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
342 # for 'object' interfaces
343 if (defined($x->{PROPERTIES}->{object})) {
344 foreach my $e (@{$x->{DATA}}) {
345 if($e->{TYPE} eq "FUNCTION") {
346 $e->{PROPERTIES}->{object} = 1;
347 unshift(@{$e->{DATA}},
348 { 'NAME' => 'ORPCthis',
350 'PROPERTIES' => { 'in' => '1' },
353 unshift(@{$e->{DATA}},
354 { 'NAME' => 'ORPCthat',
356 'PROPERTIES' => { 'out' => '1' },
364 if (defined($x->{BASE}) and $x->{BASE} ne "") {
365 my $parent = util::get_interface($idl, $x->{BASE});
367 if(not defined($parent)) {
368 die("No such parent interface " . $x->{BASE});
371 @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
373 $x->{INHERITED_DATA} = $x->{DATA};