Exemple #1
0
def p_var_list(p):
    '''
    var_list : identifier
             | var_list COMMA identifier
    '''
    if len(p) == 2:
        p[1] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'identifier',
                        'line': p.lineno(1),
                        'terminal': True
                    })
        p[0] = Node('var_list',
                    args=[p[1]],
                    attrs={'operator': OperatorType.N_ARY})
    else:
        p[0] = p[1]
        p[1].args.append(
            Node(p[3],
                 args=None,
                 attrs={
                     'name': 'identifier',
                     'line': p.lineno(3),
                     'terminal': True
                 }))
Exemple #2
0
def p_program(p):
    '''
    program : function_def program
            | decl program
            | function_decl program
            | empty
    '''
    if len(p) == 2:
        p[0] = None
        return

    if p[2] is None:
        p[0] = Node('program', args=[p[1]])
    else:
        p[0] = Node('program', args=[p[1], *p[2].args])
Exemple #3
0
def handle_function_def(node_stack, table_stack, node):
    msg = table_stack[0].set(
        node.args[0].symbol,
        Symbol(
            table_stack[0].scope, SymbolType.FUNCTION, {
                'init': True,
                'type': node.args[0].attrs['type'],
                'name': node.args[0],
                'arg_type': node.args[1].attrs['type'],
                'arg': node.args[1],
                'line': node.attrs['line']
            }))
    info(table_stack[0].get(node.args[0].symbol), usage=False)
    if msg:
        log.error(msg)
        return Signal.CONTINUE

    table_stack.append(SymbolTable(SymbolScope.LOCAL,
                                   name=node.args[0].symbol))
    table_stack[-1].set(
        node.args[1].symbol,
        Symbol(
            table_stack[-1].scope, SymbolType.VARIABLE, {
                'value': None,
                'type': node.args[1].attrs['type'],
                'name': node.args[1],
                'line': node.attrs.get('line')
            }))

    # psuedo node to mark function exit
    node_stack.append(Node('function_def_end', args=[node.args[0]], attrs={}))

    return_node = None

    node_stack.append(node.args[2])
Exemple #4
0
def generate_function(node_stack, table_stack, table_cache, function):
    function_identifier = function.args[0]
    function_argument = function.args[1]
    function_body = function.args[2]

    table_stack.append(table_cache[function_identifier.symbol])

    node_stack.append(
        Node('function_def_end', args=[function_identifier], attrs={}))

    output = []
    # generate local variables
    generate_memory(table_stack[-1], True)
    function_symbol = table_stack[0].get(function.args[0].symbol)

    output.append(ASM('LABEL', function_symbol.attrs['label']))

    # function is not main
    if function_identifier.symbol != 'main':
        output.append(
            ASM('POP',
                table_stack[-1].get(function_argument.symbol).get('memory')))

    output.append(generate_body(table_stack, function_body))

    if table_stack[-1].name == 'main':
        # if main then just exit the program since we're at the end
        output.append(ASM('STOP'))
    else:
        # if another function then let's return
        output.append(ASM('RETURN'))

    table_stack.pop()

    return output
Exemple #5
0
def p_body(p):
    '''
    body : LBRACE body_prime RBRACE
    '''
    if p[2] is None:
        p[0] = Node('body', args=[])
    else:
        p[0] = p[2]
Exemple #6
0
def p_function_call(p):
    '''
    function_call : identifier LPAR expr RPAR
    '''
    p[1] = Node(p[1],
                args=None,
                attrs={
                    'name': 'identifier',
                    'line': p.lineno(1),
                    'terminal': True
                })
    p[0] = Node('function_call',
                args=[p[1], p[3]],
                attrs={
                    'line': p.lineno(1),
                    'operator': OperatorType.BINARY
                })
Exemple #7
0
def p_function_decl(p):
    '''
    function_decl : kind identifier LPAR kind RPAR SEMI
    '''
    p[2] = Node(p[2],
                args=None,
                attrs={
                    'type': p[1].symbol,
                    'name': 'identifier',
                    'line': p.lineno(1),
                    'terminal': True
                })
    p[0] = Node('function_decl',
                args=[p[2]],
                attrs={
                    'type': p[4].symbol,
                    'line': p.lineno(2),
                    'operator': OperatorType.UNARY
                })
Exemple #8
0
def p_stmt_prime(p):
    '''
    stmt_prime : stmt stmt_prime
               | empty
    '''
    if len(p) == 2:
        p[0] = None
    else:
        if p[2] is None:
            p[0] = p[1]
        else:
            p[0] = Node('stmt_prime', args=[p[1], p[2]])
Exemple #9
0
def p_body_prime(p):
    '''
    body_prime : decl body_prime
               | stmt body_prime
               | empty
    '''
    if len(p) == 2:
        p[0] = None
    else:
        p[0] = Node('body', args=[p[1]])
        if p[2] is not None:
            p[0].args.extend(p[2].args)
Exemple #10
0
def p_expr(p):
    '''
    expr : identifier ASSIGN expr
         | expr1
    '''
    if len(p) == 4:
        p[1] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'identifier',
                        'line': p.lineno(1)
                    })
        p[0] = Node(p[2],
                    args=[p[1], p[3]],
                    attrs={
                        'name': 'ASSIGN',
                        'line': p.lineno(1),
                        'operator': OperatorType.BINARY
                    })
    else:
        p[0] = p[1]
Exemple #11
0
def p_factor(p):
    '''
    factor : identifier
           | integer_literal
           | float_literal
           | function_call
           | LPAR expr RPAR
    '''
    if len(p) == 2:
        if isinstance(p[1], str):
            p[0] = Node(p[1],
                        args=None,
                        attrs={
                            'name': 'identifier',
                            'line': p.lineno(1),
                            'terminal': True
                        })
        elif isinstance(p[1], float):
            p[0] = Node(p[1],
                        args=None,
                        attrs={
                            'name': 'float_literal',
                            'line': p.lineno(1),
                            'terminal': True,
                            'type': float
                        })
        elif isinstance(p[1], int):
            p[0] = Node(p[1],
                        args=None,
                        attrs={
                            'name': 'integer_literal',
                            'line': p.lineno(1),
                            'terminal': True,
                            'type': int
                        })
        else:
            p[0] = p[1]
    else:
        p[0] = p[2]
Exemple #12
0
def p_write_expr_list(p):
    '''
    write_expr_list : expr write_expr_list_prime
                    | string write_expr_list_prime
    '''
    # expr
    if not isinstance(p[1], Node):
        p[1] = Node(p[1],
                    args=[],
                    attrs={
                        'name': 'string',
                        'terminal': True,
                        'line': p.lineno(1)
                    })

    node = Node('write_expr_list', args=[p[1]])

    if p[2] is None:
        p[0] = node
    else:
        p[0] = p[2]
        p[0].args = [p[1], *p[2].args]
Exemple #13
0
def p_kind(p):
    '''
    kind : int_kw
         | float_kw
    '''
    if p[1] == 'int':
        p[0] = Node(int,
                    args=None,
                    attrs={
                        'name': 'int_kw',
                        'type': int,
                        'line': p.lineno(1),
                        'terminal': True
                    })
    else:
        p[0] = Node(float,
                    args=None,
                    attrs={
                        'name': 'float_kw',
                        'type': float,
                        'line': p.lineno(1),
                        'terminal': True
                    })
Exemple #14
0
def p_addop(p):
    '''
    addop : PLUS
          | MINUS
    '''
    if p[1] == '+':
        p[0] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'PLUS',
                        'line': p.lineno(1),
                        'terminal': True,
                        'operator': OperatorType.BINARY
                    })
    else:
        p[0] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'MINUS',
                        'line': p.lineno(1),
                        'terminal': True,
                        'operator': OperatorType.BINARY
                    })
Exemple #15
0
def p_mulop(p):
    '''
    mulop : DIVIDE
          | MULTIPLY
    '''
    if p[1] == '*':
        p[0] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'MULTIPLY',
                        'line': p.lineno(1),
                        'terminal': True,
                        'operator': OperatorType.BINARY
                    })
    else:
        p[0] = Node(p[1],
                    args=None,
                    attrs={
                        'name': 'DIVIDE',
                        'line': p.lineno(1),
                        'terminal': True,
                        'operator': OperatorType.BINARY
                    })
Exemple #16
0
def p_function_def(p):
    '''
    function_def : kind identifier LPAR kind identifier RPAR body
    '''
    p[2] = Node(p[2],
                args=None,
                attrs={
                    'type': p[1].symbol,
                    'name': 'identifier',
                    'terminal': True
                })
    p[5] = Node(p[5],
                args=None,
                attrs={
                    'type': p[4].symbol,
                    'name': 'identifier',
                    'terminal': True
                })
    p[0] = Node('function_def',
                args=[p[2], p[5], p[7]],
                attrs={
                    'line': p.lineno(2),
                    'operator': OperatorType.TRINARY
                })
Exemple #17
0
def p_uminus(p):
    '''
    uminus : MINUS factor %prec uminus
           | factor
    '''
    if p[1] == '-':
        p[0] = Node(p[1],
                    args=[p[2]],
                    attrs={
                        'terminal': True,
                        'line': p.lineno(1),
                        'operator': OperatorType.UNARY
                    })
    else:
        p[0] = p[1]
Exemple #18
0
def p_decl(p):
    '''
    decl : kind var_list SEMI
    '''
    for var in p[2].args:
        var.attrs['type'] = p[1].symbol

    p[0] = Node('decl',
                args=[*p[2].args],
                attrs={
                    'name': 'decl',
                    'line': p.lineno(2),
                    'type': p[1].symbol,
                    'terminal': False
                })
Exemple #19
0
def p_else_stmt(p):
    '''
    else_stmt : else_kw stmt
              | empty
    '''
    if len(p) == 2:
        p[0] = None
    else:
        p[0] = Node(p[1],
                    args=[p[2]],
                    attrs={
                        'name': 'else_kw',
                        'terminal': True,
                        'line': p.lineno(1)
                    })
Exemple #20
0
def p_boolop(p):
    '''
    boolop : LT
           | GT
           | EQUAL
           | LE
           | GE
    '''
    name_map = {'<': 'LT', '>': 'GT', '==': 'EQUAL', '<=': 'LE', '>=': 'GE'}
    p[0] = Node(p[1],
                args=None,
                attrs={
                    'name': name_map[p[1]],
                    'line': p.lineno(1),
                    'terminal': True,
                    'operator': OperatorType.BINARY
                })
Exemple #21
0
def p_stmt(p):
    '''
    stmt : expr SEMI
         | if_kw LPAR bool_expr RPAR stmt else_stmt
         | while_kw LPAR bool_expr RPAR stmt
         | read_kw var_list SEMI
         | write_kw write_expr_list SEMI
         | return_kw expr SEMI
         | LBRACE stmt_prime RBRACE
    '''
    # expr
    if len(p) == 3:
        p[0] = p[1]
    else:
        if p[1] == 'if':
            if p[6] is None:
                p[0] = Node(p[1], args=[p[3], p[5]])
            else:
                p[0] = Node(p[1], args=[p[3], p[5], p[6]])

        elif p[1] == 'while':
            p[0] = Node(p[1],
                        args=[p[3], p[5]],
                        attrs={
                            'name': 'while_kw',
                            'terminal': True,
                            'line': p.lineno(1),
                            'operator': OperatorType.BINARY
                        })

        elif p[1] == 'read':
            p[0] = Node(p[1],
                        args=[*p[2].args],
                        attrs={
                            'name': 'read_kw',
                            'terminal': True,
                            'line': p.lineno(1),
                            'operator': OperatorType.N_ARY
                        })

        elif p[1] == 'write':
            p[0] = Node(p[1],
                        args=[*p[2].args],
                        attrs={
                            'name': 'write_kw',
                            'terminal': True,
                            'line': p.lineno(1),
                            'operator': OperatorType.N_ARY
                        })

        elif p[1] == 'return':
            p[0] = Node(p[1],
                        args=[p[2]],
                        attrs={
                            'name': 'return_kw',
                            'terminal': True,
                            'line': p.lineno(1),
                            'operator': OperatorType.UNARY
                        })

        elif p[1] == '{':
            p[0] = p[2]

        else:
            p[0] = p[1]