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 '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
20 push(@{$_[1]}, $_[2]); $_[1]
24 interface: property_list 'interface' identifier base_interface '{' definitions '}'
26 "TYPE" => "INTERFACE",
27 "PROPERTIES" => $_[1],
36 | ':' identifier { $_[2] }
40 definition { [ $_[1] ] }
41 | definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
45 definition: function | const | typedef
48 const: 'const' identifier identifier '=' anytext ';'
58 function: property_list type identifier '(' element_list2 ')' ';'
62 "RETURN_TYPE" => $_[2],
63 "PROPERTIES" => $_[1],
68 typedef: 'typedef' type identifier array_len ';'
77 type: struct | union | enum | identifier
82 enum: 'enum' '{' enum_elements '}'
90 enum_element { [ $_[1] ] }
91 | enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
94 enum_element: identifier
95 | identifier '=' anytext { "$_[1]$_[2]$_[3]" }
98 struct: property_list 'struct' '{' element_list1 '}'
101 "PROPERTIES" => $_[1],
106 union: property_list 'union' '{' union_elements '}'
109 "PROPERTIES" => $_[1],
115 union_element { [ $_[1] ] }
116 | union_elements union_element { push(@{$_[1]}, $_[2]); $_[1] }
120 '[' 'case' '(' anytext ')' ']' base_element ';'
122 "TYPE" => "UNION_ELEMENT",
126 | '[' 'case' '(' anytext ')' ']' ';'
131 | '[' 'default' ']' base_element ';'
133 "TYPE" => "UNION_ELEMENT",
137 | '[' 'default' ']' ';'
144 base_element: property_list type pointers identifier array_len
148 "PROPERTIES" => $_[1],
158 | pointers '*' { $_[1]+1 }
165 | element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
171 | base_element { [ $_[1] ] }
172 | element_list2 ',' base_element { push(@{$_[1]}, $_[3]); $_[1] }
178 | '[' anytext ']' { "$_[2]" }
184 | property_list '[' properties ']' { util::FlattenHash([$_[1],$_[3]]); }
187 properties: property { $_[1] }
188 | properties ',' property { util::FlattenHash([$_[1], $_[3]]); }
191 property: identifier {{ "$_[1]" => "1" }}
192 | identifier '(' listtext ')' {{ "$_[1]" => "$_[3]" }}
197 | listtext ',' anytext { "$_[1] $_[3]" }
202 | identifier | constant | text
203 | anytext '-' anytext { "$_[1]$_[2]$_[3]" }
204 | anytext '.' anytext { "$_[1]$_[2]$_[3]" }
205 | anytext '*' anytext { "$_[1]$_[2]$_[3]" }
206 | anytext '>' anytext { "$_[1]$_[2]$_[3]" }
207 | anytext '|' anytext { "$_[1]$_[2]$_[3]" }
208 | anytext '&' anytext { "$_[1]$_[2]$_[3]" }
209 | anytext '/' anytext { "$_[1]$_[2]$_[3]" }
210 | anytext '+' anytext { "$_[1]$_[2]$_[3]" }
211 | anytext '(' anytext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
214 identifier: IDENTIFIER
220 text: TEXT { "\"$_[1]\"" }
224 #####################################
231 if (exists $_[0]->YYData->{ERRMSG}) {
232 print $_[0]->YYData->{ERRMSG};
233 delete $_[0]->YYData->{ERRMSG};
236 my $line = $_[0]->YYData->{LINE};
237 my $last_token = $_[0]->YYData->{LAST_TOKEN};
238 my $file = $_[0]->YYData->{INPUT_FILENAME};
240 print "$file:$line: Syntax error near '$last_token'\n";
247 $parser->YYData->{INPUT}
251 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
253 for ($parser->YYData->{INPUT}) {
255 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
256 $parser->YYData->{LINE} = $1-1;
257 $parser->YYData->{INPUT_FILENAME} = $2;
260 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
261 $parser->YYData->{LINE} = $1-1;
262 $parser->YYData->{INPUT_FILENAME} = $2;
270 $parser->YYData->{LINE}++;
273 if (s/^\"(.*?)\"//) {
274 $parser->YYData->{LAST_TOKEN} = $1;
277 if (s/^(\d+)(\W|$)/$2/) {
278 $parser->YYData->{LAST_TOKEN} = $1;
279 return('CONSTANT',$1);
282 $parser->YYData->{LAST_TOKEN} = $1;
284 /^(interface|const|typedef|union
285 |struct|enum|void|case|default)$/x) {
288 return('IDENTIFIER',$1);
291 $parser->YYData->{LAST_TOKEN} = $1;
300 my $filename = shift;
302 my $saved_delim = $/;
305 if (! defined $cpp) {
308 my $data = `$cpp -xc $filename`;
311 $self->YYData->{INPUT} = $data;
312 $self->YYData->{LINE} = 0;
313 $self->YYData->{LAST_TOKEN} = "NONE";
315 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
317 foreach my $x (@{$idl}) {
318 # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
319 # for 'object' interfaces
320 if (defined($x->{PROPERTIES}->{object})) {
321 foreach my $e (@{$x->{DATA}}) {
322 if($e->{TYPE} eq "FUNCTION") {
323 unshift(@{$e->{DATA}},
324 { 'NAME' => 'ORPCthis',
326 'PROPERTIES' => { 'in' => '1' },
329 unshift(@{$e->{DATA}},
330 { 'NAME' => 'ORPCthat',
332 'PROPERTIES' => { 'out' => '1' },
340 if (defined($x->{BASE}) and $x->{BASE} ne "") {
341 my $parent = util::get_interface($idl, $x->{BASE});
343 if(not defined($parent)) {
344 die("No such parent interface " . $x->{BASE});
347 @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}});
349 $x->{INHERITED_DATA} = $x->{DATA};