def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start,), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), ) ) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset(start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8*size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def compound_statement(tokens, symbol_table): #: '{' statement* '}' _, symbol_table = error_if_not_value(tokens, TOKENS.LEFT_BRACE), push(symbol_table) statement = symbol_table['__ statement __'] while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: yield statement(tokens, symbol_table) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) and pop(symbol_table)
def type_name_or_unary_expression(tokens, symbol_table): symbol_table = push(symbol_table) set_rules(type_name_or_postfix_expression, rules(symbol_table['__ postfix_expression __'])) symbol_table['__ postfix_expression __'] = type_name_or_postfix_expression unary_exp = symbol_table['__ unary_expression __'](tokens, symbol_table) _ = pop(symbol_table) return unary_exp
def loop_body(body, symbol_table, continue_instr, break_instr): symbol_table = push(symbol_table) statement, stack = imap(symbol_table.__getitem__, ('__ statement __', '__ stack __')) symbol_table['__ continue __'] = (continue_instr, stack.stack_pointer) symbol_table['__ break __'] = (break_instr, stack.stack_pointer) for instr in statement(body, symbol_table): yield instr _ = pop(symbol_table)
def type_name_or_postfix_expression(tokens, symbol_table): symbol_table = push(symbol_table) symbol_table['__ compound_literal __'] = type_name_or_compound_literal primary_exp = symbol_table['__ primary_expression __'](tokens, symbol_table) _ = pop(symbol_table) # pop 'type_name_or_compound_literal' and type_name_or_postfix_expression ... postfix_expression_rules = rules(symbol_table['__ postfix_expression __']) if not isinstance(primary_exp, CType): # it must have being an expression ... while peek_or_terminal(tokens) in postfix_expression_rules: primary_exp = postfix_expression_rules[peek(tokens)](tokens, symbol_table, primary_exp) return primary_exp # otherwise it must have being a type_name ...
def declarations(tokens, symbol_table): # storage_class_specifier? type_name? init_declarator_list (';' or compound_statement) # declaration storage_class_specifier, specifier_qualifier_list, statement = imap( symbol_table.__getitem__, ('__ storage_class_specifier __', '__ specifier_qualifier_list __', '__ statement __')) storage_class = storage_class_specifier(tokens, symbol_table) base_type = specifier_qualifier_list(tokens, symbol_table) expecting_token = TOKENS.SEMICOLON if peek_or_terminal(tokens) == TOKENS.SEMICOLON: yield EmptyDeclaration(loc(consume(tokens)), storage_class) elif peek_or_terminal(tokens) is terminal: raise_error( '{l} Expected TOKENS.COMMA TOKENS.EQUAL TOKENS.SEMICOLON TOKENS.LEFT_BRACE got `{got}`' .format(l=loc(peek(tokens, EOFLocation)), got=peek(tokens, ''))) else: for dec in init_declarator_list(tokens, symbol_table, base_type=base_type, storage_class=storage_class): dec.storage_class = storage_class if isinstance( storage_class, TypeDef ): # init_declarator_list adds the symbol as a decl to symbol_table symbol_table[name(dec)] = (symbol_table.pop( name(dec)) or 1) and c_type(dec) # replace dec by ctype elif peek_or_terminal( tokens) == TOKENS.LEFT_BRACE and not error_if_not_type( c_type(dec), FunctionType): symbol_table = push(symbol_table) symbol_table.update( chain( imap( lambda a: ( name(a), a ), # add non variable list parameters to the symbol table ... ifilterfalse( lambda c: isinstance(c_type(c), VAListType), c_type(dec))), (('__ RETURN_TYPE __', c_type(c_type(dec))), ('__ LABELS __', SymbolTable())))) yield FunctionDefinition(dec, next(statement(tokens, symbol_table))) expecting_token = (pop(symbol_table) or 1) and '' else: yield dec expecting_token = TOKENS.SEMICOLON _ = expecting_token and error_if_not_value(tokens, expecting_token)
def body(stmnt, symbol_table, end_switch): symbol_table = push(symbol_table) stack, statement = imap(symbol_table.__getitem__, ('__ stack __', '__ statement __')) symbol_table['__ break __'] = (end_switch, stack.stack_pointer) symbol_table['__ switch __'] = True allocation_table = [ ] # create an allocation table to update stack before jump in case of nested definitions switch_body_instrs = [] cases = {'default': Offset(end_switch, loc(stmnt))} for instr in statement(stmnt.statement, symbol_table): if isinstance(getattr(instr, 'case', None), CaseStatement): start = Pass(loc(instr)) allocation_table.append( chain( (start, ), update_stack(stmnt.stack.stack_pointer, instr.case.stack.stack_pointer, loc(instr)), relative_jump(Offset(instr, loc(instr)), loc(instr)), )) cases[error_if_not_type(exp(exp(instr.case)), (int, long, str))] = Offset( start, loc(instr)) del instr.case switch_body_instrs.append(instr) max_switch_value = 2**(8 * size_arrays_as_pointers(c_type(exp(stmnt)))) - 1 for instr in jump_table(loc(stmnt), cases, allocation_table, max_switch_value, switch_body_instrs): yield instr _ = pop(symbol_table)
def declarations(tokens, symbol_table): # storage_class_specifier? type_name? init_declarator_list (';' or compound_statement) # declaration storage_class_specifier, specifier_qualifier_list, statement = imap( symbol_table.__getitem__, ('__ storage_class_specifier __', '__ specifier_qualifier_list __', '__ statement __') ) storage_class = storage_class_specifier(tokens, symbol_table) base_type = specifier_qualifier_list(tokens, symbol_table) expecting_token = TOKENS.SEMICOLON if peek_or_terminal(tokens) == TOKENS.SEMICOLON: yield EmptyDeclaration(loc(consume(tokens)), storage_class) elif peek_or_terminal(tokens) is terminal: raise_error('{l} Expected TOKENS.COMMA TOKENS.EQUAL TOKENS.SEMICOLON TOKENS.LEFT_BRACE got `{got}`'.format( l=loc(peek(tokens, EOFLocation)), got=peek(tokens, '') )) else: for dec in init_declarator_list(tokens, symbol_table, base_type=base_type, storage_class=storage_class): dec.storage_class = storage_class if isinstance(storage_class, TypeDef): # init_declarator_list adds the symbol as a decl to symbol_table symbol_table[name(dec)] = (symbol_table.pop(name(dec)) or 1) and c_type(dec) # replace dec by ctype elif peek_or_terminal(tokens) == TOKENS.LEFT_BRACE and not error_if_not_type(c_type(dec), FunctionType): symbol_table = push(symbol_table) symbol_table.update(chain( imap( lambda a: (name(a), a), # add non variable list parameters to the symbol table ... ifilterfalse(lambda c: isinstance(c_type(c), VAListType), c_type(dec)) ), (('__ RETURN_TYPE __', c_type(c_type(dec))), ('__ LABELS __', SymbolTable())) )) yield FunctionDefinition(dec, next(statement(tokens, symbol_table))) expecting_token = (pop(symbol_table) or 1) and '' else: yield dec expecting_token = TOKENS.SEMICOLON _ = expecting_token and error_if_not_value(tokens, expecting_token)
def _pop_symbol_table(symbol_table): # Pop symbol table once we have gone through the whole body ... _ = pop(symbol_table) yield EmptyStatement()
def pop_symbol_table(symbol_table, location=loc( dec)): # pop symbol table once all binaries have being emitted yield (pop(symbol_table) or 1) and Pass(location)
def pop_macros(macros): yield (pop(macros) or 1) and empty_token
def pop_symbol_table(symbol_table, location=loc(dec)): # pop symbol table once all binaries have being emitted yield (pop(symbol_table) or 1) and Pass(location)