codekingpro/portable-devtools
114k
1#------------------------------------------------------------------------------2# pycparser: c_parser.py3#4# CParser class: Parser and AST builder for the C language5#6# Eli Bendersky [https://eli.thegreenplace.net/]7# License: BSD8#------------------------------------------------------------------------------9from .ply import yacc10 11from . import c_ast12from .c_lexer import CLexer13from .plyparser import PLYParser, ParseError, parameterized, template14from .ast_transforms import fix_switch_cases, fix_atomic_specifiers15 16 17@template18class CParser(PLYParser):19 def __init__(20 self,21 lex_optimize=True,22 lexer=CLexer,23 lextab='pycparser.lextab',24 yacc_optimize=True,25 yacctab='pycparser.yacctab',26 yacc_debug=False,27 taboutputdir=''):28 """ Create a new CParser.29 30 Some arguments for controlling the debug/optimization31 level of the parser are provided. The defaults are32 tuned for release/performance mode.33 The simple rules for using them are:34 *) When tweaking CParser/CLexer, set these to False35 *) When releasing a stable parser, set to True36 37 lex_optimize:38 Set to False when you're modifying the lexer.39 Otherwise, changes in the lexer won't be used, if40 some lextab.py file exists.41 When releasing with a stable lexer, set to True42 to save the re-generation of the lexer table on43 each run.44 45 lexer:46 Set this parameter to define the lexer to use if47 you're not using the default CLexer.48 49 lextab:50 Points to the lex table that's used for optimized51 mode. Only if you're modifying the lexer and want52 some tests to avoid re-generating the table, make53 this point to a local lex table file (that's been54 earlier generated with lex_optimize=True)55 56 yacc_optimize:57 Set to False when you're modifying the parser.58 Otherwise, changes in the parser won't be used, if59 some parsetab.py file exists.60 When releasing with a stable parser, set to True61 to save the re-generation of the parser table on62 each run.63 64 yacctab:65 Points to the yacc table that's used for optimized66 mode. Only if you're modifying the parser, make67 this point to a local yacc table file68 69 yacc_debug:70 Generate a parser.out file that explains how yacc71 built the parsing table from the grammar.72 73 taboutputdir:74 Set this parameter to control the location of generated75 lextab and yacctab files.76 """77 self.clex = lexer(78 error_func=self._lex_error_func,79 on_lbrace_func=self._lex_on_lbrace_func,80 on_rbrace_func=self._lex_on_rbrace_func,81 type_lookup_func=self._lex_type_lookup_func)82 83 self.clex.build(84 optimize=lex_optimize,85 lextab=lextab,86 outputdir=taboutputdir)87 self.tokens = self.clex.tokens88 89 rules_with_opt = [90 'abstract_declarator',91 'assignment_expression',92 'declaration_list',93 'declaration_specifiers_no_type',94 'designation',95 'expression',96 'identifier_list',97 'init_declarator_list',98 'id_init_declarator_list',99 'initializer_list',100 'parameter_type_list',101 'block_item_list',102 'type_qualifier_list',103 'struct_declarator_list'104 ]105 106 for rule in rules_with_opt:107 self._create_opt_rule(rule)108 109 self.cparser = yacc.yacc(110 module=self,111 start='translation_unit_or_empty',112 debug=yacc_debug,113 optimize=yacc_optimize,114 tabmodule=yacctab,115 outputdir=taboutputdir)116 117 # Stack of scopes for keeping track of symbols. _scope_stack[-1] is118 # the current (topmost) scope. Each scope is a dictionary that119 # specifies whether a name is a type. If _scope_stack[n][name] is120 # True, 'name' is currently a type in the scope. If it's False,121 # 'name' is used in the scope but not as a type (for instance, if we122 # saw: int name;123 # If 'name' is not a key in _scope_stack[n] then 'name' was not defined124 # in this scope at all.125 self._scope_stack = [dict()]126 127 # Keeps track of the last token given to yacc (the lookahead token)128 self._last_yielded_token = None129 130 def parse(self, text, filename='', debug=False):131 """ Parses C code and returns an AST.132 133 text:134 A string containing the C source code135 136 filename:137 Name of the file being parsed (for meaningful138 error messages)139 140 debug:141 Debug flag to YACC142 """143 self.clex.filename = filename144 self.clex.reset_lineno()145 self._scope_stack = [dict()]146 self._last_yielded_token = None147 return self.cparser.parse(148 input=text,149 lexer=self.clex,150 debug=debug)151 152 ######################-- PRIVATE --######################153 154 def _push_scope(self):155 self._scope_stack.append(dict())156 157 def _pop_scope(self):158 assert len(self._scope_stack) > 1159 self._scope_stack.pop()160 161 def _add_typedef_name(self, name, coord):162 """ Add a new typedef name (ie a TYPEID) to the current scope163 """164 if not self._scope_stack[-1].get(name, True):165 self._parse_error(166 "Typedef %r previously declared as non-typedef "167 "in this scope" % name, coord)168 self._scope_stack[-1][name] = True169 170 def _add_identifier(self, name, coord):171 """ Add a new object, function, or enum member name (ie an ID) to the172 current scope173 """174 if self._scope_stack[-1].get(name, False):175 self._parse_error(176 "Non-typedef %r previously declared as typedef "177 "in this scope" % name, coord)178 self._scope_stack[-1][name] = False179 180 def _is_type_in_scope(self, name):181 """ Is *name* a typedef-name in the current scope?182 """183 for scope in reversed(self._scope_stack):184 # If name is an identifier in this scope it shadows typedefs in185 # higher scopes.186 in_scope = scope.get(name)187 if in_scope is not None: return in_scope188 return False189 190 def _lex_error_func(self, msg, line, column):191 self._parse_error(msg, self._coord(line, column))192 193 def _lex_on_lbrace_func(self):194 self._push_scope()195 196 def _lex_on_rbrace_func(self):197 self._pop_scope()198 199 def _lex_type_lookup_func(self, name):200 """ Looks up types that were previously defined with201 typedef.202 Passed to the lexer for recognizing identifiers that203 are types.204 """205 is_type = self._is_type_in_scope(name)206 return is_type207 208 def _get_yacc_lookahead_token(self):209 """ We need access to yacc's lookahead token in certain cases.210 This is the last token yacc requested from the lexer, so we211 ask the lexer.212 """213 return self.clex.last_token214 215 # To understand what's going on here, read sections A.8.5 and216 # A.8.6 of K&R2 very carefully.217 #218 # A C type consists of a basic type declaration, with a list219 # of modifiers. For example:220 #221 # int *c[5];222 #223 # The basic declaration here is 'int c', and the pointer and224 # the array are the modifiers.225 #226 # Basic declarations are represented by TypeDecl (from module c_ast) and the227 # modifiers are FuncDecl, PtrDecl and ArrayDecl.228 #229 # The standard states that whenever a new modifier is parsed, it should be230 # added to the end of the list of modifiers. For example:231 #232 # K&R2 A.8.6.2: Array Declarators233 #234 # In a declaration T D where D has the form235 # D1 [constant-expression-opt]236 # and the type of the identifier in the declaration T D1 is237 # "type-modifier T", the type of the238 # identifier of D is "type-modifier array of T"239 #240 # This is what this method does. The declarator it receives241 # can be a list of declarators ending with TypeDecl. It242 # tacks the modifier to the end of this list, just before243 # the TypeDecl.244 #245 # Additionally, the modifier may be a list itself. This is246 # useful for pointers, that can come as a chain from the rule247 # p_pointer. In this case, the whole modifier list is spliced248 # into the new location.249 def _type_modify_decl(self, decl, modifier):250 """ Tacks a type modifier on a declarator, and returns251 the modified declarator.252 253 Note: the declarator and modifier may be modified254 """255 #~ print '****'256 #~ decl.show(offset=3)257 #~ modifier.show(offset=3)258 #~ print '****'259 260 modifier_head = modifier261 modifier_tail = modifier262 263 # The modifier may be a nested list. Reach its tail.264 while modifier_tail.type:265 modifier_tail = modifier_tail.type266 267 # If the decl is a basic type, just tack the modifier onto it.268 if isinstance(decl, c_ast.TypeDecl):269 modifier_tail.type = decl270 return modifier271 else:272 # Otherwise, the decl is a list of modifiers. Reach273 # its tail and splice the modifier onto the tail,274 # pointing to the underlying basic type.275 decl_tail = decl276 277 while not isinstance(decl_tail.type, c_ast.TypeDecl):278 decl_tail = decl_tail.type279 280 modifier_tail.type = decl_tail.type281 decl_tail.type = modifier_head282 return decl283 284 # Due to the order in which declarators are constructed,285 # they have to be fixed in order to look like a normal AST.286 #287 # When a declaration arrives from syntax construction, it has288 # these problems:289 # * The innermost TypeDecl has no type (because the basic290 # type is only known at the uppermost declaration level)291 # * The declaration has no variable name, since that is saved292 # in the innermost TypeDecl293 # * The typename of the declaration is a list of type294 # specifiers, and not a node. Here, basic identifier types295 # should be separated from more complex types like enums296 # and structs.297 #298 # This method fixes these problems.299 def _fix_decl_name_type(self, decl, typename):300 """ Fixes a declaration. Modifies decl.301 """302 # Reach the underlying basic type303 #304 type = decl305 while not isinstance(type, c_ast.TypeDecl):306 type = type.type307 308 decl.name = type.declname309 type.quals = decl.quals[:]310 311 # The typename is a list of types. If any type in this312 # list isn't an IdentifierType, it must be the only313 # type in the list (it's illegal to declare "int enum ..")314 # If all the types are basic, they're collected in the315 # IdentifierType holder.316 for tn in typename:317 if not isinstance(tn, c_ast.IdentifierType):318 if len(typename) > 1:319 self._parse_error(320 "Invalid multiple types specified", tn.coord)321 else:322 type.type = tn323 return decl324 325 if not typename:326 # Functions default to returning int327 #328 if not isinstance(decl.type, c_ast.FuncDecl):329 self._parse_error(330 "Missing type in declaration", decl.coord)331 type.type = c_ast.IdentifierType(332 ['int'],333 coord=decl.coord)334 else:335 # At this point, we know that typename is a list of IdentifierType336 # nodes. Concatenate all the names into a single list.337 #338 type.type = c_ast.IdentifierType(339 [name for id in typename for name in id.names],340 coord=typename[0].coord)341 return decl342 343 def _add_declaration_specifier(self, declspec, newspec, kind, append=False):344 """ Declaration specifiers are represented by a dictionary345 with the entries:346 * qual: a list of type qualifiers347 * storage: a list of storage type qualifiers348 * type: a list of type specifiers349 * function: a list of function specifiers350 * alignment: a list of alignment specifiers351 352 This method is given a declaration specifier, and a353 new specifier of a given kind.354 If `append` is True, the new specifier is added to the end of355 the specifiers list, otherwise it's added at the beginning.356 Returns the declaration specifier, with the new357 specifier incorporated.358 """359 spec = declspec or dict(qual=[], storage=[], type=[], function=[], alignment=[])360 361 if append:362 spec[kind].append(newspec)363 else:364 spec[kind].insert(0, newspec)365 366 return spec367 368 def _build_declarations(self, spec, decls, typedef_namespace=False):369 """ Builds a list of declarations all sharing the given specifiers.370 If typedef_namespace is true, each declared name is added371 to the "typedef namespace", which also includes objects,372 functions, and enum constants.373 """374 is_typedef = 'typedef' in spec['storage']375 declarations = []376 377 # Bit-fields are allowed to be unnamed.378 if decls[0].get('bitsize') is not None:379 pass380 381 # When redeclaring typedef names as identifiers in inner scopes, a382 # problem can occur where the identifier gets grouped into383 # spec['type'], leaving decl as None. This can only occur for the384 # first declarator.385 elif decls[0]['decl'] is None:386 if len(spec['type']) < 2 or len(spec['type'][-1].names) != 1 or \387 not self._is_type_in_scope(spec['type'][-1].names[0]):388 coord = '?'389 for t in spec['type']:390 if hasattr(t, 'coord'):391 coord = t.coord392 break393 self._parse_error('Invalid declaration', coord)394 395 # Make this look as if it came from "direct_declarator:ID"396 decls[0]['decl'] = c_ast.TypeDecl(397 declname=spec['type'][-1].names[0],398 type=None,399 quals=None,400 align=spec['alignment'],401 coord=spec['type'][-1].coord)402 # Remove the "new" type's name from the end of spec['type']403 del spec['type'][-1]404 405 # A similar problem can occur where the declaration ends up looking406 # like an abstract declarator. Give it a name if this is the case.407 elif not isinstance(decls[0]['decl'], (408 c_ast.Enum, c_ast.Struct, c_ast.Union, c_ast.IdentifierType)):409 decls_0_tail = decls[0]['decl']410 while not isinstance(decls_0_tail, c_ast.TypeDecl):411 decls_0_tail = decls_0_tail.type412 if decls_0_tail.declname is None:413 decls_0_tail.declname = spec['type'][-1].names[0]414 del spec['type'][-1]415 416 for decl in decls:417 assert decl['decl'] is not None418 if is_typedef:419 declaration = c_ast.Typedef(420 name=None,421 quals=spec['qual'],422 storage=spec['storage'],423 type=decl['decl'],424 coord=decl['decl'].coord)425 else:426 declaration = c_ast.Decl(427 name=None,428 quals=spec['qual'],429 align=spec['alignment'],430 storage=spec['storage'],431 funcspec=spec['function'],432 type=decl['decl'],433 init=decl.get('init'),434 bitsize=decl.get('bitsize'),435 coord=decl['decl'].coord)436 437 if isinstance(declaration.type, (438 c_ast.Enum, c_ast.Struct, c_ast.Union,439 c_ast.IdentifierType)):440 fixed_decl = declaration441 else:442 fixed_decl = self._fix_decl_name_type(declaration, spec['type'])443 444 # Add the type name defined by typedef to a445 # symbol table (for usage in the lexer)446 if typedef_namespace:447 if is_typedef:448 self._add_typedef_name(fixed_decl.name, fixed_decl.coord)449 else:450 self._add_identifier(fixed_decl.name, fixed_decl.coord)451 452 fixed_decl = fix_atomic_specifiers(fixed_decl)453 declarations.append(fixed_decl)454 455 return declarations456 457 def _build_function_definition(self, spec, decl, param_decls, body):458 """ Builds a function definition.459 """460 if 'typedef' in spec['storage']:461 self._parse_error("Invalid typedef", decl.coord)462 463 declaration = self._build_declarations(464 spec=spec,465 decls=[dict(decl=decl, init=None)],466 typedef_namespace=True)[0]467 468 return c_ast.FuncDef(469 decl=declaration,470 param_decls=param_decls,471 body=body,472 coord=decl.coord)473 474 def _select_struct_union_class(self, token):475 """ Given a token (either STRUCT or UNION), selects the476 appropriate AST class.477 """478 if token == 'struct':479 return c_ast.Struct480 else:481 return c_ast.Union482 483 ##484 ## Precedence and associativity of operators485 ##486 # If this changes, c_generator.CGenerator.precedence_map needs to change as487 # well488 precedence = (489 ('left', 'LOR'),490 ('left', 'LAND'),491 ('left', 'OR'),492 ('left', 'XOR'),493 ('left', 'AND'),494 ('left', 'EQ', 'NE'),495 ('left', 'GT', 'GE', 'LT', 'LE'),496 ('left', 'RSHIFT', 'LSHIFT'),497 ('left', 'PLUS', 'MINUS'),498 ('left', 'TIMES', 'DIVIDE', 'MOD')499 )500 501 ##502 ## Grammar productions503 ## Implementation of the BNF defined in K&R2 A.13504 ##505 506 # Wrapper around a translation unit, to allow for empty input.507 # Not strictly part of the C99 Grammar, but useful in practice.508 def p_translation_unit_or_empty(self, p):509 """ translation_unit_or_empty : translation_unit510 | empty511 """512 if p[1] is None:513 p[0] = c_ast.FileAST([])514 else:515 p[0] = c_ast.FileAST(p[1])516 517 def p_translation_unit_1(self, p):518 """ translation_unit : external_declaration519 """520 # Note: external_declaration is already a list521 p[0] = p[1]522 523 def p_translation_unit_2(self, p):524 """ translation_unit : translation_unit external_declaration525 """526 p[1].extend(p[2])527 p[0] = p[1]528 529 # Declarations always come as lists (because they can be530 # several in one line), so we wrap the function definition531 # into a list as well, to make the return value of532 # external_declaration homogeneous.533 def p_external_declaration_1(self, p):534 """ external_declaration : function_definition535 """536 p[0] = [p[1]]537 538 def p_external_declaration_2(self, p):539 """ external_declaration : declaration540 """541 p[0] = p[1]542 543 def p_external_declaration_3(self, p):544 """ external_declaration : pp_directive545 | pppragma_directive546 """547 p[0] = [p[1]]548 549 def p_external_declaration_4(self, p):550 """ external_declaration : SEMI551 """552 p[0] = []553 554 def p_external_declaration_5(self, p):555 """ external_declaration : static_assert556 """557 p[0] = p[1]558 559 def p_static_assert_declaration(self, p):560 """ static_assert : _STATIC_ASSERT LPAREN constant_expression COMMA unified_string_literal RPAREN561 | _STATIC_ASSERT LPAREN constant_expression RPAREN562 """563 if len(p) == 5:564 p[0] = [c_ast.StaticAssert(p[3], None, self._token_coord(p, 1))]565 else:566 p[0] = [c_ast.StaticAssert(p[3], p[5], self._token_coord(p, 1))]567 568 def p_pp_directive(self, p):569 """ pp_directive : PPHASH570 """571 self._parse_error('Directives not supported yet',572 self._token_coord(p, 1))573 574 # This encompasses two types of C99-compatible pragmas:575 # - The #pragma directive:576 # # pragma character_sequence577 # - The _Pragma unary operator:578 # _Pragma ( " string_literal " )579 def p_pppragma_directive(self, p):580 """ pppragma_directive : PPPRAGMA581 | PPPRAGMA PPPRAGMASTR582 | _PRAGMA LPAREN unified_string_literal RPAREN583 """584 if len(p) == 5:585 p[0] = c_ast.Pragma(p[3], self._token_coord(p, 2))586 elif len(p) == 3:587 p[0] = c_ast.Pragma(p[2], self._token_coord(p, 2))588 else:589 p[0] = c_ast.Pragma("", self._token_coord(p, 1))590 591 def p_pppragma_directive_list(self, p):592 """ pppragma_directive_list : pppragma_directive593 | pppragma_directive_list pppragma_directive594 """595 p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]596 597 # In function definitions, the declarator can be followed by598 # a declaration list, for old "K&R style" function definitios.599 def p_function_definition_1(self, p):600 """ function_definition : id_declarator declaration_list_opt compound_statement601 """602 # no declaration specifiers - 'int' becomes the default type603 spec = dict(604 qual=[],605 alignment=[],606 storage=[],607 type=[c_ast.IdentifierType(['int'],608 coord=self._token_coord(p, 1))],609 function=[])610 611 p[0] = self._build_function_definition(612 spec=spec,613 decl=p[1],614 param_decls=p[2],615 body=p[3])616 617 def p_function_definition_2(self, p):618 """ function_definition : declaration_specifiers id_declarator declaration_list_opt compound_statement619 """620 spec = p[1]621 622 p[0] = self._build_function_definition(623 spec=spec,624 decl=p[2],625 param_decls=p[3],626 body=p[4])627 628 # Note, according to C18 A.2.2 6.7.10 static_assert-declaration _Static_assert629 # is a declaration, not a statement. We additionally recognise it as a statement630 # to fix parsing of _Static_assert inside the functions.631 #632 def p_statement(self, p):633 """ statement : labeled_statement634 | expression_statement635 | compound_statement636 | selection_statement637 | iteration_statement638 | jump_statement639 | pppragma_directive640 | static_assert641 """642 p[0] = p[1]643 644 # A pragma is generally considered a decorator rather than an actual645 # statement. Still, for the purposes of analyzing an abstract syntax tree of646 # C code, pragma's should not be ignored and were previously treated as a647 # statement. This presents a problem for constructs that take a statement648 # such as labeled_statements, selection_statements, and649 # iteration_statements, causing a misleading structure in the AST. For650 # example, consider the following C code.651 #652 # for (int i = 0; i < 3; i++)653 # #pragma omp critical654 # sum += 1;655 #656 # This code will compile and execute "sum += 1;" as the body of the for657 # loop. Previous implementations of PyCParser would render the AST for this658 # block of code as follows:659 #660 # For:661 # DeclList:662 # Decl: i, [], [], []663 # TypeDecl: i, []664 # IdentifierType: ['int']665 # Constant: int, 0666 # BinaryOp: <667 # ID: i668 # Constant: int, 3669 # UnaryOp: p++670 # ID: i671 # Pragma: omp critical672 # Assignment: +=673 # ID: sum674 # Constant: int, 1675 #676 # This AST misleadingly takes the Pragma as the body of the loop and the677 # assignment then becomes a sibling of the loop.678 #679 # To solve edge cases like these, the pragmacomp_or_statement rule groups680 # a pragma and its following statement (which would otherwise be orphaned)681 # using a compound block, effectively turning the above code into:682 #683 # for (int i = 0; i < 3; i++) {684 # #pragma omp critical685 # sum += 1;686 # }687 def p_pragmacomp_or_statement(self, p):688 """ pragmacomp_or_statement : pppragma_directive_list statement689 | statement690 """691 if len(p) == 3:692 p[0] = c_ast.Compound(693 block_items=p[1]+[p[2]],694 coord=self._token_coord(p, 1))695 else:696 p[0] = p[1]697 698 # In C, declarations can come several in a line:699 # int x, *px, romulo = 5;700 #701 # However, for the AST, we will split them to separate Decl702 # nodes.703 #704 # This rule splits its declarations and always returns a list705 # of Decl nodes, even if it's one element long.706 #707 def p_decl_body(self, p):708 """ decl_body : declaration_specifiers init_declarator_list_opt709 | declaration_specifiers_no_type id_init_declarator_list_opt710 """711 spec = p[1]712 713 # p[2] (init_declarator_list_opt) is either a list or None714 #715 if p[2] is None:716 # By the standard, you must have at least one declarator unless717 # declaring a structure tag, a union tag, or the members of an718 # enumeration.719 #720 ty = spec['type']721 s_u_or_e = (c_ast.Struct, c_ast.Union, c_ast.Enum)722 if len(ty) == 1 and isinstance(ty[0], s_u_or_e):723 decls = [c_ast.Decl(724 name=None,725 quals=spec['qual'],726 align=spec['alignment'],727 storage=spec['storage'],728 funcspec=spec['function'],729 type=ty[0],730 init=None,731 bitsize=None,732 coord=ty[0].coord)]733 734 # However, this case can also occur on redeclared identifiers in735 # an inner scope. The trouble is that the redeclared type's name736 # gets grouped into declaration_specifiers; _build_declarations737 # compensates for this.738 #739 else:740 decls = self._build_declarations(741 spec=spec,742 decls=[dict(decl=None, init=None)],743 typedef_namespace=True)744 745 else:746 decls = self._build_declarations(747 spec=spec,748 decls=p[2],749 typedef_namespace=True)750 751 p[0] = decls752 753 # The declaration has been split to a decl_body sub-rule and754 # SEMI, because having them in a single rule created a problem755 # for defining typedefs.756 #757 # If a typedef line was directly followed by a line using the758 # type defined with the typedef, the type would not be759 # recognized. This is because to reduce the declaration rule,760 # the parser's lookahead asked for the token after SEMI, which761 # was the type from the next line, and the lexer had no chance762 # to see the updated type symbol table.763 #764 # Splitting solves this problem, because after seeing SEMI,765 # the parser reduces decl_body, which actually adds the new766 # type into the table to be seen by the lexer before the next767 # line is reached.768 def p_declaration(self, p):769 """ declaration : decl_body SEMI770 """771 p[0] = p[1]772 773 # Since each declaration is a list of declarations, this774 # rule will combine all the declarations and return a single775 # list776 #777 def p_declaration_list(self, p):778 """ declaration_list : declaration779 | declaration_list declaration780 """781 p[0] = p[1] if len(p) == 2 else p[1] + p[2]782 783 # To know when declaration-specifiers end and declarators begin,784 # we require declaration-specifiers to have at least one785 # type-specifier, and disallow typedef-names after we've seen any786 # type-specifier. These are both required by the spec.787 #788 def p_declaration_specifiers_no_type_1(self, p):789 """ declaration_specifiers_no_type : type_qualifier declaration_specifiers_no_type_opt790 """791 p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')792 793 def p_declaration_specifiers_no_type_2(self, p):794 """ declaration_specifiers_no_type : storage_class_specifier declaration_specifiers_no_type_opt795 """796 p[0] = self._add_declaration_specifier(p[2], p[1], 'storage')797 798 def p_declaration_specifiers_no_type_3(self, p):799 """ declaration_specifiers_no_type : function_specifier declaration_specifiers_no_type_opt800 """801 p[0] = self._add_declaration_specifier(p[2], p[1], 'function')802 803 # Without this, `typedef _Atomic(T) U` will parse incorrectly because the804 # _Atomic qualifier will match, instead of the specifier.805 def p_declaration_specifiers_no_type_4(self, p):806 """ declaration_specifiers_no_type : atomic_specifier declaration_specifiers_no_type_opt807 """808 p[0] = self._add_declaration_specifier(p[2], p[1], 'type')809 810 def p_declaration_specifiers_no_type_5(self, p):811 """ declaration_specifiers_no_type : alignment_specifier declaration_specifiers_no_type_opt812 """813 p[0] = self._add_declaration_specifier(p[2], p[1], 'alignment')814 815 def p_declaration_specifiers_1(self, p):816 """ declaration_specifiers : declaration_specifiers type_qualifier817 """818 p[0] = self._add_declaration_specifier(p[1], p[2], 'qual', append=True)819 820 def p_declaration_specifiers_2(self, p):821 """ declaration_specifiers : declaration_specifiers storage_class_specifier822 """823 p[0] = self._add_declaration_specifier(p[1], p[2], 'storage', append=True)824 825 def p_declaration_specifiers_3(self, p):826 """ declaration_specifiers : declaration_specifiers function_specifier827 """828 p[0] = self._add_declaration_specifier(p[1], p[2], 'function', append=True)829 830 def p_declaration_specifiers_4(self, p):831 """ declaration_specifiers : declaration_specifiers type_specifier_no_typeid832 """833 p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True)834 835 def p_declaration_specifiers_5(self, p):836 """ declaration_specifiers : type_specifier837 """838 p[0] = self._add_declaration_specifier(None, p[1], 'type')839 840 def p_declaration_specifiers_6(self, p):841 """ declaration_specifiers : declaration_specifiers_no_type type_specifier842 """843 p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True)844 845 def p_declaration_specifiers_7(self, p):846 """ declaration_specifiers : declaration_specifiers alignment_specifier847 """848 p[0] = self._add_declaration_specifier(p[1], p[2], 'alignment', append=True)849 850 def p_storage_class_specifier(self, p):851 """ storage_class_specifier : AUTO852 | REGISTER853 | STATIC854 | EXTERN855 | TYPEDEF856 | _THREAD_LOCAL857 """858 p[0] = p[1]859 860 def p_function_specifier(self, p):861 """ function_specifier : INLINE862 | _NORETURN863 """864 p[0] = p[1]865 866 def p_type_specifier_no_typeid(self, p):867 """ type_specifier_no_typeid : VOID868 | _BOOL869 | CHAR870 | SHORT871 | INT872 | LONG873 | FLOAT874 | DOUBLE875 | _COMPLEX876 | SIGNED877 | UNSIGNED878 | __INT128879 """880 p[0] = c_ast.IdentifierType([p[1]], coord=self._token_coord(p, 1))881 882 def p_type_specifier(self, p):883 """ type_specifier : typedef_name884 | enum_specifier885 | struct_or_union_specifier886 | type_specifier_no_typeid887 | atomic_specifier888 """889 p[0] = p[1]890 891 # See section 6.7.2.4 of the C11 standard.892 def p_atomic_specifier(self, p):893 """ atomic_specifier : _ATOMIC LPAREN type_name RPAREN894 """895 typ = p[3]896 typ.quals.append('_Atomic')897 p[0] = typ898 899 def p_type_qualifier(self, p):900 """ type_qualifier : CONST901 | RESTRICT902 | VOLATILE903 | _ATOMIC904 """905 p[0] = p[1]906 907 def p_init_declarator_list(self, p):908 """ init_declarator_list : init_declarator909 | init_declarator_list COMMA init_declarator910 """911 p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]912 913 # Returns a {decl=<declarator> : init=<initializer>} dictionary914 # If there's no initializer, uses None915 #916 def p_init_declarator(self, p):917 """ init_declarator : declarator918 | declarator EQUALS initializer919 """920 p[0] = dict(decl=p[1], init=(p[3] if len(p) > 2 else None))921 922 def p_id_init_declarator_list(self, p):923 """ id_init_declarator_list : id_init_declarator924 | id_init_declarator_list COMMA init_declarator925 """926 p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]927 928 def p_id_init_declarator(self, p):929 """ id_init_declarator : id_declarator930 | id_declarator EQUALS initializer931 """932 p[0] = dict(decl=p[1], init=(p[3] if len(p) > 2 else None))933 934 # Require at least one type specifier in a specifier-qualifier-list935 #936 def p_specifier_qualifier_list_1(self, p):937 """ specifier_qualifier_list : specifier_qualifier_list type_specifier_no_typeid938 """939 p[0] = self._add_declaration_specifier(p[1], p[2], 'type', append=True)940 941 def p_specifier_qualifier_list_2(self, p):942 """ specifier_qualifier_list : specifier_qualifier_list type_qualifier943 """944 p[0] = self._add_declaration_specifier(p[1], p[2], 'qual', append=True)945 946 def p_specifier_qualifier_list_3(self, p):947 """ specifier_qualifier_list : type_specifier948 """949 p[0] = self._add_declaration_specifier(None, p[1], 'type')950 951 def p_specifier_qualifier_list_4(self, p):952 """ specifier_qualifier_list : type_qualifier_list type_specifier953 """954 p[0] = dict(qual=p[1], alignment=[], storage=[], type=[p[2]], function=[])955 956 def p_specifier_qualifier_list_5(self, p):957 """ specifier_qualifier_list : alignment_specifier958 """959 p[0] = dict(qual=[], alignment=[p[1]], storage=[], type=[], function=[])960 961 def p_specifier_qualifier_list_6(self, p):962 """ specifier_qualifier_list : specifier_qualifier_list alignment_specifier963 """964 p[0] = self._add_declaration_specifier(p[1], p[2], 'alignment')965 966 # TYPEID is allowed here (and in other struct/enum related tag names), because967 # struct/enum tags reside in their own namespace and can be named the same as types968 #969 def p_struct_or_union_specifier_1(self, p):970 """ struct_or_union_specifier : struct_or_union ID971 | struct_or_union TYPEID972 """973 klass = self._select_struct_union_class(p[1])974 # None means no list of members975 p[0] = klass(976 name=p[2],977 decls=None,978 coord=self._token_coord(p, 2))979 980 def p_struct_or_union_specifier_2(self, p):981 """ struct_or_union_specifier : struct_or_union brace_open struct_declaration_list brace_close982 | struct_or_union brace_open brace_close983 """984 klass = self._select_struct_union_class(p[1])985 if len(p) == 4:986 # Empty sequence means an empty list of members987 p[0] = klass(988 name=None,989 decls=[],990 coord=self._token_coord(p, 2))991 else:992 p[0] = klass(993 name=None,994 decls=p[3],995 coord=self._token_coord(p, 2))996 997 998 def p_struct_or_union_specifier_3(self, p):999 """ struct_or_union_specifier : struct_or_union ID brace_open struct_declaration_list brace_close1000 | struct_or_union ID brace_open brace_close1001 | struct_or_union TYPEID brace_open struct_declaration_list brace_close1002 | struct_or_union TYPEID brace_open brace_close1003 """1004 klass = self._select_struct_union_class(p[1])1005 if len(p) == 5:1006 # Empty sequence means an empty list of members1007 p[0] = klass(1008 name=p[2],1009 decls=[],1010 coord=self._token_coord(p, 2))1011 else:1012 p[0] = klass(1013 name=p[2],1014 decls=p[4],1015 coord=self._token_coord(p, 2))1016 1017 def p_struct_or_union(self, p):1018 """ struct_or_union : STRUCT1019 | UNION1020 """1021 p[0] = p[1]1022 1023 # Combine all declarations into a single list1024 #1025 def p_struct_declaration_list(self, p):1026 """ struct_declaration_list : struct_declaration1027 | struct_declaration_list struct_declaration1028 """1029 if len(p) == 2:1030 p[0] = p[1] or []1031 else:1032 p[0] = p[1] + (p[2] or [])1033 1034 def p_struct_declaration_1(self, p):1035 """ struct_declaration : specifier_qualifier_list struct_declarator_list_opt SEMI1036 """1037 spec = p[1]1038 assert 'typedef' not in spec['storage']1039 1040 if p[2] is not None:1041 decls = self._build_declarations(1042 spec=spec,1043 decls=p[2])1044 1045 elif len(spec['type']) == 1:1046 # Anonymous struct/union, gcc extension, C1x feature.1047 # Although the standard only allows structs/unions here, I see no1048 # reason to disallow other types since some compilers have typedefs1049 # here, and pycparser isn't about rejecting all invalid code.1050 #1051 node = spec['type'][0]1052 if isinstance(node, c_ast.Node):1053 decl_type = node1054 else:1055 decl_type = c_ast.IdentifierType(node)1056 1057 decls = self._build_declarations(1058 spec=spec,1059 decls=[dict(decl=decl_type)])1060 1061 else:1062 # Structure/union members can have the same names as typedefs.1063 # The trouble is that the member's name gets grouped into1064 # specifier_qualifier_list; _build_declarations compensates.1065 #1066 decls = self._build_declarations(1067 spec=spec,1068 decls=[dict(decl=None, init=None)])1069 1070 p[0] = decls1071 1072 def p_struct_declaration_2(self, p):1073 """ struct_declaration : SEMI1074 """1075 p[0] = None1076 1077 def p_struct_declaration_3(self, p):1078 """ struct_declaration : pppragma_directive1079 """1080 p[0] = [p[1]]1081 1082 def p_struct_declarator_list(self, p):1083 """ struct_declarator_list : struct_declarator1084 | struct_declarator_list COMMA struct_declarator1085 """1086 p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]1087 1088 # struct_declarator passes up a dict with the keys: decl (for1089 # the underlying declarator) and bitsize (for the bitsize)1090 #1091 def p_struct_declarator_1(self, p):1092 """ struct_declarator : declarator1093 """1094 p[0] = {'decl': p[1], 'bitsize': None}1095 1096 def p_struct_declarator_2(self, p):1097 """ struct_declarator : declarator COLON constant_expression1098 | COLON constant_expression1099 """1100 if len(p) > 3:1101 p[0] = {'decl': p[1], 'bitsize': p[3]}1102 else:1103 p[0] = {'decl': c_ast.TypeDecl(None, None, None, None), 'bitsize': p[2]}1104 1105 def p_enum_specifier_1(self, p):1106 """ enum_specifier : ENUM ID1107 | ENUM TYPEID1108 """1109 p[0] = c_ast.Enum(p[2], None, self._token_coord(p, 1))1110 1111 def p_enum_specifier_2(self, p):1112 """ enum_specifier : ENUM brace_open enumerator_list brace_close1113 """1114 p[0] = c_ast.Enum(None, p[3], self._token_coord(p, 1))1115 1116 def p_enum_specifier_3(self, p):1117 """ enum_specifier : ENUM ID brace_open enumerator_list brace_close1118 | ENUM TYPEID brace_open enumerator_list brace_close1119 """1120 p[0] = c_ast.Enum(p[2], p[4], self._token_coord(p, 1))1121 1122 def p_enumerator_list(self, p):1123 """ enumerator_list : enumerator1124 | enumerator_list COMMA1125 | enumerator_list COMMA enumerator1126 """1127 if len(p) == 2:1128 p[0] = c_ast.EnumeratorList([p[1]], p[1].coord)1129 elif len(p) == 3:1130 p[0] = p[1]1131 else:1132 p[1].enumerators.append(p[3])1133 p[0] = p[1]1134 1135 def p_alignment_specifier(self, p):1136 """ alignment_specifier : _ALIGNAS LPAREN type_name RPAREN1137 | _ALIGNAS LPAREN constant_expression RPAREN1138 """1139 p[0] = c_ast.Alignas(p[3], self._token_coord(p, 1))1140 1141 def p_enumerator(self, p):1142 """ enumerator : ID1143 | ID EQUALS constant_expression1144 """1145 if len(p) == 2:1146 enumerator = c_ast.Enumerator(1147 p[1], None,1148 self._token_coord(p, 1))1149 else:1150 enumerator = c_ast.Enumerator(1151 p[1], p[3],1152 self._token_coord(p, 1))1153 self._add_identifier(enumerator.name, enumerator.coord)1154 1155 p[0] = enumerator1156 1157 def p_declarator(self, p):1158 """ declarator : id_declarator1159 | typeid_declarator1160 """1161 p[0] = p[1]1162 1163 @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))1164 def p_xxx_declarator_1(self, p):1165 """ xxx_declarator : direct_xxx_declarator1166 """1167 p[0] = p[1]1168 1169 @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))1170 def p_xxx_declarator_2(self, p):1171 """ xxx_declarator : pointer direct_xxx_declarator1172 """1173 p[0] = self._type_modify_decl(p[2], p[1])1174 1175 @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))1176 def p_direct_xxx_declarator_1(self, p):1177 """ direct_xxx_declarator : yyy1178 """1179 p[0] = c_ast.TypeDecl(1180 declname=p[1],1181 type=None,1182 quals=None,1183 align=None,1184 coord=self._token_coord(p, 1))1185 1186 @parameterized(('id', 'ID'), ('typeid', 'TYPEID'))1187 def p_direct_xxx_declarator_2(self, p):1188 """ direct_xxx_declarator : LPAREN xxx_declarator RPAREN1189 """1190 p[0] = p[2]1191 1192 @parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))1193 def p_direct_xxx_declarator_3(self, p):1194 """ direct_xxx_declarator : direct_xxx_declarator LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET1195 """1196 quals = (p[3] if len(p) > 5 else []) or []1197 # Accept dimension qualifiers1198 # Per C99 6.7.5.3 p71199 arr = c_ast.ArrayDecl(1200 type=None,