Beispiel #1
0
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
Beispiel #2
0
    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)
Beispiel #3
0
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)
Beispiel #4
0
    def binaries(body, symbol_table):
        symbol_table = push(symbol_table)
        symbol_table['__ stack __'] = Stack()  # Each function call has its own Frame which is nothing more than a stack

        # Skip return address ...
        offset = size_arrays_as_pointers(void_pointer_type) + (
            # if function has zero return size then the return pointer will be omitted ...
            size_arrays_as_pointers(void_pointer_type) *
            bool(size_arrays_as_pointers(c_type(c_type(dec)), overrides={VoidType: 0}))
        )

        for parameter in c_type(dec):
            # monkey patch declarator objects add Load commands according to stack state; add to symbol table.
            symbol_table[name(parameter)] = bind_instructions(parameter, offset)
            assert not type(parameter) is ArrayType  # TODO: fix this.
            offset += size_arrays_as_pointers(c_type(parameter))

        symbol_table.update(
            izip(('__ CURRENT FUNCTION __', '__ LABELS __', '__ GOTOS __'), (dec, SymbolTable(), defaultdict(list)))
        )

        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)

        return chain(   # body of function ...
            chain.from_iterable(imap(symbol_table['__ statement __'], chain.from_iterable(body), repeat(symbol_table))),
            return_instrs(loc(dec)),        # default return instructions, in case one was not giving ...
            pop_symbol_table(symbol_table)  # pop symbol_table once complete ...
        )
Beispiel #5
0
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)
Beispiel #6
0
def switch(tokens, symbol_table):
    def _pop_symbol_table(symbol_table):  # Pop symbol table once we have gone through the whole body ...
        _ = pop(symbol_table)
        yield EmptyStatement()
    expression, statement = imap(symbol_table.__getitem__, ('__ expression __', '__ statement __'))
    location, _ = loc(consume(tokens)), error_if_not_value(tokens, TOKENS.LEFT_PARENTHESIS)
    expr, _ = expression(tokens, symbol_table), error_if_not_value(tokens, TOKENS.RIGHT_PARENTHESIS)
    symbol_table = push(symbol_table)
    symbol_table['__ SWITCH STATEMENT __'] = SymbolTable()  # Add dict to track cases, emit error on duplicates.
    symbol_table['__ SWITCH EXPRESSION __'] = expr
    yield SwitchStatement(expr, chain(statement(tokens, symbol_table), _pop_symbol_table(symbol_table)), location)
Beispiel #7
0
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 ...
Beispiel #8
0
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)
Beispiel #9
0
    def binaries(body, symbol_table):
        symbol_table = push(symbol_table)
        symbol_table['__ stack __'] = Stack(
        )  # Each function call has its own Frame which is nothing more than a stack

        # Skip return address ...
        offset = size_arrays_as_pointers(void_pointer_type) + (
            # if function has zero return size then the return pointer will be omitted ...
            size_arrays_as_pointers(void_pointer_type) * bool(
                size_arrays_as_pointers(c_type(c_type(dec)),
                                        overrides={VoidType: 0})))

        for parameter in c_type(dec):
            # monkey patch declarator objects add Load commands according to stack state; add to symbol table.
            symbol_table[name(parameter)] = bind_instructions(
                parameter, offset)
            assert not type(parameter) is ArrayType  # TODO: fix this.
            offset += size_arrays_as_pointers(c_type(parameter))

        symbol_table.update(
            izip(('__ CURRENT FUNCTION __', '__ LABELS __', '__ GOTOS __'),
                 (dec, SymbolTable(), defaultdict(list))))

        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)

        return chain(  # body of function ...
            chain.from_iterable(
                imap(symbol_table['__ statement __'],
                     chain.from_iterable(body), repeat(symbol_table))),
            return_instrs(
                loc(dec)
            ),  # default return instructions, in case one was not giving ...
            pop_symbol_table(
                symbol_table)  # pop symbol_table once complete ...
        )
Beispiel #10
0
    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)
Beispiel #11
0
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)
Beispiel #12
0
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)