OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """ Parser for PPAPI IDL """ | 6 """ Parser for PPAPI IDL """ |
7 | 7 |
8 # | 8 # |
9 # IDL Parser | 9 # IDL Parser |
10 # | 10 # |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 """top : COMMENT COMMENT ext_attr_block top_list""" | 216 """top : COMMENT COMMENT ext_attr_block top_list""" |
217 | 217 |
218 Copyright = self.BuildComment('Copyright', p, 1) | 218 Copyright = self.BuildComment('Copyright', p, 1) |
219 Filedoc = self.BuildComment('Comment', p, 2) | 219 Filedoc = self.BuildComment('Comment', p, 2) |
220 | 220 |
221 p[0] = ListFromConcat(Copyright, Filedoc, p[3], p[4]) | 221 p[0] = ListFromConcat(Copyright, Filedoc, p[3], p[4]) |
222 if self.parse_debug: DumpReduction('top', p) | 222 if self.parse_debug: DumpReduction('top', p) |
223 | 223 |
224 # Build a list of top level items. | 224 # Build a list of top level items. |
225 def p_top_list(self, p): | 225 def p_top_list(self, p): |
226 """top_list : describe_block top_list | 226 """top_list : callback_decl top_list |
| 227 | describe_block top_list |
| 228 | dictionary_block top_list |
227 | enum_block top_list | 229 | enum_block top_list |
228 | inline top_list | 230 | inline top_list |
229 | interface_block top_list | 231 | interface_block top_list |
230 | label_block top_list | 232 | label_block top_list |
| 233 | namespace top_list |
231 | struct_block top_list | 234 | struct_block top_list |
232 | typedef_decl top_list | 235 | typedef_decl top_list |
233 | """ | 236 | """ |
234 if len(p) > 2: | 237 if len(p) > 2: |
235 p[0] = ListFromConcat(p[1], p[2]) | 238 p[0] = ListFromConcat(p[1], p[2]) |
236 if self.parse_debug: DumpReduction('top_list', p) | 239 if self.parse_debug: DumpReduction('top_list', p) |
237 | 240 |
238 # Recover from error and continue parsing at the next top match. | 241 # Recover from error and continue parsing at the next top match. |
239 def p_top_error(self, p): | 242 def p_top_error(self, p): |
240 """top_list : error top_list""" | 243 """top_list : error top_list""" |
(...skipping 19 matching lines...) Expand all Loading... |
260 | """ | 263 | """ |
261 if len(p) > 1: | 264 if len(p) > 1: |
262 child = self.BuildComment('Comment', p, 1) | 265 child = self.BuildComment('Comment', p, 1) |
263 p[0] = ListFromConcat(child, p[2]) | 266 p[0] = ListFromConcat(child, p[2]) |
264 if self.parse_debug: DumpReduction('comments', p) | 267 if self.parse_debug: DumpReduction('comments', p) |
265 else: | 268 else: |
266 if self.parse_debug: DumpReduction('no comments', p) | 269 if self.parse_debug: DumpReduction('no comments', p) |
267 | 270 |
268 | 271 |
269 # | 272 # |
| 273 # Namespace |
| 274 # |
| 275 # A namespace provides a named scope to an enclosed top_list. |
| 276 # |
| 277 def p_namespace(self, p): |
| 278 """namespace : modifiers NAMESPACE namespace_name '{' top_list '}' ';'""" |
| 279 children = ListFromConcat(p[1], p[5]) |
| 280 p[0] = self.BuildNamed('Namespace', p, 3, children) |
| 281 |
| 282 # We allow namespace names of the form foo.bar.baz. |
| 283 def p_namespace_name(self, p): |
| 284 """namespace_name : SYMBOL |
| 285 | SYMBOL '.' namespace_name""" |
| 286 p[0] = "".join(p[1:]) |
| 287 |
| 288 |
| 289 # |
| 290 # Dictionary |
| 291 # |
| 292 # A dictionary contains is a named list of optional and required members. |
| 293 # |
| 294 def p_dictionary_block(self, p): |
| 295 """dictionary_block : modifiers DICTIONARY SYMBOL '{' struct_list '}' ';'""" |
| 296 p[0] = self.BuildNamed('Dictionary', p, 3, ListFromConcat(p[5])) |
| 297 |
| 298 # |
| 299 # Callback |
| 300 # |
| 301 # A callback is essentially a single function declaration (outside of an |
| 302 # Interface). |
| 303 # |
| 304 def p_callback_decl(self, p): |
| 305 """callback_decl : modifiers CALLBACK SYMBOL '=' SYMBOL param_list ';'""" |
| 306 children = ListFromConcat(p[1], p[6]) |
| 307 p[0] = self.BuildNamed('Callback', p, 3, children) |
| 308 |
| 309 |
| 310 # |
270 # Inline | 311 # Inline |
271 # | 312 # |
272 # Inline blocks define option code to be emitted based on language tag, | 313 # Inline blocks define option code to be emitted based on language tag, |
273 # in the form of: | 314 # in the form of: |
274 # #inline <LANGUAGE> | 315 # #inline <LANGUAGE> |
275 # <CODE> | 316 # <CODE> |
276 # #endinl | 317 # #endinl |
277 # | 318 # |
278 def p_inline(self, p): | 319 def p_inline(self, p): |
279 """inline : modifiers INLINE""" | 320 """inline : modifiers INLINE""" |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 p[0] = ListFromConcat(array, p[3]) | 516 p[0] = ListFromConcat(array, p[3]) |
476 # If there are 4 tokens plus a return slot it is a fixed array | 517 # If there are 4 tokens plus a return slot it is a fixed array |
477 elif len(p) == 5: | 518 elif len(p) == 5: |
478 count = self.BuildAttribute('FIXED', p[2]) | 519 count = self.BuildAttribute('FIXED', p[2]) |
479 array = self.BuildProduction('Array', p, 2, [count]) | 520 array = self.BuildProduction('Array', p, 2, [count]) |
480 p[0] = ListFromConcat(array, p[4]) | 521 p[0] = ListFromConcat(array, p[4]) |
481 # If there is only a return slot, do not fill it for this terminator. | 522 # If there is only a return slot, do not fill it for this terminator. |
482 elif len(p) == 1: return | 523 elif len(p) == 1: return |
483 if self.parse_debug: DumpReduction('arrays', p) | 524 if self.parse_debug: DumpReduction('arrays', p) |
484 | 525 |
| 526 |
| 527 # An identifier is a legal value for a parameter or attribute name. Lots of |
| 528 # existing IDL files use "callback" as a parameter/attribute name, so we allow |
| 529 # a SYMBOL or the CALLBACK keyword. |
| 530 def p_identifier(self, p): |
| 531 """identifier : SYMBOL |
| 532 | CALLBACK""" |
| 533 p[0] = p[1] |
| 534 # Save the line number of the underlying token (otherwise it gets |
| 535 # discarded), since we use it in the productions with an identifier in |
| 536 # them. |
| 537 p.set_lineno(0, p.lineno(1)) |
| 538 |
485 # | 539 # |
486 # Parameter List | 540 # Parameter List |
487 # | 541 # |
488 # A parameter list is a collection of arguments which are passed to a | 542 # A parameter list is a collection of arguments which are passed to a |
489 # function. | 543 # function. |
490 # | 544 # |
491 def p_param_list(self, p): | 545 def p_param_list(self, p): |
492 """param_list : '(' param_item param_cont ')' | 546 """param_list : '(' param_item param_cont ')' |
493 | '(' ')' """ | 547 | '(' ')' """ |
494 if len(p) > 3: | 548 if len(p) > 3: |
495 args = ListFromConcat(p[2], p[3]) | 549 args = ListFromConcat(p[2], p[3]) |
496 else: | 550 else: |
497 args = [] | 551 args = [] |
498 p[0] = self.BuildProduction('Callspec', p, 1, args) | 552 p[0] = self.BuildProduction('Callspec', p, 1, args) |
499 if self.parse_debug: DumpReduction('param_list', p) | 553 if self.parse_debug: DumpReduction('param_list', p) |
500 | 554 |
501 def p_param_item(self, p): | 555 def p_param_item(self, p): |
502 """param_item : modifiers SYMBOL arrays SYMBOL""" | 556 """param_item : modifiers optional SYMBOL arrays identifier""" |
503 typeref = self.BuildAttribute('TYPEREF', p[2]) | 557 typeref = self.BuildAttribute('TYPEREF', p[3]) |
504 children = ListFromConcat(p[1],typeref, p[3]) | 558 children = ListFromConcat(p[1],p[2], typeref, p[4]) |
505 p[0] = self.BuildNamed('Param', p, 4, children) | 559 p[0] = self.BuildNamed('Param', p, 5, children) |
506 if self.parse_debug: DumpReduction('param_item', p) | 560 if self.parse_debug: DumpReduction('param_item', p) |
507 | 561 |
| 562 def p_optional(self, p): |
| 563 """optional : OPTIONAL |
| 564 | """ |
| 565 if len(p) == 2: |
| 566 p[0] = self.BuildAttribute('OPTIONAL', True) |
| 567 |
| 568 |
508 def p_param_cont(self, p): | 569 def p_param_cont(self, p): |
509 """param_cont : ',' param_item param_cont | 570 """param_cont : ',' param_item param_cont |
510 | """ | 571 | """ |
511 if len(p) > 1: | 572 if len(p) > 1: |
512 p[0] = ListFromConcat(p[2], p[3]) | 573 p[0] = ListFromConcat(p[2], p[3]) |
513 if self.parse_debug: DumpReduction('param_cont', p) | 574 if self.parse_debug: DumpReduction('param_cont', p) |
514 | 575 |
515 def p_param_error(self, p): | 576 def p_param_error(self, p): |
516 """param_cont : error param_cont""" | 577 """param_cont : error param_cont""" |
517 p[0] = p[2] | 578 p[0] = p[2] |
518 | 579 |
519 | 580 |
520 # | 581 # |
521 # Typedef | 582 # Typedef |
522 # | 583 # |
523 # A typedef creates a new referencable type. The tyepdef can specify an array | 584 # A typedef creates a new referencable type. The typedef can specify an array |
524 # definition as well as a function declaration. | 585 # definition as well as a function declaration. |
525 # | 586 # |
526 def p_typedef_data(self, p): | 587 def p_typedef_data(self, p): |
527 """typedef_decl : modifiers TYPEDEF SYMBOL SYMBOL ';' """ | 588 """typedef_decl : modifiers TYPEDEF SYMBOL SYMBOL ';' """ |
528 typeref = self.BuildAttribute('TYPEREF', p[3]) | 589 typeref = self.BuildAttribute('TYPEREF', p[3]) |
529 children = ListFromConcat(p[1], typeref) | 590 children = ListFromConcat(p[1], typeref) |
530 p[0] = self.BuildNamed('Typedef', p, 4, children) | 591 p[0] = self.BuildNamed('Typedef', p, 4, children) |
531 if self.parse_debug: DumpReduction('typedef_data', p) | 592 if self.parse_debug: DumpReduction('typedef_data', p) |
532 | 593 |
533 def p_typedef_array(self, p): | 594 def p_typedef_array(self, p): |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 p[0] = p[2] | 669 p[0] = p[2] |
609 if self.parse_debug: DumpReduction('label_error', p) | 670 if self.parse_debug: DumpReduction('label_error', p) |
610 | 671 |
611 | 672 |
612 # | 673 # |
613 # Members | 674 # Members |
614 # | 675 # |
615 # A member attribute or function of a struct or interface. | 676 # A member attribute or function of a struct or interface. |
616 # | 677 # |
617 def p_member_attribute(self, p): | 678 def p_member_attribute(self, p): |
618 """member_attribute : modifiers SYMBOL SYMBOL """ | 679 """member_attribute : modifiers SYMBOL arrays questionmark identifier""" |
619 typeref = self.BuildAttribute('TYPEREF', p[2]) | 680 typeref = self.BuildAttribute('TYPEREF', p[2]) |
620 children = ListFromConcat(p[1], typeref) | 681 children = ListFromConcat(p[1], typeref, p[3], p[4]) |
621 p[0] = self.BuildNamed('Member', p, 3, children) | 682 p[0] = self.BuildNamed('Member', p, 5, children) |
622 if self.parse_debug: DumpReduction('attribute', p) | |
623 | |
624 def p_member_attribute_array(self, p): | |
625 """member_attribute : modifiers SYMBOL arrays SYMBOL """ | |
626 typeref = self.BuildAttribute('TYPEREF', p[2]) | |
627 children = ListFromConcat(p[1], typeref, p[3]) | |
628 p[0] = self.BuildNamed('Member', p, 4, children) | |
629 if self.parse_debug: DumpReduction('attribute', p) | 683 if self.parse_debug: DumpReduction('attribute', p) |
630 | 684 |
631 def p_member_function(self, p): | 685 def p_member_function(self, p): |
632 """member_function : modifiers SYMBOL SYMBOL param_list""" | 686 """member_function : modifiers static SYMBOL SYMBOL param_list""" |
633 typeref = self.BuildAttribute('TYPEREF', p[2]) | 687 typeref = self.BuildAttribute('TYPEREF', p[3]) |
634 children = ListFromConcat(p[1], typeref, p[4]) | 688 children = ListFromConcat(p[1], p[2], typeref, p[5]) |
635 p[0] = self.BuildNamed('Member', p, 3, children) | 689 p[0] = self.BuildNamed('Member', p, 4, children) |
636 if self.parse_debug: DumpReduction('function', p) | 690 if self.parse_debug: DumpReduction('function', p) |
637 | 691 |
| 692 def p_static(self, p): |
| 693 """static : STATIC |
| 694 | """ |
| 695 if len(p) == 2: |
| 696 p[0] = self.BuildAttribute('STATIC', True) |
| 697 |
| 698 def p_questionmark(self, p): |
| 699 """questionmark : '?' |
| 700 | """ |
| 701 if len(p) == 2: |
| 702 p[0] = self.BuildAttribute('OPTIONAL', True) |
| 703 |
638 # | 704 # |
639 # Interface | 705 # Interface |
640 # | 706 # |
641 # An interface is a named collection of functions. | 707 # An interface is a named collection of functions. |
642 # | 708 # |
643 def p_interface_block(self, p): | 709 def p_interface_block(self, p): |
644 """interface_block : modifiers INTERFACE SYMBOL '{' interface_list '}' ';'""
" | 710 """interface_block : modifiers INTERFACE SYMBOL '{' interface_list '}' ';'""
" |
645 p[0] = self.BuildNamed('Interface', p, 3, ListFromConcat(p[1], p[5])) | 711 p[0] = self.BuildNamed('Interface', p, 3, ListFromConcat(p[1], p[5])) |
646 if self.parse_debug: DumpReduction('interface_block', p) | 712 if self.parse_debug: DumpReduction('interface_block', p) |
647 | 713 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 | 829 |
764 def BuildNamed(self, cls, p, index, childlist=None): | 830 def BuildNamed(self, cls, p, index, childlist=None): |
765 if not childlist: childlist = [] | 831 if not childlist: childlist = [] |
766 childlist.append(self.BuildAttribute('NAME', p[index])) | 832 childlist.append(self.BuildAttribute('NAME', p[index])) |
767 return self.BuildProduction(cls, p, index, childlist) | 833 return self.BuildProduction(cls, p, index, childlist) |
768 | 834 |
769 def BuildComment(self, cls, p, index): | 835 def BuildComment(self, cls, p, index): |
770 name = p[index] | 836 name = p[index] |
771 | 837 |
772 # Remove comment markers | 838 # Remove comment markers |
| 839 lines = [] |
773 if name[:2] == '//': | 840 if name[:2] == '//': |
774 # For C++ style, remove the preceding '//' | 841 # For C++ style, remove any leading whitespace and the '//' marker from |
| 842 # each line. |
775 form = 'cc' | 843 form = 'cc' |
776 name = name[2:].rstrip() | 844 for line in name.split('\n'): |
| 845 start = line.find('//') |
| 846 lines.append(line[start+2:]) |
777 else: | 847 else: |
778 # For C style, remove ending '*/'' | 848 # For C style, remove ending '*/'' |
779 form = 'c' | 849 form = 'c' |
780 lines = [] | |
781 for line in name[:-2].split('\n'): | 850 for line in name[:-2].split('\n'): |
782 # Remove characters until start marker for this line '*' if found | 851 # Remove characters until start marker for this line '*' if found |
783 # otherwise it should be blank. | 852 # otherwise it should be blank. |
784 offs = line.find('*') | 853 offs = line.find('*') |
785 if offs >= 0: | 854 if offs >= 0: |
786 line = line[offs + 1:].rstrip() | 855 line = line[offs + 1:].rstrip() |
787 else: | 856 else: |
788 line = '' | 857 line = '' |
789 lines.append(line) | 858 lines.append(line) |
790 name = '\n'.join(lines) | 859 name = '\n'.join(lines) |
791 | 860 |
792 childlist = [self.BuildAttribute('NAME', name), | 861 childlist = [self.BuildAttribute('NAME', name), |
793 self.BuildAttribute('FORM', form)] | 862 self.BuildAttribute('FORM', form)] |
794 return self.BuildProduction(cls, p, index, childlist) | 863 return self.BuildProduction(cls, p, index, childlist) |
795 | 864 |
796 # | 865 # |
797 # BuildAttribute | 866 # BuildAttribute |
798 # | 867 # |
799 # An ExtendedAttribute is a special production that results in a property | 868 # An ExtendedAttribute is a special production that results in a property |
800 # which is applied to the adjacent item. Attributes have no children and | 869 # which is applied to the adjacent item. Attributes have no children and |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 ast = ParseFiles(filenames) | 1117 ast = ParseFiles(filenames) |
1049 errs = ast.GetProperty('ERRORS') | 1118 errs = ast.GetProperty('ERRORS') |
1050 if errs: | 1119 if errs: |
1051 ErrOut.Log('Found %d error(s).' % errs); | 1120 ErrOut.Log('Found %d error(s).' % errs); |
1052 InfoOut.Log("%d files processed." % len(filenames)) | 1121 InfoOut.Log("%d files processed." % len(filenames)) |
1053 return errs | 1122 return errs |
1054 | 1123 |
1055 | 1124 |
1056 if __name__ == '__main__': | 1125 if __name__ == '__main__': |
1057 sys.exit(Main(sys.argv[1:])) | 1126 sys.exit(Main(sys.argv[1:])) |
OLD | NEW |