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

Last change on this file since 414 was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 11.1 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 identifier array_len ';'
173 {{
174 "TYPE" => "TYPEDEF",
175 "PROPERTIES" => $_[1],
176 "NAME" => $_[4],
177 "DATA" => $_[3],
178 "ARRAY_LEN" => $_[5],
179 "FILE" => $_[0]->YYData->{FILE},
180 "LINE" => $_[0]->YYData->{LINE},
181 }}
182;
183
184usertype:
185 struct
186 |
187 union
188 |
189 enum
190 |
191 bitmap
192 |
193 pipe
194;
195
196typedecl:
197 usertype ';' { $_[1] }
198;
199
200sign:
201 'signed'
202 |
203 'unsigned'
204;
205
206existingtype:
207 sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
208 |
209 identifier
210;
211
212type:
213 usertype
214 |
215 existingtype
216 |
217 void { "void" }
218;
219
220enum_body:
221 '{' enum_elements '}' { $_[2] }
222;
223
224opt_enum_body:
225 #empty
226 |
227 enum_body
228;
229
230enum:
231 property_list 'enum' optional_identifier opt_enum_body
232 {{
233 "TYPE" => "ENUM",
234 "PROPERTIES" => $_[1],
235 "NAME" => $_[3],
236 "ELEMENTS" => $_[4],
237 "FILE" => $_[0]->YYData->{FILE},
238 "LINE" => $_[0]->YYData->{LINE},
239 }}
240;
241
242enum_elements:
243 enum_element { [ $_[1] ] }
244 |
245 enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
246;
247
248enum_element:
249 identifier
250 |
251 identifier '=' anytext { "$_[1]$_[2]$_[3]" }
252;
253
254bitmap_body:
255 '{' opt_bitmap_elements '}' { $_[2] }
256;
257
258opt_bitmap_body:
259 #empty
260 |
261 bitmap_body
262;
263
264bitmap:
265 property_list 'bitmap' optional_identifier opt_bitmap_body
266 {{
267 "TYPE" => "BITMAP",
268 "PROPERTIES" => $_[1],
269 "NAME" => $_[3],
270 "ELEMENTS" => $_[4],
271 "FILE" => $_[0]->YYData->{FILE},
272 "LINE" => $_[0]->YYData->{LINE},
273 }}
274;
275
276bitmap_elements:
277 bitmap_element { [ $_[1] ] }
278 |
279 bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
280;
281
282opt_bitmap_elements:
283 #empty
284 |
285 bitmap_elements
286;
287
288bitmap_element:
289 identifier '=' anytext { "$_[1] ( $_[3] )" }
290;
291
292struct_body:
293 '{' element_list1 '}' { $_[2] }
294;
295
296opt_struct_body:
297 #empty
298 |
299 struct_body
300;
301
302struct:
303 property_list 'struct' optional_identifier opt_struct_body
304 {{
305 "TYPE" => "STRUCT",
306 "PROPERTIES" => $_[1],
307 "NAME" => $_[3],
308 "ELEMENTS" => $_[4],
309 "FILE" => $_[0]->YYData->{FILE},
310 "LINE" => $_[0]->YYData->{LINE},
311 }}
312;
313
314empty_element:
315 property_list ';'
316 {{
317 "NAME" => "",
318 "TYPE" => "EMPTY",
319 "PROPERTIES" => $_[1],
320 "POINTERS" => 0,
321 "ARRAY_LEN" => [],
322 "FILE" => $_[0]->YYData->{FILE},
323 "LINE" => $_[0]->YYData->{LINE},
324 }}
325;
326
327base_or_empty:
328 base_element ';'
329 |
330 empty_element;
331
332optional_base_element:
333 property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
334;
335
336union_elements:
337 #empty
338 |
339 union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
340;
341
342union_body:
343 '{' union_elements '}' { $_[2] }
344;
345
346opt_union_body:
347 #empty
348 |
349 union_body
350;
351
352union:
353 property_list 'union' optional_identifier opt_union_body
354 {{
355 "TYPE" => "UNION",
356 "PROPERTIES" => $_[1],
357 "NAME" => $_[3],
358 "ELEMENTS" => $_[4],
359 "FILE" => $_[0]->YYData->{FILE},
360 "LINE" => $_[0]->YYData->{LINE},
361 }}
362;
363
364base_element:
365 property_list type pointers identifier array_len
366 {{
367 "NAME" => $_[4],
368 "TYPE" => $_[2],
369 "PROPERTIES" => $_[1],
370 "POINTERS" => $_[3],
371 "ARRAY_LEN" => $_[5],
372 "FILE" => $_[0]->YYData->{FILE},
373 "LINE" => $_[0]->YYData->{LINE},
374 }}
375;
376
377pointers:
378 #empty
379 { 0 }
380 |
381 pointers '*' { $_[1]+1 }
382;
383
384pipe:
385 property_list 'pipe' type
386 {{
387 "TYPE" => "PIPE",
388 "PROPERTIES" => $_[1],
389 "DATA" => $_[3],
390 "FILE" => $_[0]->YYData->{FILE},
391 "LINE" => $_[0]->YYData->{LINE},
392 }}
393;
394
395element_list1:
396 #empty
397 { [] }
398 |
399 element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
400;
401
402optional_const:
403 #empty
404 |
405 'const'
406;
407
408element_list2:
409 #empty
410 |
411 'void'
412 |
413 optional_const base_element { [ $_[2] ] }
414 |
415 element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
416;
417
418array_len:
419 #empty { [] }
420 |
421 '[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
422 |
423 '[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
424;
425
426property_list:
427 #empty
428 |
429 property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
430;
431
432properties:
433 property { $_[1] }
434 |
435 properties ',' property { FlattenHash([$_[1], $_[3]]); }
436;
437
438property:
439 identifier {{ "$_[1]" => "1" }}
440 |
441 identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
442;
443
444commalisttext:
445 anytext
446 |
447 commalisttext ',' anytext { "$_[1],$_[3]" }
448;
449
450anytext:
451 #empty
452 { "" }
453 |
454 identifier
455 |
456 constant
457 |
458 text
459 |
460 anytext '-' anytext { "$_[1]$_[2]$_[3]" }
461 |
462 anytext '.' anytext { "$_[1]$_[2]$_[3]" }
463 |
464 anytext '*' anytext { "$_[1]$_[2]$_[3]" }
465 |
466 anytext '>' anytext { "$_[1]$_[2]$_[3]" }
467 |
468 anytext '<' anytext { "$_[1]$_[2]$_[3]" }
469 |
470 anytext '|' anytext { "$_[1]$_[2]$_[3]" }
471 |
472 anytext '&' anytext { "$_[1]$_[2]$_[3]" }
473 |
474 anytext '/' anytext { "$_[1]$_[2]$_[3]" }
475 |
476 anytext '?' anytext { "$_[1]$_[2]$_[3]" }
477 |
478 anytext ':' anytext { "$_[1]$_[2]$_[3]" }
479 |
480 anytext '=' anytext { "$_[1]$_[2]$_[3]" }
481 |
482 anytext '+' anytext { "$_[1]$_[2]$_[3]" }
483 |
484 anytext '~' anytext { "$_[1]$_[2]$_[3]" }
485 |
486 anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
487 |
488 anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
489;
490
491identifier:
492 IDENTIFIER
493;
494
495optional_identifier:
496 #empty { undef }
497 |
498 IDENTIFIER
499;
500
501constant:
502 CONSTANT
503;
504
505text:
506 TEXT { "\"$_[1]\"" }
507;
508
509optional_semicolon:
510 #empty
511 |
512 ';'
513;
514
515
516#####################################
517# start code
518%%
519
520use Parse::Pidl qw(error);
521
522#####################################################################
523# flatten an array of hashes into a single hash
524sub FlattenHash($)
525{
526 my $a = shift;
527 my %b;
528 for my $d (@{$a}) {
529 for my $k (keys %{$d}) {
530 $b{$k} = $d->{$k};
531 }
532 }
533 return \%b;
534}
535
536#####################################################################
537# traverse a perl data structure removing any empty arrays or
538# hashes and any hash elements that map to undef
539sub CleanData($)
540{
541 sub CleanData($);
542 my($v) = shift;
543
544 return undef if (not defined($v));
545
546 if (ref($v) eq "ARRAY") {
547 foreach my $i (0 .. $#{$v}) {
548 CleanData($v->[$i]);
549 }
550 # this removes any undefined elements from the array
551 @{$v} = grep { defined $_ } @{$v};
552 } elsif (ref($v) eq "HASH") {
553 foreach my $x (keys %{$v}) {
554 CleanData($v->{$x});
555 if (!defined $v->{$x}) {
556 delete($v->{$x});
557 next;
558 }
559 }
560 }
561
562 return $v;
563}
564
565sub _Error {
566 if (exists $_[0]->YYData->{ERRMSG}) {
567 error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
568 delete $_[0]->YYData->{ERRMSG};
569 return;
570 }
571
572 my $last_token = $_[0]->YYData->{LAST_TOKEN};
573
574 error($_[0]->YYData, "Syntax error near '$last_token'");
575}
576
577sub _Lexer($)
578{
579 my($parser)=shift;
580
581 $parser->YYData->{INPUT} or return('',undef);
582
583again:
584 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
585
586 for ($parser->YYData->{INPUT}) {
587 if (/^\#/) {
588 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
589 $parser->YYData->{LINE} = $1-1;
590 $parser->YYData->{FILE} = $2;
591 goto again;
592 }
593 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
594 $parser->YYData->{LINE} = $1-1;
595 $parser->YYData->{FILE} = $2;
596 goto again;
597 }
598 if (s/^(\#.*)$//m) {
599 goto again;
600 }
601 }
602 if (s/^(\n)//) {
603 $parser->YYData->{LINE}++;
604 goto again;
605 }
606 if (s/^\"(.*?)\"//) {
607 $parser->YYData->{LAST_TOKEN} = $1;
608 return('TEXT',$1);
609 }
610 if (s/^(\d+)(\W|$)/$2/) {
611 $parser->YYData->{LAST_TOKEN} = $1;
612 return('CONSTANT',$1);
613 }
614 if (s/^([\w_]+)//) {
615 $parser->YYData->{LAST_TOKEN} = $1;
616 if ($1 =~
617 /^(coclass|interface|import|importlib
618 |include|cpp_quote|typedef
619 |union|struct|enum|bitmap|pipe
620 |void|const|unsigned|signed)$/x) {
621 return $1;
622 }
623 return('IDENTIFIER',$1);
624 }
625 if (s/^(.)//s) {
626 $parser->YYData->{LAST_TOKEN} = $1;
627 return($1,$1);
628 }
629 }
630}
631
632sub parse_string
633{
634 my ($data,$filename) = @_;
635
636 my $self = new Parse::Pidl::IDL;
637
638 $self->YYData->{FILE} = $filename;
639 $self->YYData->{INPUT} = $data;
640 $self->YYData->{LINE} = 0;
641 $self->YYData->{LAST_TOKEN} = "NONE";
642
643 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
644
645 return CleanData($idl);
646}
647
648sub parse_file($$)
649{
650 my ($filename,$incdirs) = @_;
651
652 my $saved_delim = $/;
653 undef $/;
654 my $cpp = $ENV{CPP};
655 if (! defined $cpp) {
656 $cpp = "cpp";
657 }
658 my $includes = join('',map { " -I$_" } @$incdirs);
659 my $data = `$cpp -D__PIDL__$includes -xc $filename`;
660 $/ = $saved_delim;
661
662 return parse_string($data, $filename);
663}
Note: See TracBrowser for help on using the repository browser.