source: vendor/current/pidl/idl.yp@ 989

Last change on this file since 989 was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 11.9 KB
Line 
1########################
2# IDL Parse::Yapp parser
3# Copyright (C) Andrew Tridgell <tridge@samba.org>
4# released under the GNU GPL version 3 or later
5
6
7
8# the precedence actually doesn't matter at all for this grammar, but
9# by providing a precedence we reduce the number of conflicts
10# enormously
11%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
12
13
14################
15# grammar
16%%
17idl:
18 #empty { {} }
19 |
20 idl interface { push(@{$_[1]}, $_[2]); $_[1] }
21 |
22 idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
23 |
24 idl import { push(@{$_[1]}, $_[2]); $_[1] }
25 |
26 idl include { push(@{$_[1]}, $_[2]); $_[1] }
27 |
28 idl importlib { push(@{$_[1]}, $_[2]); $_[1] }
29 |
30 idl cpp_quote { push(@{$_[1]}, $_[2]); $_[1] }
31;
32
33import:
34 'import' commalist ';'
35 {{
36 "TYPE" => "IMPORT",
37 "PATHS" => $_[2],
38 "FILE" => $_[0]->YYData->{FILE},
39 "LINE" => $_[0]->YYData->{LINE},
40 }}
41;
42
43include:
44 'include' commalist ';'
45 {{
46 "TYPE" => "INCLUDE",
47 "PATHS" => $_[2],
48 "FILE" => $_[0]->YYData->{FILE},
49 "LINE" => $_[0]->YYData->{LINE},
50 }}
51;
52
53importlib:
54 'importlib' commalist ';'
55 {{
56 "TYPE" => "IMPORTLIB",
57 "PATHS" => $_[2],
58 "FILE" => $_[0]->YYData->{FILE},
59 "LINE" => $_[0]->YYData->{LINE},
60 }}
61;
62
63commalist:
64 text { [ $_[1] ] }
65 |
66 commalist ',' text { push(@{$_[1]}, $_[3]); $_[1] }
67;
68
69coclass:
70 property_list 'coclass' identifier '{' interface_names '}' optional_semicolon
71 {{
72 "TYPE" => "COCLASS",
73 "PROPERTIES" => $_[1],
74 "NAME" => $_[3],
75 "DATA" => $_[5],
76 "FILE" => $_[0]->YYData->{FILE},
77 "LINE" => $_[0]->YYData->{LINE},
78 }}
79;
80
81interface_names:
82 #empty { {} }
83 |
84 interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
85;
86
87interface:
88 property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
89 {{
90 "TYPE" => "INTERFACE",
91 "PROPERTIES" => $_[1],
92 "NAME" => $_[3],
93 "BASE" => $_[4],
94 "DATA" => $_[6],
95 "FILE" => $_[0]->YYData->{FILE},
96 "LINE" => $_[0]->YYData->{LINE},
97 }}
98;
99
100base_interface:
101 #empty
102 |
103 ':' identifier { $_[2] }
104;
105
106
107cpp_quote:
108 'cpp_quote' '(' text ')'
109 {{
110 "TYPE" => "CPP_QUOTE",
111 "DATA" => $_[3],
112 "FILE" => $_[0]->YYData->{FILE},
113 "LINE" => $_[0]->YYData->{LINE},
114 }}
115;
116
117definitions:
118 definition { [ $_[1] ] }
119 |
120 definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
121;
122
123definition:
124 function
125 |
126 const
127 |
128 typedef
129 |
130 typedecl
131;
132
133const:
134 'const' identifier pointers identifier '=' anytext ';'
135 {{
136 "TYPE" => "CONST",
137 "DTYPE" => $_[2],
138 "POINTERS" => $_[3],
139 "NAME" => $_[4],
140 "VALUE" => $_[6],
141 "FILE" => $_[0]->YYData->{FILE},
142 "LINE" => $_[0]->YYData->{LINE},
143 }}
144 |
145 'const' identifier pointers identifier array_len '=' anytext ';'
146 {{
147 "TYPE" => "CONST",
148 "DTYPE" => $_[2],
149 "POINTERS" => $_[3],
150 "NAME" => $_[4],
151 "ARRAY_LEN" => $_[5],
152 "VALUE" => $_[7],
153 "FILE" => $_[0]->YYData->{FILE},
154 "LINE" => $_[0]->YYData->{LINE},
155 }}
156;
157
158function:
159 property_list type identifier '(' element_list2 ')' ';'
160 {{
161 "TYPE" => "FUNCTION",
162 "NAME" => $_[3],
163 "RETURN_TYPE" => $_[2],
164 "PROPERTIES" => $_[1],
165 "ELEMENTS" => $_[5],
166 "FILE" => $_[0]->YYData->{FILE},
167 "LINE" => $_[0]->YYData->{LINE},
168 }}
169;
170
171typedef:
172 property_list 'typedef' type pointers identifier array_len ';'
173 {{
174 "TYPE" => "TYPEDEF",
175 "PROPERTIES" => $_[1],
176 "NAME" => $_[5],
177 "DATA" => $_[3],
178 "POINTERS" => $_[4],
179 "ARRAY_LEN" => $_[6],
180 "FILE" => $_[0]->YYData->{FILE},
181 "LINE" => $_[0]->YYData->{LINE},
182 }}
183;
184
185usertype:
186 struct
187 |
188 union
189 |
190 enum
191 |
192 bitmap
193 |
194 pipe
195;
196
197typedecl:
198 usertype ';' { $_[1] }
199;
200
201sign:
202 'signed'
203 |
204 'unsigned'
205;
206
207existingtype:
208 sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
209 |
210 identifier
211;
212
213type:
214 usertype
215 |
216 existingtype
217 |
218 void { "void" }
219;
220
221enum_body:
222 '{' enum_elements '}' { $_[2] }
223;
224
225opt_enum_body:
226 #empty
227 |
228 enum_body
229;
230
231enum:
232 property_list 'enum' optional_identifier opt_enum_body
233 {{
234 "TYPE" => "ENUM",
235 "PROPERTIES" => $_[1],
236 "NAME" => $_[3],
237 "ELEMENTS" => $_[4],
238 "FILE" => $_[0]->YYData->{FILE},
239 "LINE" => $_[0]->YYData->{LINE},
240 }}
241;
242
243enum_elements:
244 enum_element { [ $_[1] ] }
245 |
246 enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
247;
248
249enum_element:
250 identifier
251 |
252 identifier '=' anytext { "$_[1]$_[2]$_[3]" }
253;
254
255bitmap_body:
256 '{' opt_bitmap_elements '}' { $_[2] }
257;
258
259opt_bitmap_body:
260 #empty
261 |
262 bitmap_body
263;
264
265bitmap:
266 property_list 'bitmap' optional_identifier opt_bitmap_body
267 {{
268 "TYPE" => "BITMAP",
269 "PROPERTIES" => $_[1],
270 "NAME" => $_[3],
271 "ELEMENTS" => $_[4],
272 "FILE" => $_[0]->YYData->{FILE},
273 "LINE" => $_[0]->YYData->{LINE},
274 }}
275;
276
277bitmap_elements:
278 bitmap_element { [ $_[1] ] }
279 |
280 bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
281;
282
283opt_bitmap_elements:
284 #empty
285 |
286 bitmap_elements
287;
288
289bitmap_element:
290 identifier '=' anytext { "$_[1] ( $_[3] )" }
291;
292
293struct_body:
294 '{' element_list1 '}' { $_[2] }
295;
296
297opt_struct_body:
298 #empty
299 |
300 struct_body
301;
302
303struct:
304 property_list 'struct' optional_identifier opt_struct_body
305 {{
306 "TYPE" => "STRUCT",
307 "PROPERTIES" => $_[1],
308 "NAME" => $_[3],
309 "ELEMENTS" => $_[4],
310 "FILE" => $_[0]->YYData->{FILE},
311 "LINE" => $_[0]->YYData->{LINE},
312 }}
313;
314
315empty_element:
316 property_list ';'
317 {{
318 "NAME" => "",
319 "TYPE" => "EMPTY",
320 "PROPERTIES" => $_[1],
321 "POINTERS" => 0,
322 "ARRAY_LEN" => [],
323 "FILE" => $_[0]->YYData->{FILE},
324 "LINE" => $_[0]->YYData->{LINE},
325 }}
326;
327
328base_or_empty:
329 base_element ';'
330 |
331 empty_element;
332
333optional_base_element:
334 property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
335;
336
337union_elements:
338 #empty
339 |
340 union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
341;
342
343union_body:
344 '{' union_elements '}' { $_[2] }
345;
346
347opt_union_body:
348 #empty
349 |
350 union_body
351;
352
353union:
354 property_list 'union' optional_identifier opt_union_body
355 {{
356 "TYPE" => "UNION",
357 "PROPERTIES" => $_[1],
358 "NAME" => $_[3],
359 "ELEMENTS" => $_[4],
360 "FILE" => $_[0]->YYData->{FILE},
361 "LINE" => $_[0]->YYData->{LINE},
362 }}
363;
364
365base_element:
366 property_list type pointers identifier array_len
367 {{
368 "NAME" => $_[4],
369 "TYPE" => $_[2],
370 "PROPERTIES" => $_[1],
371 "POINTERS" => $_[3],
372 "ARRAY_LEN" => $_[5],
373 "FILE" => $_[0]->YYData->{FILE},
374 "LINE" => $_[0]->YYData->{LINE},
375 }}
376;
377
378pointers:
379 #empty
380 { 0 }
381 |
382 pointers '*' { $_[1]+1 }
383;
384
385pipe:
386 property_list 'pipe' type
387 {{
388 "TYPE" => "PIPE",
389 "PROPERTIES" => $_[1],
390 "NAME" => undef,
391 "DATA" => {
392 "TYPE" => "STRUCT",
393 "PROPERTIES" => $_[1],
394 "NAME" => undef,
395 "ELEMENTS" => [{
396 "NAME" => "count",
397 "PROPERTIES" => $_[1],
398 "POINTERS" => 0,
399 "ARRAY_LEN" => [],
400 "TYPE" => "uint3264",
401 "FILE" => $_[0]->YYData->{FILE},
402 "LINE" => $_[0]->YYData->{LINE},
403 },{
404 "NAME" => "array",
405 "PROPERTIES" => $_[1],
406 "POINTERS" => 0,
407 "ARRAY_LEN" => [ "count" ],
408 "TYPE" => $_[3],
409 "FILE" => $_[0]->YYData->{FILE},
410 "LINE" => $_[0]->YYData->{LINE},
411 }],
412 "FILE" => $_[0]->YYData->{FILE},
413 "LINE" => $_[0]->YYData->{LINE},
414 },
415 "FILE" => $_[0]->YYData->{FILE},
416 "LINE" => $_[0]->YYData->{LINE},
417 }}
418;
419
420element_list1:
421 #empty
422 { [] }
423 |
424 element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
425;
426
427optional_const:
428 #empty
429 |
430 'const'
431;
432
433element_list2:
434 #empty
435 |
436 'void'
437 |
438 optional_const base_element { [ $_[2] ] }
439 |
440 element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
441;
442
443array_len:
444 #empty { [] }
445 |
446 '[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
447 |
448 '[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
449;
450
451property_list:
452 #empty
453 |
454 property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
455;
456
457properties:
458 property { $_[1] }
459 |
460 properties ',' property { FlattenHash([$_[1], $_[3]]); }
461;
462
463property:
464 identifier {{ "$_[1]" => "1" }}
465 |
466 identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
467;
468
469commalisttext:
470 anytext
471 |
472 commalisttext ',' anytext { "$_[1],$_[3]" }
473;
474
475anytext:
476 #empty
477 { "" }
478 |
479 identifier
480 |
481 constant
482 |
483 text
484 |
485 anytext '-' anytext { "$_[1]$_[2]$_[3]" }
486 |
487 anytext '.' anytext { "$_[1]$_[2]$_[3]" }
488 |
489 anytext '*' anytext { "$_[1]$_[2]$_[3]" }
490 |
491 anytext '>' anytext { "$_[1]$_[2]$_[3]" }
492 |
493 anytext '<' anytext { "$_[1]$_[2]$_[3]" }
494 |
495 anytext '|' anytext { "$_[1]$_[2]$_[3]" }
496 |
497 anytext '&' anytext { "$_[1]$_[2]$_[3]" }
498 |
499 anytext '/' anytext { "$_[1]$_[2]$_[3]" }
500 |
501 anytext '?' anytext { "$_[1]$_[2]$_[3]" }
502 |
503 anytext ':' anytext { "$_[1]$_[2]$_[3]" }
504 |
505 anytext '=' anytext { "$_[1]$_[2]$_[3]" }
506 |
507 anytext '+' anytext { "$_[1]$_[2]$_[3]" }
508 |
509 anytext '~' anytext { "$_[1]$_[2]$_[3]" }
510 |
511 anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
512 |
513 anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
514;
515
516identifier:
517 IDENTIFIER
518;
519
520optional_identifier:
521 #empty { undef }
522 |
523 IDENTIFIER
524;
525
526constant:
527 CONSTANT
528;
529
530text:
531 TEXT { "\"$_[1]\"" }
532;
533
534optional_semicolon:
535 #empty
536 |
537 ';'
538;
539
540
541#####################################
542# start code
543%%
544
545use Parse::Pidl qw(error);
546
547#####################################################################
548# flatten an array of hashes into a single hash
549sub FlattenHash($)
550{
551 my $a = shift;
552 my %b;
553 for my $d (@{$a}) {
554 for my $k (keys %{$d}) {
555 $b{$k} = $d->{$k};
556 }
557 }
558 return \%b;
559}
560
561#####################################################################
562# traverse a perl data structure removing any empty arrays or
563# hashes and any hash elements that map to undef
564sub CleanData($)
565{
566 sub CleanData($);
567 my($v) = shift;
568
569 return undef if (not defined($v));
570
571 if (ref($v) eq "ARRAY") {
572 foreach my $i (0 .. $#{$v}) {
573 CleanData($v->[$i]);
574 }
575 # this removes any undefined elements from the array
576 @{$v} = grep { defined $_ } @{$v};
577 } elsif (ref($v) eq "HASH") {
578 foreach my $x (keys %{$v}) {
579 CleanData($v->{$x});
580 if (!defined $v->{$x}) {
581 delete($v->{$x});
582 next;
583 }
584 }
585 }
586
587 return $v;
588}
589
590sub _Error {
591 if (exists $_[0]->YYData->{ERRMSG}) {
592 error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
593 delete $_[0]->YYData->{ERRMSG};
594 return;
595 }
596
597 my $last_token = $_[0]->YYData->{LAST_TOKEN};
598
599 error($_[0]->YYData, "Syntax error near '$last_token'");
600}
601
602sub _Lexer($)
603{
604 my($parser)=shift;
605
606 $parser->YYData->{INPUT} or return('',undef);
607
608again:
609 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
610
611 for ($parser->YYData->{INPUT}) {
612 if (/^\#/) {
613 # Linemarker format is described at
614 # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
615 if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
616 $parser->YYData->{LINE} = $1-1;
617 $parser->YYData->{FILE} = $2;
618 goto again;
619 }
620 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
621 $parser->YYData->{LINE} = $1-1;
622 $parser->YYData->{FILE} = $2;
623 goto again;
624 }
625 if (s/^(\#.*)$//m) {
626 goto again;
627 }
628 }
629 if (s/^(\n)//) {
630 $parser->YYData->{LINE}++;
631 goto again;
632 }
633 if (s/^\"(.*?)\"//) {
634 $parser->YYData->{LAST_TOKEN} = $1;
635 return('TEXT',$1);
636 }
637 if (s/^(\d+)(\W|$)/$2/) {
638 $parser->YYData->{LAST_TOKEN} = $1;
639 return('CONSTANT',$1);
640 }
641 if (s/^([\w_]+)//) {
642 $parser->YYData->{LAST_TOKEN} = $1;
643 if ($1 =~
644 /^(coclass|interface|import|importlib
645 |include|cpp_quote|typedef
646 |union|struct|enum|bitmap|pipe
647 |void|const|unsigned|signed)$/x) {
648 return $1;
649 }
650 return('IDENTIFIER',$1);
651 }
652 if (s/^(.)//s) {
653 $parser->YYData->{LAST_TOKEN} = $1;
654 return($1,$1);
655 }
656 }
657}
658
659sub parse_string
660{
661 my ($data,$filename) = @_;
662
663 my $self = new Parse::Pidl::IDL;
664
665 $self->YYData->{FILE} = $filename;
666 $self->YYData->{INPUT} = $data;
667 $self->YYData->{LINE} = 0;
668 $self->YYData->{LAST_TOKEN} = "NONE";
669
670 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
671
672 return CleanData($idl);
673}
674
675sub parse_file($$)
676{
677 my ($filename,$incdirs) = @_;
678
679 my $saved_delim = $/;
680 undef $/;
681 my $cpp = $ENV{CPP};
682 my $options = "";
683 if (! defined $cpp) {
684 if (defined $ENV{CC}) {
685 $cpp = "$ENV{CC}";
686 $options = "-E";
687 } else {
688 $cpp = "cpp";
689 }
690 }
691 my $includes = join('',map { " -I$_" } @$incdirs);
692 my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
693 $/ = $saved_delim;
694
695 return parse_string($data, $filename);
696}
Note: See TracBrowser for help on using the repository browser.