Esempio n. 1
0
def p_term(p):
    """
    term : ASTERISK term %prec DE_REF
        | AMPERSAND ID %prec ADDR_OF
        | ID

    """
    global global_symbol_table, symbol_table_stack
    if len(p) == 2:
        try:
            _id = p[1]
            sym = access_variable_symbol(_id, global_symbol_table,
                                         symbol_table_stack)
            p[0] = ASTNode('VAR', _id), sym.type, sym.deref_depth
        except KeyError:
            panic('Symbol accessed without declaration')
    elif len(p) == 3:
        if p[1] == '*':
            child_ast_node, _type, deref_depth = p[2]
            if deref_depth == 0:
                panic('Symbol de-referenced too many times')
            node = ASTNode('DEREF', '*%s' % child_ast_node.value)
            node.append_child(child_ast_node)
            p[0] = node, _type, deref_depth - 1
        elif p[1] == '&':
            try:
                _id = p[2]
                sym = access_variable_symbol(_id, global_symbol_table,
                                             symbol_table_stack)
                node = ASTNode('ADDR', '&%s' % _id)
                id_node = ASTNode('VAR', _id)
                node.append_child(id_node)
                p[0] = node, sym.type, sym.deref_depth + 1
            except KeyError:
                panic('Symbol accessed without declaration')
Esempio n. 2
0
def p_return_statement(p):
    """
    return_statement : RETURN expression SEMICOLON
                | RETURN SEMICOLON
                |
    """
    global symbol_table_stack, global_symbol_table
    fun = symbol_table_stack[-1]
    fun_type = fun.type
    fun_deref_depth = fun.deref_depth
    if len(p) == 4:
        ast_node, _type, deref_depth = p[2]
        if fun_type != _type or fun_deref_depth != deref_depth:
            panic('Improper return type in function implementation')
        node = ASTNode('RETURN', 'return')
        node.append_child(ast_node)
        p[0] = node, True
    elif len(p) == 3 or len(p) == 1:
        if fun_type != 'void':
            panic('Improper return type in function implementation')
        node = ASTNode('RETURN', 'return')
        if len(p) == 3:
            p[0] = node, True
        elif len(p) == 1:
            p[0] = node, False
Esempio n. 3
0
def p_while_block(p):
    """
    while_block : WHILE L_PAREN compound_condition R_PAREN if_else_while_common_body
    """
    while_block = ASTNode('WHILE', 'while')
    while_block.append_child(p[3])
    while_block.append_child(p[5])
    p[0] = while_block
Esempio n. 4
0
def p_if_block(p):
    """
    if_block : IF L_PAREN compound_condition R_PAREN if_else_while_common_body
                | IF L_PAREN compound_condition R_PAREN if_else_while_common_body ELSE if_block
                | IF L_PAREN compound_condition R_PAREN if_else_while_common_body ELSE if_else_while_common_body
    """
    if_block = ASTNode('IF', 'if')
    if_block.append_child(p[3])
    if_block.append_child(p[5])
    if len(p) == 8:
        if_block.append_child(p[7])
    p[0] = if_block
Esempio n. 5
0
def p_if_else_while_common_body(p):
    """
    if_else_while_common_body : SEMICOLON
                | assignment SEMICOLON
                | L_CURLY body R_CURLY
    """
    if len(p) == 2:
        p[0] = ASTNode('BODY', 'body')
    elif len(p) == 3:
        body = ASTNode('BODY', 'body')
        body.append_child(p[1])
        p[0] = body
    elif len(p) == 4:
        p[0] = p[2]
Esempio n. 6
0
def p_compound_condition(p):
    """
    compound_condition : compound_condition LOGICAL_AND compound_condition
                       | compound_condition LOGICAL_OR compound_condition
                       | L_PAREN compound_condition R_PAREN
                       | EXCLAMATION L_PAREN compound_condition R_PAREN
                       | EXCLAMATION condition
                       | condition
    """
    if len(p) == 4:
        if p[2] == '&&':
            node = ASTNode('AND', '&&', p[1].is_constant and p[3].is_constant)
            node.append_child(p[1])
            node.append_child(p[3])
            p[0] = node
        elif p[2] == '||':
            node = ASTNode('OR', '||', p[1].is_constant and p[3].is_constant)
            node.append_child(p[1])
            node.append_child(p[3])
            p[0] = node
        elif p[1] == '(' and p[3] == ')':
            p[0] = p[2]
    elif len(p) == 3:
        node = ASTNode('NOT', '!', p[2][0].is_constant)
        node.append_child(p[2][0])
        p[0] = node
    elif len(p) == 5:
        node = ASTNode('NOT', '!', p[3].is_constant)
        node.append_child(p[3])
        p[0] = node
    elif len(p) == 2:
        p[0] = p[1][0]
Esempio n. 7
0
def p_function_term_r(p):
    """
    function_term_r : ASTERISK function_term_r
                        | ID
    """
    # p[0] = ast_node, id, deref_depth
    if len(p) == 2:
        _id = p[1]
        p[0] = ASTNode('VAR', _id), _id, 0
    elif len(p) == 3:
        child_ast_node, _id, deref_depth = p[2]
        node = ASTNode('DEREF', '*%s' % child_ast_node.value)
        node.append_child(child_ast_node)
        p[0] = node, _id, deref_depth + 1
Esempio n. 8
0
def p_arg_list_non_empty(p):
    """
    arg_list_non_empty : arg_list_non_empty COMMA expression
                    | expression
    """
    # p[0] := ast_node, [(type, deref_depth, arg_index), ...]
    if len(p) == 2:
        expr_ast_node, _type, deref_depth = p[1]
        node = ASTNode('ARG_LIST', 'arg_list')
        node.append_child(expr_ast_node)
        arg_list = [(_type, deref_depth, 0)]
        p[0] = node, arg_list
    elif len(p) == 4:
        node, arg_list = p[1]
        expr_ast_node, _type, deref_depth = p[3]
        node.append_child(expr_ast_node)
        current_arg = [(_type, deref_depth, len(arg_list))]
        arg_list = arg_list + current_arg
        p[0] = node, arg_list
Esempio n. 9
0
def p_func_expr(p):
    """
    func_expr : ID L_PAREN arg_list R_PAREN
    """
    if len(p) == 5:
        _id = p[1]
        func_symbol = None
        arg_list_ast_node, arg_types = p[3]
        if global_symbol_table.symbol_exists(_id):
            func_symbol = global_symbol_table.get_symbol(_id)
            if func_symbol.is_function():
                param_list = func_symbol.its_child_table.get_param_signature()
                if param_list != arg_types:
                    panic('Function %s arguments are mismatched' % _id)
            else:
                panic('Symbol %s is not a function' % _id)
        else:
            panic('Function called without declaration %s' % _id)
        node = ASTNode('FUNCTION_CALL', 'function_call')
        id_node = ASTNode('VAR', p[1])
        node.append_child(id_node)
        node.append_child(arg_list_ast_node)
        p[0] = node, func_symbol.type, func_symbol.deref_depth
Esempio n. 10
0
def p_assignment(p):
    """
    assignment :  ID EQUALS expression
                | ASTERISK term EQUALS expression %prec DE_REF
    """
    global no_assignments
    no_assignments += 1
    global global_symbol_table, symbol_table_stack
    if len(p) == 4:
        # ID = expr
        expr_ast_node, expr_type, expr_deref_depth = p[3]
        if expr_ast_node.is_constant:
            panic(
                'Constant cannot be assigned directly without de-referencing')
        _id = p[1]
        lhs_symbol = None
        try:
            lhs_symbol = access_variable_symbol(_id, global_symbol_table,
                                                symbol_table_stack)
        except KeyError:
            panic('Symbol %s accessed without declaration' % _id)
        if lhs_symbol.deref_depth == 0:
            panic('Scalar %s cannot be directly assigned' % _id)
        if lhs_symbol.type != expr_type or lhs_symbol.deref_depth != expr_deref_depth:
            panic('Type mismatch while assigning %s' % _id)
        id_node = ASTNode('VAR', _id)
        node = ASTNode('ASGN', '=')
        node.append_child(id_node)
        node.append_child(expr_ast_node)
        p[0] = node
    elif len(p) == 5:
        term_node, term_type, term_deref_depth = p[2]
        expr_ast_node, expr_type, expr_deref_depth = p[4]
        if term_deref_depth <= 0:
            panic('Symbol de-referenced too many times')
        if term_type != expr_type or term_deref_depth - 1 != expr_deref_depth:
            panic('Type mismatch at assignment')
        asterisk_node = ASTNode('DEREF', '*%s' % term_node.value)
        asterisk_node.append_child(term_node)
        node = ASTNode('ASGN', '=')
        node.append_child(asterisk_node)
        node.append_child(expr_ast_node)
        p[0] = node
Esempio n. 11
0
def p_expression_uminus(p):
    """expression : MINUS expression %prec U_MINUS"""
    child_ast_node, _type, deref_depth = p[2]
    node = ASTNode('UMINUS', '-', child_ast_node.is_constant)
    node.append_child(child_ast_node)
    p[0] = node, _type, deref_depth
Esempio n. 12
0
def p_expression_binary_op(p):
    """
    expression : expression PLUS expression
              | expression MINUS expression
              | expression ASTERISK expression
              | expression DIVIDE expression
    """
    left_child_node, left_type, left_deref_depth = p[1]
    right_child_node, right_type, right_deref_depth = p[3]
    if left_type != right_type or left_deref_depth != right_deref_depth:
        panic('Type mismatch for operation %s' % p[2])
    if left_deref_depth != 0:
        panic('Pointer Arthmatic is not allowed')
    if p[2] == '+':
        node = ASTNode(
            'PLUS', '+', left_child_node.is_constant
            and right_child_node.is_constant)
        node.append_child(left_child_node)
        node.append_child(right_child_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '-':
        node = ASTNode(
            'MINUS', '-', left_child_node.is_constant
            and right_child_node.is_constant)
        node.append_child(left_child_node)
        node.append_child(right_child_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '*':
        node = ASTNode(
            'MUL', '*', left_child_node.is_constant
            and right_child_node.is_constant)
        node.append_child(left_child_node)
        node.append_child(right_child_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '/':
        node = ASTNode(
            'DIV', '/', left_child_node.is_constant
            and right_child_node.is_constant)
        node.append_child(left_child_node)
        node.append_child(right_child_node)
        p[0] = node, left_type, left_deref_depth
Esempio n. 13
0
def p_condition(p):
    """
    condition : expression EE expression
                | expression NE expression
                | expression GE expression
                | expression GT expression
                | expression LE expression
                | expression LT expression
    """
    left_ast_node, left_type, left_deref_depth = p[1]
    right_ast_node, right_type, right_deref_depth = p[3]
    if left_type != right_type or left_deref_depth != right_deref_depth:
        panic('Type mismatch at boolean operator %s' % p[2])
    if left_deref_depth != 0:
        panic('Pointer Comparision is not allowed')
    if p[2] == '==':
        node = ASTNode(
            'EQ', '==', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '!=':
        node = ASTNode(
            'NE', '!=', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '>=':
        node = ASTNode(
            'GE', '>=', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '>':
        node = ASTNode(
            'GT', '>', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '<=':
        node = ASTNode(
            'LE', '<=', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
    elif p[2] == '<':
        node = ASTNode(
            'LT', '<', left_ast_node.is_constant
            and right_ast_node.is_constant)
        node.append_child(left_ast_node)
        node.append_child(right_ast_node)
        p[0] = node, left_type, left_deref_depth
Esempio n. 14
0
def p_function_implementation(p):
    """
    function : function_head L_PAREN param_list R_PAREN L_CURLY body return_statement R_CURLY
    """
    global symbol_table_stack
    global global_symbol_table
    current_symbol_table = symbol_table_stack[-1]
    type_node, id_node, _id, _type, deref_depth = p[1]
    param_list_node = p[3]
    body_node = p[6]
    return_node, return_existence = p[7]
    if _id == 'main':
        if len(param_list_node.children) != 0:
            panic('main function cannot have parameters')
        if return_existence:
            panic('main function cannot have return statement')
    if not global_symbol_table.symbol_exists(_id):
        # New function implementation
        symbol = Symbol(_id,
                        _type,
                        Symbol.GLOBAL_SCOPE,
                        deref_depth,
                        its_child_table=current_symbol_table,
                        is_prototype=False)
        global_symbol_table.add_symbol(symbol)
        symbol_table_stack.pop()
    else:
        existing_symbol = global_symbol_table.get_symbol(_id)
        if not existing_symbol.is_function():
            # Existing symbol is not a function
            panic('Function implementation : Symbol already exists')
        else:
            if existing_symbol.is_prototype:
                if existing_symbol.type == _type and existing_symbol.deref_depth == deref_depth:
                    param_symbols1 = current_symbol_table.get_param_signature()
                    param_symbols2 = existing_symbol.its_child_table.get_param_signature(
                    )
                    if param_symbols1 == param_symbols2:
                        symbol = Symbol(_id,
                                        _type,
                                        Symbol.GLOBAL_SCOPE,
                                        deref_depth,
                                        its_child_table=current_symbol_table,
                                        is_prototype=False)
                        prototype_symbol_tables.append(
                            (_id, existing_symbol.its_child_table))
                        global_symbol_table.add_symbol(symbol)
                        symbol_table_stack.pop()
                    else:
                        # Params mismatch
                        panic('Params mismatch in function implementation')
                else:
                    # Return type mismatch
                    panic('Return type mismatch')
            else:
                # Already implemented function
                panic('Multiple function implementation')
    function_node = ASTNode('FUNCTION', _id)
    type_node_val = type_node.value
    for i in range(deref_depth):
        type_node_val = '*' + type_node_val
    type_node.value = type_node_val
    function_node.append_child(type_node)
    function_node.append_child(id_node)
    function_node.append_child(param_list_node)
    function_node.append_child(body_node)
    function_node.append_child(return_node)
    p[0] = function_node