示例#1
0
 def VarCall(node, children_codes):
     # VarCall -> ident VarCallRight
     code = []
     ident = node.children[0].token.string
     var_type = node.properties['var_type']
     data_type = node.properties['data_type']
     if var_type == 'var':
         arg = Argument('ident', data_type, ident)
     elif var_type == 'array':
         # todo: array
         pass
     elif var_type == 'call':
         arglist_code = children_codes[1]
         code = [*code, *arglist_code]
         code.append(new_inst('call', ident))
         if data_type != 'void':
             getval = Argument('ident', data_type, GETVAL)
             arg = Argument('ident', data_type, get_ident())
             code.append(new_inst('mov', arg, getval))
         else:
             arg = None
     else:
         assert False
     node.properties['arg'] = arg
     return code
示例#2
0
 def Function(node, children_codes):
     # Fucntion -> def ident(ParaList) FunctionBody
     body_code = children_codes[-1]
     para_list = node.properties['para_list']  # ((type, ident),...)
     para_code = []
     i = len(para_list) - 1
     while i >= 0:
         para = para_list[i]
         para_code.append(new_inst('alloc', *para,
                                   DEFAULT_VAL[para[0]]))
         para_code.append(
             new_inst('mov', Argument('ident', *para),
                      Argument('ident', para[0], ARG_PREFIX + str(i))))
         i = i - 1
     name = node.properties['name']
     if name == MAIN:
         return_code = [new_inst('exit')]
     else:
         return_code = [new_inst('ret')]
     return_type = node.properties['return_type']
     if return_type != 'void':
         retval_code = [
             new_inst('alloc', return_type, RETVAL,
                      DEFAULT_VAL[return_type])
         ]
     else:
         retval_code = []
     return [
         new_inst('proc', name), *retval_code, *para_code, *body_code,
         *return_code,
         new_inst('end', name)
     ]
示例#3
0
 def HandleCalcItem(inst_of_op, left, right, node, children_codes):
     # Xxx -> Item XxxRight
     # XxxRight -> Op Item XxxRight
     code = []
     if (right.children
             #                and right.children[].syntax_item.startswith(node.syntax_item)
         ):
         op = right.properties['op']
         right_arg = right.properties['arg']
         left_arg = left.properties['arg']
         data_type = node.properties['data_type']
         temp = Argument('ident', data_type, get_ident())
         code.append(new_inst(inst_of_op[op], temp, left_arg,
                              right_arg))
         node.properties['arg'] = temp
         if node.deriv_tuple[0] in inst_of_op:
             node.properties['op'] = node.children[0].token.string
         else:
             pass
     else:
         if node.deriv_tuple[0] in inst_of_op:
             node.properties['op'] = node.children[0].token.string
         else:
             pass
         node.properties['arg'] = left.properties['arg']
     return expand_code_list(children_codes) + code
示例#4
0
 def Assign(node, children_codes):
     # Assign -> Var = Expr
     ident = node.children[0].properties['ident']
     data_type = node.children[0].properties['data_type']
     var_arg = Argument('ident', data_type, ident)
     expr_arg = node.children[2].properties['arg']
     expr_code = children_codes[2]
     return [*expr_code, new_inst('mov', var_arg, expr_arg)]
示例#5
0
 def Oprand(node, children_codes):
     # Oprand -> Var | integer_value | double_value | bool_value
     data_type = node.properties['data_type']
     child = node.children[0]
     if node.deriv_tuple[0] == 'VarCall':
         arg = node.children[0].properties['arg']
     else:
         arg = Argument('data', data_type, child.token.string)
     node.properties['arg'] = arg
     return expand_code_list(children_codes)
示例#6
0
 def Unary(node, children_codes):
     # Unary -> {+, -, !} Unary | ParExpr | Oprand
     code = []
     op = node.deriv_tuple[0]
     oprand = node.children[-1]
     oprand_arg = oprand.properties['arg']
     data_type = node.properties['data_type']
     if op in ['ParExpr', 'Oprand', '+']:
         node.properties['arg'] = oprand_arg
     elif op == '-':
         temp = Argument('ident', data_type, get_ident())
         zero = Argument('data', data_type, 0)
         code.append(new_inst('minus', temp, zero, oprand_arg))
         node.properties['arg'] = temp
     elif op == '!':
         temp = Argument('ident', data_type, get_ident())
         code.append(new_inst('not', temp, oprand_arg))
         node.properties['arg'] = temp
     else:
         assert False
     return expand_code_list(children_codes) + code
示例#7
0
 def ArgList(node, children_codes):
     # ArgList -> Expr ArgListRight
     if not node.children:
         return []
     result_code = []
     expr_node = node.children[0]
     right = node.children[-1]
     arg = expr_node.properties['arg']
     code = children_codes[0]
     args = node.properties['args'] = [arg, *right.properties['args']]
     codes = [[*code], *children_codes[-1]]
     types = node.properties['arg_types']
     for i in range(0, len(args)):
         result_code = [
             *result_code, *codes[i],
             new_inst('override',
                      Argument('ident', types[i], ARG_PREFIX + str(i)),
                      args[i])
         ]
     return result_code
示例#8
0
        def Stmt(node, children_codes):
            # Stmt -> Assign; | read Var; | print Expr; | eval Expr;
            #         if(Expr) Stmt Else | while(Expr) Stmt |
            #         do Stmt while(Expr); | for(Assign; Expr; Assign) Stmt |
            #         break; | continue; | return ReturnValue | Block
            def enable_jump(code, continue_label, break_label):
                for i in range(0, len(code)):
                    if code[i] == 'continue':
                        code[i] = new_inst('goto', continue_label)
                    elif code[i] == 'break':
                        code[i] = new_inst('goto', break_label)

            rule = node.deriv_tuple[0]
            if rule == 'if':
                # if(Expr) Stmt Else
                expr_node = node.children[2]
                expr_code = children_codes[2]
                expr_arg = expr_node.properties['arg']
                stmt_code = children_codes[4]
                else_code = children_codes[5]
                label_pre_else = get_label()
                label_post_else = get_label()
                return [
                    *expr_code,
                    new_inst('goto_if_false', expr_arg, label_pre_else),
                    *stmt_code,
                    new_inst('goto', label_post_else),
                    new_inst('label', label_pre_else), *else_code,
                    new_inst('label', label_post_else)
                ]
            elif rule == 'while':
                # while(Expr) Stmt
                expr_node = node.children[2]
                expr_code = children_codes[2]
                expr_arg = expr_node.properties['arg']
                stmt_code = children_codes[4]
                label_go_back = get_label()
                label_tail = get_label()
                enable_jump(stmt_code, label_go_back, label_tail)
                return [
                    new_inst('label', label_go_back), *expr_code,
                    new_inst('goto_if_false', expr_arg, label_tail),
                    *stmt_code,
                    new_inst('goto', label_go_back),
                    new_inst('label', label_tail)
                ]
            elif rule == 'do':
                # do Stmt while(Expr);
                expr_node = node.children[4]
                expr_code = children_codes[4]
                expr_arg = expr_node.properties['arg']
                stmt_code = children_codes[1]
                label_go_back = get_label()
                label_tail = get_label()
                enable_jump(stmt_code, label_go_back, label_tail)
                return [
                    new_inst('label', label_go_back), *stmt_code, *expr_code,
                    new_inst('goto_if', expr_arg, label_go_back),
                    new_inst('label', label_tail)
                ]
            elif rule == 'for':
                # for(Assign; Expr; Assign) Stmt
                initial_code = children_codes[2]
                condition_node = node.children[4]
                condition_code = children_codes[4]
                condition_arg = condition_node.properties['arg']
                increment_code = children_codes[6]
                stmt_code = children_codes[8]
                label_go_back = get_label()
                label_tail = get_label()
                enable_jump(stmt_code, label_go_back, label_tail)
                return [
                    *initial_code,
                    new_inst('label', label_go_back), *condition_code,
                    new_inst('goto_if_false', condition_arg, label_tail),
                    *stmt_code, *increment_code,
                    new_inst('goto', label_go_back),
                    new_inst('label', label_tail)
                ]
            elif rule == 'break':
                # to be handled in enable_jump()
                return ['break']
            elif rule == 'continue':
                # to be handled in enable_jump()
                return ['continue']
            elif rule == 'return':
                code = []
                data_type = node.children[1].properties['data_type']
                if data_type != 'void':
                    retval_arg = Argument('ident', data_type, RETVAL)
                    expr_arg = node.children[1].properties['arg']
                    expr_code = children_codes[1]
                    code = [*code, *expr_code]
                    code.append(new_inst('mov', retval_arg, expr_arg))
                assert node.function
                if node.function.properties['name'] == MAIN:
                    code.append(new_inst('exit'))
                else:
                    code.append(new_inst('ret'))
                return code
            elif rule == 'read':
                # read Var;
                ident = node.children[1].properties['ident']
                data_type = node.children[1].properties['data_type']
                ident_arg = Argument('ident', data_type, ident)
                return [new_inst('read', ident_arg)]
            elif rule == 'print':
                # print Expr;
                expr_code = children_codes[1]
                expr_arg = node.children[1].properties['arg']
                return [*expr_code, new_inst('print', expr_arg)]
            else:
                return expand_code_list(children_codes)
示例#9
0
#!/usr/bin/env python3

import sys
from syntax import get_syntax_tree
from machine import (Instruction, Argument, CALCULATION, RETVAL, GETVAL,
                     ARG_PREFIX, TEMP_PREFIX)
from common import DEBUG, e_print

LABEL_PREFIX = 'L'
MAIN = 'main'
DEFAULT_VAL = {
    'int': Argument('data', 'int', 0),
    'double': Argument('data', 'double', 0.0),
    'bool': Argument('data', 'bool', False)
}


def translate(syntax_tree_root):
    max_ident_index = -1
    max_label_index = -1
    released_idents_list = []
    released_idents = {}

    def get_label():
        nonlocal max_label_index
        max_label_index += 1
        return LABEL_PREFIX + str(max_label_index)

    def get_ident():
        nonlocal max_ident_index
        if released_idents_list: