1#!/usr/local/bin/python3.8 2 3'''This is a yacc grammar for C. 4 5Derived from ANSI C grammar: 6 * Lexicon: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html 7 * Grammar: http://www.lysator.liu.se/c/ANSI-C-grammar-y.html 8 9Reference is C99: 10 * http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf 11 12''' 13__docformat__ = 'restructuredtext' 14 15import operator 16import os.path 17import re 18import sys 19import time 20import warnings 21 22from . import cdeclarations 23try: 24 from . import ctypesparser 25except: 26 import ctypesparser 27import ctypesgencore.expressions as expressions 28from . import preprocessor 29from . import yacc 30 31 32if sys.version_info.major == 3: 33 long = int 34 35 36tokens = ( 37 'PP_DEFINE', 'PP_DEFINE_NAME', 'PP_DEFINE_MACRO_NAME', 'PP_MACRO_PARAM', 38 'PP_STRINGIFY', 'PP_IDENTIFIER_PASTE', 'PP_END_DEFINE', 39 40 'IDENTIFIER', 'CONSTANT', 'CHARACTER_CONSTANT', 'STRING_LITERAL', 'SIZEOF', 41 'PTR_OP', 'INC_OP', 'DEC_OP', 'LEFT_OP', 'RIGHT_OP', 'LE_OP', 'GE_OP', 42 'EQ_OP', 'NE_OP', 'AND_OP', 'OR_OP', 'MUL_ASSIGN', 'DIV_ASSIGN', 43 'MOD_ASSIGN', 'ADD_ASSIGN', 'SUB_ASSIGN', 'LEFT_ASSIGN', 'RIGHT_ASSIGN', 44 'AND_ASSIGN', 'XOR_ASSIGN', 'OR_ASSIGN', 'PERIOD', 'TYPE_NAME', 45 46 'TYPEDEF', 'EXTERN', 'STATIC', 'AUTO', 'REGISTER', 47 '_BOOL', 'CHAR', 'SHORT', 'INT', 'LONG', 'SIGNED', 'UNSIGNED', 'FLOAT', 'DOUBLE', 48 'CONST', 'VOLATILE', 'VOID', 49 'STRUCT', 'UNION', 'ENUM', 'ELLIPSIS', 50 51 'CASE', 'DEFAULT', 'IF', 'ELSE', 'SWITCH', 'WHILE', 'DO', 'FOR', 'GOTO', 52 'CONTINUE', 'BREAK', 'RETURN', '__ASM__', '__ATTRIBUTE__', 'PACKED', 53 'ALIGNED', 'TRANSPARENT_UNION', 54) 55 56keywords = [ 57 'auto', '_Bool', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 58 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'int', 59 'long', 'register', 'return', 'short', 'signed', 'sizeof', 'static', 60 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 61 'while', '__asm__', '__attribute__', 'packed', 'aligned', 62 'transparent_union', 63] 64 65 66def p_translation_unit(p): 67 '''translation_unit : 68 | translation_unit external_declaration 69 | translation_unit define 70 ''' 71 # Starting production. 72 # Allow empty production so that files with no declarations are still 73 # valid. 74 # Intentionally empty 75 76 77def p_identifier(p): 78 '''identifier : IDENTIFIER 79 | IDENTIFIER PP_IDENTIFIER_PASTE identifier 80 | PP_MACRO_PARAM PP_IDENTIFIER_PASTE identifier 81 | IDENTIFIER PP_IDENTIFIER_PASTE PP_MACRO_PARAM 82 | PP_MACRO_PARAM PP_IDENTIFIER_PASTE PP_MACRO_PARAM 83 ''' 84 if len(p) == 2: 85 p[0] = expressions.IdentifierExpressionNode(p[1]) 86 else: 87 # Should it be supported? It wouldn't be very hard to add support. 88 # Basically, it would involve a new ExpressionNode called 89 # an IdentifierPasteExpressionNode that took a list of strings and 90 # ParameterExpressionNodes. Then it would generate code like 91 # "locals()['%s' + '%s' + ...]" where %s was substituted with the 92 # elements of the list. I haven't supported it yet because I think 93 # it's unnecessary and a little too powerful. 94 p[0] = expressions.UnsupportedExpressionNode("Identifier pasting is " 95 "not supported by ctypesgen.") 96 97 98def p_constant(p): 99 '''constant : CONSTANT 100 | CHARACTER_CONSTANT 101 ''' 102 constant = p[1] 103 104 if constant[0] == "'": 105 # Character constant 106 value = constant[1:-1] 107 else: 108 # This is a value formatted the way that the preprocessor formats 109 # numeric constants. It puts a prefix "l", "i", or "f" to indicate 110 # if it should be converted into an integer, long or float. 111 prefix = constant[0] 112 constant = constant[1:] 113 if prefix == "i": 114 value = int(constant) 115 elif prefix == "l": 116 value = long(constant) 117 else: 118 value = float(constant) 119 120 p[0] = expressions.ConstantExpressionNode(value) 121 122 123def p_string_literal(p): 124 '''string_literal : STRING_LITERAL''' 125 p[0] = expressions.ConstantExpressionNode(p[1]) 126 127 128def p_multi_string_literal(p): 129 '''multi_string_literal : string_literal 130 | macro_param 131 | multi_string_literal string_literal 132 | multi_string_literal macro_param 133 ''' 134 if len(p) == 2: 135 p[0] = p[1] 136 else: 137 p[0] = expressions.BinaryExpressionNode( 138 "string concatenation", (lambda x, y: x + y), 139 "(%s + %s)", (False, False), 140 p[1], 141 p[2]) 142 143 144def p_macro_param(p): 145 '''macro_param : PP_MACRO_PARAM 146 | PP_STRINGIFY PP_MACRO_PARAM 147 ''' 148 if len(p) == 2: 149 p[0] = expressions.ParameterExpressionNode(p[1]) 150 else: 151 p[0] = expressions.ParameterExpressionNode(p[2]) 152 153 154def p_primary_expression(p): 155 '''primary_expression : identifier 156 | constant 157 | multi_string_literal 158 | '(' expression ')' 159 ''' 160 if p[1] == '(': 161 p[0] = p[2] 162 else: 163 p[0] = p[1] 164 165 166def p_postfix_expression(p): 167 '''postfix_expression : primary_expression 168 | postfix_expression '[' expression ']' 169 | postfix_expression '(' ')' 170 | postfix_expression '(' argument_expression_list ')' 171 | postfix_expression PERIOD IDENTIFIER 172 | postfix_expression PTR_OP IDENTIFIER 173 | postfix_expression INC_OP 174 | postfix_expression DEC_OP 175 ''' 176 177 if len(p) == 2: 178 p[0] = p[1] 179 180 elif p[2] == '[': 181 p[0] = expressions.BinaryExpressionNode( 182 "array access", (lambda a, b: a[b]), 183 "(%s [%s])", (True, False), 184 p[1], 185 p[3]) 186 187 elif p[2] == '(': 188 if p[3] == ')': 189 p[0] = expressions.CallExpressionNode(p[1], []) 190 else: 191 p[0] = expressions.CallExpressionNode(p[1], p[3]) 192 193 elif p[2] == '.': 194 p[0] = expressions.AttributeExpressionNode( 195 (lambda x, a: getattr(x, a)), "(%s.%s)", p[1], p[3]) 196 197 elif p[2] == '->': 198 p[0] = expressions.AttributeExpressionNode( 199 (lambda x, a: getattr(x.contents, a)), "(%s.contents.%s)", p[1], p[3]) 200 201 elif p[2] == '++': 202 p[0] = expressions.UnaryExpressionNode("increment", (lambda x: x + 1), 203 "(%s + 1)", False, p[1]) 204 205 elif p[2] == '--': 206 p[0] = expressions.UnaryExpressionNode("decrement", (lambda x: x - 1), 207 "(%s - 1)", False, p[1]) 208 209 210def p_argument_expression_list(p): 211 '''argument_expression_list : assignment_expression 212 | argument_expression_list ',' assignment_expression 213 ''' 214 if len(p) == 4: 215 p[1].append(p[3]) 216 p[0] = p[1] 217 else: 218 p[0] = [p[1]] 219 220 221def p_asm_expression(p): 222 '''asm_expression : __ASM__ volatile_opt '(' string_literal ')' 223 | __ASM__ volatile_opt '(' string_literal ':' str_opt_expr_pair_list ')' 224 | __ASM__ volatile_opt '(' string_literal ':' str_opt_expr_pair_list ':' str_opt_expr_pair_list ')' 225 | __ASM__ volatile_opt '(' string_literal ':' str_opt_expr_pair_list ':' str_opt_expr_pair_list ':' str_opt_expr_pair_list ')' 226 ''' 227 228 # Definitely not ISO C, adapted from example ANTLR GCC parser at 229 # http://www.antlr.org/grammar/cgram//grammars/GnuCParser.g 230 # but more lenient (expressions permitted in optional final part, when 231 # they shouldn't be -- avoids shift/reduce conflict with 232 # str_opt_expr_pair_list). 233 234 p[0] = expressions.UnsupportedExpressionNode("This node is ASM assembler.") 235 236 237def p_str_opt_expr_pair_list(p): 238 '''str_opt_expr_pair_list : 239 | str_opt_expr_pair 240 | str_opt_expr_pair_list ',' str_opt_expr_pair 241 ''' 242 243 244def p_str_opt_expr_pair(p): 245 '''str_opt_expr_pair : string_literal 246 | string_literal '(' expression ')' 247 ''' 248 249 250def p_volatile_opt(p): 251 '''volatile_opt : 252 | VOLATILE 253 ''' 254 255prefix_ops_dict = { 256 "++": ("increment", (lambda x: x + 1), "(%s + 1)", False), 257 "--": ("decrement", (lambda x: x - 1), "(%s - 1)", False), 258 '&': ("reference ('&')", None, "pointer(%s)", True), 259 '*': ("dereference ('*')", None, "(%s[0])", True), 260 '+': ("unary '+'", (lambda x: x), "%s", True), 261 '-': ("negation", (lambda x: -x), "(-%s)", False), 262 '~': ("inversion", (lambda x: ~x), "(~%s)", False), 263 '!': ("logical not", (lambda x: not x), "(not %s)", True) 264} 265 266 267def p_unary_expression(p): 268 '''unary_expression : postfix_expression 269 | INC_OP unary_expression 270 | DEC_OP unary_expression 271 | unary_operator cast_expression 272 | SIZEOF unary_expression 273 | SIZEOF '(' type_name ')' 274 | asm_expression 275 ''' 276 if len(p) == 2: 277 p[0] = p[1] 278 279 elif p[1] == 'sizeof': 280 if len(p) == 5: 281 p[0] = expressions.SizeOfExpressionNode(p[3]) 282 else: 283 p[0] = expressions.SizeOfExpressionNode(p[2]) 284 285 else: 286 name, op, format, can_be_ctype = prefix_ops_dict[p[1]] 287 p[0] = expressions.UnaryExpressionNode(name, op, format, can_be_ctype, 288 p[2]) 289 290 291def p_unary_operator(p): 292 '''unary_operator : '&' 293 | '*' 294 | '+' 295 | '-' 296 | '~' 297 | '!' 298 ''' 299 p[0] = p[1] 300 301 302def p_cast_expression(p): 303 '''cast_expression : unary_expression 304 | '(' type_name ')' cast_expression 305 ''' 306 if len(p) == 2: 307 p[0] = p[1] 308 else: 309 p[0] = expressions.TypeCastExpressionNode(p[4], p[2]) 310 311mult_ops_dict = { 312 '*': ("multiplication", (lambda x, y: x * y), "(%s * %s)"), 313 '/': ("division", (lambda x, y: x / y), "(%s / %s)"), 314 '%': ("modulo", (lambda x, y: x % y), "(%s %% %s)") 315} 316 317 318def p_multiplicative_expression(p): 319 '''multiplicative_expression : cast_expression 320 | multiplicative_expression '*' cast_expression 321 | multiplicative_expression '/' cast_expression 322 | multiplicative_expression '%' cast_expression 323 ''' 324 if len(p) == 2: 325 p[0] = p[1] 326 else: 327 name, op, format = mult_ops_dict[p[2]] 328 p[0] = expressions.BinaryExpressionNode(name, op, format, (False, False), 329 p[1], p[3]) 330 331add_ops_dict = { 332 '+': ("addition", (lambda x, y: x + y), "(%s + %s)"), 333 '-': ("subtraction", (lambda x, y: x - y), "(%s - %s)") 334} 335 336 337def p_additive_expression(p): 338 '''additive_expression : multiplicative_expression 339 | additive_expression '+' multiplicative_expression 340 | additive_expression '-' multiplicative_expression 341 ''' 342 if len(p) == 2: 343 p[0] = p[1] 344 else: 345 name, op, format = add_ops_dict[p[2]] 346 p[0] = expressions.BinaryExpressionNode(name, op, format, (False, False), 347 p[1], p[3]) 348 349shift_ops_dict = { 350 '>>': ("right shift", (lambda x, y: x >> y), "(%s >> %s)"), 351 '<<': ("left shift", (lambda x, y: x << y), "(%s << %s)") 352} 353 354 355def p_shift_expression(p): 356 '''shift_expression : additive_expression 357 | shift_expression LEFT_OP additive_expression 358 | shift_expression RIGHT_OP additive_expression 359 ''' 360 if len(p) == 2: 361 p[0] = p[1] 362 else: 363 name, op, format = shift_ops_dict[p[2]] 364 p[0] = expressions.BinaryExpressionNode(name, op, format, (False, False), 365 p[1], p[3]) 366 367rel_ops_dict = { 368 '>': ("greater-than", (lambda x, y: x > y), "(%s > %s)"), 369 '<': ("less-than", (lambda x, y: x < y), "(%s < %s)"), 370 '>=': ("greater-than-equal", (lambda x, y: x >= y), "(%s >= %s)"), 371 '<=': ("less-than-equal", (lambda x, y: x <= y), "(%s <= %s)") 372} 373 374 375def p_relational_expression(p): 376 '''relational_expression : shift_expression 377 | relational_expression '<' shift_expression 378 | relational_expression '>' shift_expression 379 | relational_expression LE_OP shift_expression 380 | relational_expression GE_OP shift_expression 381 ''' 382 if len(p) == 2: 383 p[0] = p[1] 384 else: 385 name, op, format = rel_ops_dict[p[2]] 386 p[0] = expressions.BinaryExpressionNode(name, op, format, (False, False), 387 p[1], p[3]) 388 389equality_ops_dict = { 390 '==': ("equals", (lambda x, y: x == y), "(%s == %s)"), 391 '!=': ("not equals", (lambda x, y: x != y), "(%s != %s)") 392} 393 394 395def p_equality_expression(p): 396 '''equality_expression : relational_expression 397 | equality_expression EQ_OP relational_expression 398 | equality_expression NE_OP relational_expression 399 ''' 400 if len(p) == 2: 401 p[0] = p[1] 402 else: 403 name, op, format = equality_ops_dict[p[2]] 404 p[0] = expressions.BinaryExpressionNode(name, op, format, (False, False), 405 p[1], p[3]) 406 407 408def p_and_expression(p): 409 '''and_expression : equality_expression 410 | and_expression '&' equality_expression 411 ''' 412 if len(p) == 2: 413 p[0] = p[1] 414 else: 415 p[0] = expressions.BinaryExpressionNode( 416 "bitwise and", (lambda x, y: x & y), 417 "(%s & %s)", (False, False), 418 p[1], 419 p[3]) 420 421 422def p_exclusive_or_expression(p): 423 '''exclusive_or_expression : and_expression 424 | exclusive_or_expression '^' and_expression 425 ''' 426 if len(p) == 2: 427 p[0] = p[1] 428 else: 429 p[0] = expressions.BinaryExpressionNode( 430 "bitwise xor", (lambda x, y: x ^ y), 431 "(%s ^ %s)", (False, False), 432 p[1], 433 p[3]) 434 435 436def p_inclusive_or_expression(p): 437 '''inclusive_or_expression : exclusive_or_expression 438 | inclusive_or_expression '|' exclusive_or_expression 439 ''' 440 if len(p) == 2: 441 p[0] = p[1] 442 else: 443 p[0] = expressions.BinaryExpressionNode( 444 "bitwise or", (lambda x, y: x | y), 445 "(%s | %s)", (False, False), 446 p[1], 447 p[3]) 448 449 450def p_logical_and_expression(p): 451 '''logical_and_expression : inclusive_or_expression 452 | logical_and_expression AND_OP inclusive_or_expression 453 ''' 454 if len(p) == 2: 455 p[0] = p[1] 456 else: 457 p[0] = expressions.BinaryExpressionNode( 458 "logical and", (lambda x, y: x and y), 459 "(%s and %s)", (True, True), 460 p[1], 461 p[3]) 462 463 464def p_logical_or_expression(p): 465 '''logical_or_expression : logical_and_expression 466 | logical_or_expression OR_OP logical_and_expression 467 ''' 468 if len(p) == 2: 469 p[0] = p[1] 470 else: 471 p[0] = expressions.BinaryExpressionNode( 472 "logical and", (lambda x, y: x or y), 473 "(%s or %s)", (True, True), 474 p[1], 475 p[3]) 476 477 478def p_conditional_expression(p): 479 '''conditional_expression : logical_or_expression 480 | logical_or_expression '?' expression ':' conditional_expression 481 ''' 482 if len(p) == 2: 483 p[0] = p[1] 484 else: 485 p[0] = expressions.ConditionalExpressionNode(p[1], p[3], p[5]) 486 487assign_ops_dict = { 488 '*=': ("multiply", (lambda x, y: x * y), "(%s * %s)"), 489 '/=': ("divide", (lambda x, y: x / y), "(%s / %s)"), 490 '%=': ("modulus", (lambda x, y: x % y), "(%s % %s)"), 491 '+=': ("addition", (lambda x, y: x + y), "(%s + %s)"), 492 '-=': ("subtraction", (lambda x, y: x - y), "(%s - %s)"), 493 '<<=': ("left shift", (lambda x, y: x << y), "(%s << %s)"), 494 '>>=': ("right shift", (lambda x, y: x >> y), "(%s >> %s)"), 495 '&=': ("bitwise and", (lambda x, y: x & y), "(%s & %s)"), 496 '^=': ("bitwise xor", (lambda x, y: x ^ y), "(%s ^ %s)"), 497 '|=': ("bitwise or", (lambda x, y: x | y), "(%s | %s)") 498} 499 500 501def p_assignment_expression(p): 502 '''assignment_expression : conditional_expression 503 | unary_expression assignment_operator assignment_expression 504 ''' 505 if len(p) == 2: 506 p[0] = p[1] 507 else: 508 # In C, the value of (x*=3) is the same as (x*3). We support that here. 509 # However, we don't support the change in the value of x. 510 if p[2] == '=': 511 p[0] = p[3] 512 else: 513 name, op, format = assign_ops_dict[p[2]] 514 p[0] = expressions.BinaryExpressionNode(name, op, format, (True, True), 515 p[1], p[3]) 516 517 518def p_assignment_operator(p): 519 '''assignment_operator : '=' 520 | MUL_ASSIGN 521 | DIV_ASSIGN 522 | MOD_ASSIGN 523 | ADD_ASSIGN 524 | SUB_ASSIGN 525 | LEFT_ASSIGN 526 | RIGHT_ASSIGN 527 | AND_ASSIGN 528 | XOR_ASSIGN 529 | OR_ASSIGN 530 ''' 531 p[0] = p[1] 532 533 534def p_expression(p): 535 '''expression : assignment_expression 536 | expression ',' assignment_expression 537 ''' 538 p[0] = p[1] 539 # We don't need to support sequence expressions... 540 541 542def p_constant_expression(p): 543 '''constant_expression : conditional_expression 544 ''' 545 p[0] = p[1] 546 547 548def p_declaration(p): 549 '''declaration : declaration_impl ';' 550 ''' 551 # The ';' must be here, not in 'declaration', as declaration needs to 552 # be executed before the ';' is shifted (otherwise the next lookahead will 553 # be read, which may be affected by this declaration if its a typedef. 554 555 556def p_declaration_impl(p): 557 '''declaration_impl : declaration_specifiers 558 | declaration_specifiers init_declarator_list 559 ''' 560 declaration = cdeclarations.Declaration() 561 cdeclarations.apply_specifiers(p[1], declaration) 562 563 if len(p) == 2: 564 filename = p.slice[1].filename 565 lineno = p.slice[1].lineno 566 p.parser.cparser.impl_handle_declaration(declaration, filename, lineno) 567 return 568 569 filename = p.slice[2].filename 570 lineno = p.slice[2].lineno 571 for declarator in p[2]: 572 declaration.declarator = declarator 573 p.parser.cparser.impl_handle_declaration(declaration, filename, lineno) 574 575# shift/reduce conflict with p_statement_error. 576# def p_declaration_error(p): 577# '''declaration : error ';' 578# ''' 579# # Error resynchronisation catch-all 580 581 582def p_declaration_specifiers(p): 583 '''declaration_specifiers : storage_class_specifier 584 | storage_class_specifier declaration_specifiers 585 | type_specifier 586 | type_specifier declaration_specifiers 587 | type_qualifier 588 | type_qualifier declaration_specifiers 589 ''' 590 if len(p) > 2: 591 p[0] = (p[1],) + p[2] 592 else: 593 p[0] = (p[1],) 594 595 596def p_init_declarator_list(p): 597 '''init_declarator_list : init_declarator 598 | init_declarator_list ',' init_declarator 599 ''' 600 if len(p) > 2: 601 p[0] = p[1] + (p[3],) 602 else: 603 p[0] = (p[1],) 604 605 606def p_init_declarator(p): 607 '''init_declarator : declarator 608 | declarator '=' initializer 609 ''' 610 p[0] = p[1] 611 if len(p) > 2: 612 p[0].initializer = p[2] 613 614 615def p_storage_class_specifier(p): 616 '''storage_class_specifier : TYPEDEF 617 | EXTERN 618 | STATIC 619 | AUTO 620 | REGISTER 621 ''' 622 p[0] = cdeclarations.StorageClassSpecifier(p[1]) 623 624 625def p_type_specifier(p): 626 '''type_specifier : VOID 627 | _BOOL 628 | CHAR 629 | SHORT 630 | INT 631 | LONG 632 | FLOAT 633 | DOUBLE 634 | SIGNED 635 | UNSIGNED 636 | struct_or_union_specifier 637 | enum_specifier 638 | TYPE_NAME 639 ''' 640 if type(p[1]) in (cdeclarations.StructTypeSpecifier, 641 cdeclarations.EnumSpecifier): 642 p[0] = p[1] 643 else: 644 p[0] = cdeclarations.TypeSpecifier(p[1]) 645 646 647class Attribs(dict): 648 def __init__(self, packed=False, aligned=False, transparent_union=False): 649 super(Attribs, self).__init__( 650 packed=packed, aligned=aligned, transparent_union=transparent_union, 651 ) 652 self.__dict__ = self 653 654 655def p_struct_or_union_specifier(p): 656 '''struct_or_union_specifier : struct_or_union gcc_attribs IDENTIFIER '{' struct_declaration_list '}' 657 | struct_or_union gcc_attribs TYPE_NAME '{' struct_declaration_list '}' 658 | struct_or_union gcc_attribs '{' struct_declaration_list '}' 659 | struct_or_union IDENTIFIER '{' struct_declaration_list '}' 660 | struct_or_union TYPE_NAME '{' struct_declaration_list '}' 661 | struct_or_union '{' struct_declaration_list '}' 662 | struct_or_union IDENTIFIER 663 | struct_or_union TYPE_NAME 664 ''' 665 # The TYPE_NAME ones are dodgy, needed for Apple headers 666 # CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Files.h. 667 # CoreServices.framework/Frameworks/OSServices.framework/Headers/Power.h 668 packed = False 669 if len(p) == 3: # struct <id/typname> 670 p[0] = cdeclarations.StructTypeSpecifier(p[1], False, p[2], None) 671 else: 672 if type(p[2]) is Attribs: 673 attribs = p[2] 674 if p[3] == '{': 675 tag, decl = '', p[4] 676 else: 677 tag, decl = p[3], p[5] 678 else: 679 attribs = Attribs() 680 if p[2] == '{': 681 tag, decl = '', p[3] 682 else: 683 tag, decl = p[2], p[4] 684 685 p[0] = cdeclarations.StructTypeSpecifier(p[1], attribs.packed, tag, decl) 686 687 p[0].filename = p.slice[0].filename 688 p[0].lineno = p.slice[0].lineno 689 690 691def p_struct_or_union(p): 692 '''struct_or_union : STRUCT 693 | UNION 694 ''' 695 p[0] = p[1] == 'union' 696 697 698def p_gcc_attribs(p): 699 '''gcc_attribs : __ATTRIBUTE__ '(' '(' struct_attribute ')' ')' 700 ''' 701 p[0] = Attribs() 702 p[0].packed = False if len(p) == 1 else p[4] == 'packed' 703 704 705def p_struct_attribute(p): 706 '''struct_attribute : PACKED 707 | TRANSPARENT_UNION 708 | ALIGNED 709 ''' 710 p[0] = p[1] 711 712 713def p_struct_declaration_list(p): 714 '''struct_declaration_list : struct_declaration 715 | struct_declaration_list struct_declaration 716 ''' 717 if len(p) == 2: 718 p[0] = p[1] 719 else: 720 p[0] = p[1] + p[2] 721 722 723def p_struct_declaration(p): 724 '''struct_declaration : specifier_qualifier_list struct_declarator_list ';' 725 | specifier_qualifier_list ';' 726 ''' 727 # p[0] returned is a tuple, to handle multiple declarators in one 728 # declaration. 729 r = () 730 if len(p) >= 4: 731 for declarator in p[2]: 732 declaration = cdeclarations.Declaration() 733 cdeclarations.apply_specifiers(p[1], declaration) 734 declaration.declarator = declarator 735 r += (declaration,) 736 else: 737 # anonymous field (C11/GCC extension) 738 declaration = cdeclarations.Declaration() 739 cdeclarations.apply_specifiers(p[1], declaration) 740 r = (declaration,) 741 p[0] = r 742 743 744def p_specifier_qualifier_list(p): 745 '''specifier_qualifier_list : type_specifier specifier_qualifier_list 746 | type_specifier 747 | type_qualifier specifier_qualifier_list 748 | type_qualifier 749 ''' 750 # Interesting.. why is this one right-recursion? 751 if len(p) == 3: 752 p[0] = (p[1],) + p[2] 753 else: 754 p[0] = (p[1],) 755 756 757def p_struct_declarator_list(p): 758 '''struct_declarator_list : struct_declarator 759 | struct_declarator_list ',' struct_declarator 760 ''' 761 if len(p) == 2: 762 p[0] = (p[1],) 763 else: 764 p[0] = p[1] + (p[3],) 765 766 767def p_struct_declarator(p): 768 '''struct_declarator : declarator 769 | ':' constant_expression 770 | declarator ':' constant_expression 771 ''' 772 if p[1] == ':': 773 p[0] = cdeclarations.Declarator() 774 else: 775 p[0] = p[1] 776 # Bitfield support 777 if len(p) == 4: 778 p[0].bitfield = p[3] 779 780 781def p_enum_specifier(p): 782 '''enum_specifier : ENUM '{' enumerator_list '}' 783 | ENUM IDENTIFIER '{' enumerator_list '}' 784 | ENUM IDENTIFIER 785 ''' 786 if len(p) == 5: 787 p[0] = cdeclarations.EnumSpecifier(None, p[3]) 788 elif len(p) == 6: 789 p[0] = cdeclarations.EnumSpecifier(p[2], p[4]) 790 else: 791 p[0] = cdeclarations.EnumSpecifier(p[2], ()) 792 793 p[0].filename = p.slice[0].filename 794 p[0].lineno = p.slice[0].lineno 795 796 797def p_enumerator_list(p): 798 '''enumerator_list : enumerator_list_iso 799 | enumerator_list_iso ',' 800 ''' 801 # Apple headers sometimes have trailing ',' after enumerants, which is 802 # not ISO C. 803 p[0] = p[1] 804 805 806def p_enumerator_list_iso(p): 807 '''enumerator_list_iso : enumerator 808 | enumerator_list_iso ',' enumerator 809 ''' 810 if len(p) == 2: 811 p[0] = (p[1],) 812 else: 813 p[0] = p[1] + (p[3],) 814 815 816def p_enumerator(p): 817 '''enumerator : IDENTIFIER 818 | IDENTIFIER '=' constant_expression 819 ''' 820 if len(p) == 2: 821 p[0] = cdeclarations.Enumerator(p[1], None) 822 else: 823 p[0] = cdeclarations.Enumerator(p[1], p[3]) 824 825 826def p_type_qualifier(p): 827 '''type_qualifier : CONST 828 | VOLATILE 829 ''' 830 p[0] = cdeclarations.TypeQualifier(p[1]) 831 832 833def p_declarator(p): 834 '''declarator : pointer direct_declarator 835 | direct_declarator 836 ''' 837 if len(p) > 2: 838 p[0] = p[1] 839 ptr = p[1] 840 while ptr.pointer: 841 ptr = ptr.pointer 842 ptr.pointer = p[2] 843 else: 844 p[0] = p[1] 845 846 847def p_direct_declarator(p): 848 '''direct_declarator : IDENTIFIER 849 | '(' declarator ')' 850 | direct_declarator '[' constant_expression ']' 851 | direct_declarator '[' ']' 852 | direct_declarator '(' parameter_type_list ')' 853 | direct_declarator '(' identifier_list ')' 854 | direct_declarator '(' ')' 855 ''' 856 if isinstance(p[1], cdeclarations.Declarator): 857 p[0] = p[1] 858 if p[2] == '[': 859 a = cdeclarations.Array() 860 a.array = p[0].array 861 p[0].array = a 862 if p[3] != ']': 863 a.size = p[3] 864 else: 865 if p[3] == ')': 866 p[0].parameters = () 867 else: 868 p[0].parameters = p[3] 869 elif p[1] == '(': 870 p[0] = p[2] 871 else: 872 p[0] = cdeclarations.Declarator() 873 p[0].identifier = p[1] 874 875 # Check parameters for (void) and simplify to empty tuple. 876 if p[0].parameters and len(p[0].parameters) == 1: 877 param = p[0].parameters[0] 878 if param.type.specifiers == ['void'] and not param.declarator: 879 p[0].parameters = () 880 881 882def p_pointer(p): 883 '''pointer : '*' 884 | '*' type_qualifier_list 885 | '*' pointer 886 | '*' type_qualifier_list pointer 887 ''' 888 if len(p) == 2: 889 p[0] = cdeclarations.Pointer() 890 elif len(p) == 3: 891 if isinstance(p[2], cdeclarations.Pointer): 892 p[0] = cdeclarations.Pointer() 893 p[0].pointer = p[2] 894 else: 895 p[0] = cdeclarations.Pointer() 896 p[0].qualifiers = p[2] 897 else: 898 p[0] = cdeclarations.Pointer() 899 p[0].qualifiers = p[2] 900 p[0].pointer = p[3] 901 902 903def p_type_qualifier_list(p): 904 '''type_qualifier_list : type_qualifier 905 | type_qualifier_list type_qualifier 906 ''' 907 if len(p) > 2: 908 p[0] = p[1] + (p[2],) 909 else: 910 p[0] = (p[1],) 911 912 913def p_parameter_type_list(p): 914 '''parameter_type_list : parameter_list 915 | parameter_list ',' ELLIPSIS 916 ''' 917 if len(p) > 2: 918 p[0] = p[1] + (p[3],) 919 else: 920 p[0] = p[1] 921 922 923def p_parameter_list(p): 924 '''parameter_list : parameter_declaration 925 | parameter_list ',' parameter_declaration 926 ''' 927 if len(p) > 2: 928 p[0] = p[1] + (p[3],) 929 else: 930 p[0] = (p[1],) 931 932 933def p_parameter_declaration(p): 934 '''parameter_declaration : declaration_specifiers declarator 935 | declaration_specifiers abstract_declarator 936 | declaration_specifiers 937 ''' 938 p[0] = cdeclarations.Parameter() 939 cdeclarations.apply_specifiers(p[1], p[0]) 940 if len(p) > 2: 941 p[0].declarator = p[2] 942 943 944def p_identifier_list(p): 945 '''identifier_list : IDENTIFIER 946 | identifier_list ',' IDENTIFIER 947 ''' 948 param = cdeclarations.Parameter() 949 param.declarator = cdeclarations.Declarator() 950 if len(p) > 2: 951 param.declarator.identifier = p[3] 952 p[0] = p[1] + (param,) 953 else: 954 param.declarator.identifier = p[1] 955 p[0] = (param,) 956 957 958def p_type_name(p): 959 '''type_name : specifier_qualifier_list 960 | specifier_qualifier_list abstract_declarator 961 ''' 962 typ = p[1] 963 if len(p) == 3: 964 declarator = p[2] 965 else: 966 declarator = None 967 968 declaration = cdeclarations.Declaration() 969 declaration.declarator = declarator 970 cdeclarations.apply_specifiers(typ, declaration) 971 ctype = p.parser.cparser.get_ctypes_type(declaration.type, 972 declaration.declarator) 973 p[0] = ctype 974 975 976def p_abstract_declarator(p): 977 '''abstract_declarator : pointer 978 | direct_abstract_declarator 979 | pointer direct_abstract_declarator 980 ''' 981 if len(p) == 2: 982 p[0] = p[1] 983 if isinstance(p[0], cdeclarations.Pointer): 984 ptr = p[0] 985 while ptr.pointer: 986 ptr = ptr.pointer 987 # Only if doesn't already terminate in a declarator 988 if isinstance(ptr, cdeclarations.Pointer): 989 ptr.pointer = cdeclarations.Declarator() 990 else: 991 p[0] = p[1] 992 ptr = p[0] 993 while ptr.pointer: 994 ptr = ptr.pointer 995 ptr.pointer = p[2] 996 997 998def p_direct_abstract_declarator(p): 999 '''direct_abstract_declarator : '(' abstract_declarator ')' 1000 | '[' ']' 1001 | '[' constant_expression ']' 1002 | direct_abstract_declarator '[' ']' 1003 | direct_abstract_declarator '[' constant_expression ']' 1004 | '(' ')' 1005 | '(' parameter_type_list ')' 1006 | direct_abstract_declarator '(' ')' 1007 | direct_abstract_declarator '(' parameter_type_list ')' 1008 ''' 1009 if p[1] == '(' and isinstance(p[2], cdeclarations.Declarator): 1010 p[0] = p[2] 1011 else: 1012 if isinstance(p[1], cdeclarations.Declarator): 1013 p[0] = p[1] 1014 if p[2] == '[': 1015 a = cdeclarations.Array() 1016 a.array = p[0].array 1017 p[0].array = a 1018 if p[3] != ']': 1019 p[0].array.size = p[3] 1020 elif p[2] == '(': 1021 if p[3] == ')': 1022 p[0].parameters = () 1023 else: 1024 p[0].parameters = p[3] 1025 else: 1026 p[0] = cdeclarations.Declarator() 1027 if p[1] == '[': 1028 p[0].array = cdeclarations.Array() 1029 if p[2] != ']': 1030 p[0].array.size = p[2] 1031 elif p[1] == '(': 1032 if p[2] == ')': 1033 p[0].parameters = () 1034 else: 1035 p[0].parameters = p[2] 1036 1037 # Check parameters for (void) and simplify to empty tuple. 1038 if p[0].parameters and len(p[0].parameters) == 1: 1039 param = p[0].parameters[0] 1040 if param.type.specifiers == ['void'] and not param.declarator: 1041 p[0].parameters = () 1042 1043 1044def p_initializer(p): 1045 '''initializer : assignment_expression 1046 | '{' initializer_list '}' 1047 | '{' initializer_list ',' '}' 1048 ''' 1049 1050 1051def p_initializer_list(p): 1052 '''initializer_list : initializer 1053 | initializer_list ',' initializer 1054 ''' 1055 1056 1057def p_statement(p): 1058 '''statement : labeled_statement 1059 | compound_statement 1060 | expression_statement 1061 | selection_statement 1062 | iteration_statement 1063 | jump_statement 1064 ''' 1065 1066 1067def p_labeled_statement(p): 1068 '''labeled_statement : IDENTIFIER ':' statement 1069 | CASE constant_expression ':' statement 1070 | DEFAULT ':' statement 1071 ''' 1072 1073 1074def p_compound_statement(p): 1075 '''compound_statement : '{' '}' 1076 | '{' statement_list '}' 1077 | '{' declaration_list '}' 1078 | '{' declaration_list statement_list '}' 1079 ''' 1080 1081 1082def p_compound_statement_error(p): 1083 '''compound_statement : '{' error '}' 1084 ''' 1085 # Error resynchronisation catch-all 1086 1087 1088def p_declaration_list(p): 1089 '''declaration_list : declaration 1090 | declaration_list declaration 1091 ''' 1092 1093 1094def p_statement_list(p): 1095 '''statement_list : statement 1096 | statement_list statement 1097 ''' 1098 1099 1100def p_expression_statement(p): 1101 '''expression_statement : ';' 1102 | expression ';' 1103 ''' 1104 1105 1106def p_expression_statement_error(p): 1107 '''expression_statement : error ';' 1108 ''' 1109 # Error resynchronisation catch-all 1110 1111 1112def p_selection_statement(p): 1113 '''selection_statement : IF '(' expression ')' statement 1114 | IF '(' expression ')' statement ELSE statement 1115 | SWITCH '(' expression ')' statement 1116 ''' 1117 1118 1119def p_iteration_statement(p): 1120 '''iteration_statement : WHILE '(' expression ')' statement 1121 | DO statement WHILE '(' expression ')' ';' 1122 | FOR '(' expression_statement expression_statement ')' statement 1123 | FOR '(' expression_statement expression_statement expression ')' statement 1124 ''' 1125 1126 1127def p_jump_statement(p): 1128 '''jump_statement : GOTO IDENTIFIER ';' 1129 | CONTINUE ';' 1130 | BREAK ';' 1131 | RETURN ';' 1132 | RETURN expression ';' 1133 ''' 1134 1135 1136def p_external_declaration(p): 1137 '''external_declaration : declaration 1138 | function_definition 1139 ''' 1140 1141 # Intentionally empty 1142 1143 1144def p_function_definition(p): 1145 '''function_definition : declaration_specifiers declarator declaration_list compound_statement 1146 | declaration_specifiers declarator compound_statement 1147 | declarator declaration_list compound_statement 1148 | declarator compound_statement 1149 ''' 1150 1151 1152def p_define(p): 1153 '''define : PP_DEFINE PP_DEFINE_NAME PP_END_DEFINE 1154 | PP_DEFINE PP_DEFINE_NAME type_name PP_END_DEFINE 1155 | PP_DEFINE PP_DEFINE_NAME constant_expression PP_END_DEFINE 1156 | PP_DEFINE PP_DEFINE_MACRO_NAME '(' ')' PP_END_DEFINE 1157 | PP_DEFINE PP_DEFINE_MACRO_NAME '(' ')' constant_expression PP_END_DEFINE 1158 | PP_DEFINE PP_DEFINE_MACRO_NAME '(' macro_parameter_list ')' PP_END_DEFINE 1159 | PP_DEFINE PP_DEFINE_MACRO_NAME '(' macro_parameter_list ')' constant_expression PP_END_DEFINE 1160 ''' 1161 1162 filename = p.slice[1].filename 1163 lineno = p.slice[1].lineno 1164 1165 if p[3] != '(': 1166 if len(p) == 4: 1167 p.parser.cparser.handle_define_constant(p[2], None, filename, 1168 lineno) 1169 else: 1170 p.parser.cparser.handle_define_constant(p[2], p[3], filename, 1171 lineno) 1172 else: 1173 if p[4] == ')': 1174 params = [] 1175 if len(p) == 6: 1176 expr = None 1177 elif len(p) == 7: 1178 expr = p[5] 1179 else: 1180 params = p[4] 1181 if len(p) == 7: 1182 expr = None 1183 elif len(p) == 8: 1184 expr = p[6] 1185 1186 filename = p.slice[1].filename 1187 lineno = p.slice[1].lineno 1188 1189 p.parser.cparser.handle_define_macro(p[2], params, expr, filename, lineno) 1190 1191 1192def p_define_error(p): 1193 '''define : PP_DEFINE error PP_END_DEFINE''' 1194 lexer = p[2].lexer 1195 clexdata = lexer.tokens 1196 start = end = p[2].clexpos 1197 while clexdata[start].type != 'PP_DEFINE': 1198 start -= 1 1199 while clexdata[end].type != 'PP_END_DEFINE': 1200 end += 1 1201 1202 name = clexdata[start + 1].value 1203 if clexdata[start + 1].type == 'PP_DEFINE_NAME': 1204 params = None 1205 contents = [t.value for t in clexdata[start + 2:end]] 1206 else: 1207 end_of_param_list = start 1208 while clexdata[end_of_param_list].value != ')' and \ 1209 end_of_param_list < end: 1210 end_of_param_list += 1 1211 params = [t.value for t in clexdata[start + 3:end_of_param_list] if 1212 t.value != ','] 1213 contents = [t.value for t in clexdata[end_of_param_list + 1:end]] 1214 1215 filename = p.slice[1].filename 1216 lineno = p.slice[1].lineno 1217 1218 p[2].lexer.cparser.handle_define_unparseable(name, params, contents, 1219 filename, lineno) 1220 1221 1222def p_macro_parameter_list(p): 1223 '''macro_parameter_list : PP_MACRO_PARAM 1224 | macro_parameter_list ',' PP_MACRO_PARAM 1225 ''' 1226 if len(p) == 2: 1227 p[0] = [p[1]] 1228 else: 1229 p[1].append(p[3]) 1230 p[0] = p[1] 1231 1232 1233def p_error(t): 1234 if t.lexer.in_define: 1235 # p_define_error will generate an error message. 1236 pass 1237 else: 1238 if t.type == '$end': 1239 t.parser.cparser.handle_error('Syntax error at end of file.', 1240 t.filename, 0) 1241 else: 1242 t.lexer.cparser.handle_error('Syntax error at %r' % t.value, 1243 t.filename, t.lineno) 1244 # Don't alter lexer: default behaviour is to pass error production 1245 # up until it hits the catch-all at declaration, at which point 1246 # parsing continues (synchronisation). 1247