Beispiel #1
0
    def FnExpression(self, node):
        expr_result, expr_jump_stmt = self.accept(node.expr)
        arguments_result, arguments_jump_stmt = self.accept(node.arguments)
        if all(argument.__class__ is ast.Const
               for argument in node.arguments.childs):
            if expr_result.__class__ is Function:
                node.result = expr_result.run(*arguments_result)
            else:
                if not node.initialized:
                    node.body = expr_result.body.clone()
                    func_scope = SymbolTable(expr_result, self.global_scope)
                    self.push_scope(func_scope)
                    for i, parameter in enumerate(
                            expr_result.parameterGroup.childs):
                        func_scope.define(parameter.name, parameter.type,
                                          parameter.linespan[0],
                                          arguments_result[i], None)
                    node.initialized = True

                body_result, body_jump_stmt = self.accept(node.body)
                self.pop_scope()
                node.result = body_result
            if self.get_scope().is_pure_function(
                    expr_result.name) and node.result is not None:
                self.replace(node, ast.Const(node.result, node.linespan))
            else:
                self.set_used(expr_result.name)
            return node.result, None
        else:
            self.set_used(expr_result.name)
            return None, None
    def FnExpression(self, node):
        expr_terminated, expr_result, expr_jump_stmt = self.accept(node.expr)
        if not expr_terminated:
            return False, None, None
        arguments_terminated, arguments_result, arguments_jump_stmt = self.accept(
            node.arguments)
        if not arguments_terminated:
            return False, None, None

        if expr_result.__class__ is Function:
            node.result = expr_result.run(*arguments_result)
        else:
            if not node.initialized:
                node.body = expr_result.body.clone()
                func_scope = SymbolTable(expr_result, self.global_scope)
                self.push_scope(func_scope, node.body.linespan[0])
                for i, parameter in enumerate(
                        expr_result.parameterGroup.childs):
                    func_scope.define(parameter.name, parameter.type,
                                      parameter.linespan[0],
                                      arguments_result[i])
                node.initialized = True

            body_terminated, body_result, body_jump_stmt = self.accept(
                node.body)
            if not body_terminated:
                return False, None, None
            self.pop_scope()
            node.result = body_result
        node.terminated = True
        return node.terminated, node.result, None
Beispiel #3
0
    def ConditionalStatement(self, node):
        expr_result, expr_jump_stmt = self.accept(node.expr)
        if expr_result or (not node.else_section.is_empty()):
            self.push_scope(SymbolTable(node, self.get_scope()))
            self.accept(node.then_section)
            self.pop_scope()
            if not node.else_section.is_empty():
                self.push_scope(SymbolTable(node, self.get_scope()))
                self.accept(node.else_section)
                self.pop_scope()

        return node.result, None
 def __init__(self, debug=False):
     self.global_scope = SymbolTable(ast.EmptyNode(), globalFunctionTable)
     self.scopes = [self.global_scope]
     self.linenos = [1]
     self.line_num = 0
     self.debug = debug
     self.runtime_error = False
    def ConditionalStatement(self, node):
        expr_terminated, expr_result, expr_jump_stmt = self.accept(node.expr)
        if not expr_terminated:
            return False, None, None
        if expr_result or (not node.else_section.is_empty()):
            section = node.then_section if expr_result else node.else_section
            if not section.scope_pushed:
                self.push_scope(SymbolTable(node, self.get_scope()),
                                section.linespan[0])
                self.update_lineno(section.linespan[0])
                section.scope_pushed = True
            to_return, terminated, result, jump_stmt = self.visit_with_linecount(
                section)
            if to_return:
                if jump_stmt is not None:
                    self.pop_scope()
                node.terminated = terminated
                node.result = result
                return node.terminated, node.result, jump_stmt
            self.pop_scope()
            self.line_num -= 1

        self.update_lineno(node.linespan[1])
        node.terminated = True
        return node.terminated, node.result, None
Beispiel #6
0
    def FnDeclaration(self, node):
        scope = self.get_scope()
        scope.define(node.name, node.type, node.linespan[0], node, node)

        func_scope = SymbolTable(node, self.global_scope)
        if node.name != 'main':
            self.push_scope(func_scope)
        if not node.parameterGroup.is_empty():
            for i, parameter in enumerate(node.parameterGroup.childs):
                func_scope.define(parameter.name, parameter.type,
                                  parameter.linespan[0], None)
        self.accept(node.body)
        if node.name != 'main':
            self.pop_scope()
        else:
            self.set_used('main')
        return node.result, None
 def FnDeclaration(self, node):
     if not node.visited:
         scope = self.get_scope()
         scope.define(node.name, node.type, node.linespan[0], node)
     if node.name == 'main':
         func_scope = SymbolTable(node, self.global_scope)
         if not node.parameterGroup.is_empty():
             for i, parameter in enumerate(node.parameterGroup.childs):
                 func_scope.define(parameter.name, parameter.type,
                                   parameter.linespan[0])
         if not node.body.visited:
             self.update_lineno(node.body.linespan[0])
         terminated, result, jump_stmt = self.accept(node.body)
         if not terminated:
             return False, None, None
     node.terminated = True
     return node.terminated, node.result, None
Beispiel #8
0
 def __init__(self, debug=False, mark_used=False):
     self.global_scope = SymbolTable(ast.EmptyNode(), globalFunctionTable)
     self.scopes = [self.global_scope]
     self.debug = debug
     self.runtime_error = False
     self.freeze_constant_folding = False
     self.freeze_set_constant = False
     self.check_constant_outer = False
     self.check_constant_self = False
     self.mark_used = mark_used
Beispiel #9
0
    def LoopStatement(self, node):
        prev_check_constant_outer = self.check_constant_outer
        prev_check_constant_self = self.check_constant_self
        self.check_constant_outer = False
        self.check_constant_self = True

        node.save_origin()
        scope = self.get_scope()
        self.push_scope(SymbolTable(node, scope))

        if node.init_stmt is not None:
            prev_freeze_set_constant = self.freeze_set_constant
            self.freeze_set_constant = True
            self.accept(node.init_stmt)
            self.freeze_set_constant = prev_freeze_set_constant

        for iter in range(2):
            expr_result, expr_jump_stmt = self.accept(node.expr)
            if expr_jump_stmt is not None:
                node.result = expr_result
                return node.result, expr_jump_stmt

            result, jump_stmt = self.accept(node.section)
            if jump_stmt is not None:
                if isinstance(jump_stmt, ast.Return):
                    self.pop_scope()
                    node.result = result
                    return node.result, jump_stmt
                elif isinstance(jump_stmt, ast.Break):
                    self.pop_scope()
                    return None, None
                elif isinstance(jump_stmt, ast.Continue):
                    pass
                else:
                    raise ValueError

            if node.term_stmt is not None:
                self.accept(node.term_stmt)

            self.check_constant_self = prev_check_constant_self
            self.check_constant_outer = True
            node.save_origin()
            node.load_origin()

        self.check_constant_outer = prev_check_constant_outer
        self.pop_scope()
        return None, None
Beispiel #10
0
class Interpreter:
    def __init__(self):
        pass

    symbol_table = SymbolTable()
    scope_level = 0
    pc = 0
    result = []

    @classmethod
    def interpret(cls, quaternions):
        try:
            cls.symbol_table.new_table()
            while cls.pc < len(quaternions):
                cls.quaternion_analysis(quaternions[cls.pc])
            cls.symbol_table.delete_table()
            temp = cls.result
            cls.pc = 0
            cls.scope_level = 0
            cls.result = []
            return temp
        except Exception as e:
            print(e)

    @classmethod
    def quaternion_analysis(cls, quaternion):
        try:
            instr_type = quaternion.get_first()
            # 跳转
            if instr_type == Quaternion.GO:
                # 符合跳转条件
                if quaternion.get_second(
                ) is None or cls.symbol_table.get_symbol_value(
                        quaternion.get_second()).get_value() == False:
                    cls.pc = cls.get_value(quaternion.get_forth()).get_value()
                    return
            elif instr_type == Quaternion.READ:
                input_content = raw_input()
                req_type = cls.symbol_table.get_symbol_type(
                    cls.get_identify(quaternion.get_forth()))
                if req_type in [SymbolItem.INT, SymbolItem.ARRAY_INT]:
                    value = cls.parse_input(input_content)
                    if value.get_type() == SymbolItem.INT:
                        cls.set_value(quaternion.get_forth(), value)
                    else:
                        raise ErrorInterpret("输入类型不匹配")
                elif req_type in [SymbolItem.DOUBLE, SymbolItem.ARRAY_DOU]:
                    value = cls.parse_input(input_content)
                    cls.set_value(quaternion.get_forth(), value)
            elif instr_type == Quaternion.WRITE:
                index = -1
                forth = quaternion.get_forth()
                if type(forth) == int:
                    cls.result.append(forth)
                else:
                    if cls.is_array(forth):
                        index = cls.get_array_index(quaternion.get_forth())
                    cls.result.append(
                        cls.symbol_table.get_symbol_value(
                            quaternion.get_forth(), index).get_value())
            elif instr_type == Quaternion.IN:
                cls.scope_level += 1
            elif instr_type == Quaternion.OUT:
                cls.symbol_table.pop(cls.scope_level)
                cls.scope_level -= 1
            elif instr_type == Quaternion.INT:
                if quaternion.get_third() is not None:
                    symbol = SymbolItem(quaternion.get_forth(),
                                        SymbolItem.ARRAY_INT,
                                        s_level=cls.scope_level)
                    symbol.get_value().set_value(
                        quaternion.get_third())  # maybe not work
                    cls.symbol_table.insert(symbol)
                else:
                    int_value = 0
                    if quaternion.get_second() is not None:
                        int_value = Value(SymbolItem.INT,
                                          int(quaternion.get_second()))
                    symbol = SymbolItem(quaternion.get_forth(), SymbolItem.INT,
                                        int_value, cls.scope_level)
                cls.symbol_table.insert(symbol)
            elif instr_type == Quaternion.DOUBLE:
                if quaternion.get_third() is not None:
                    symbol = SymbolItem(quaternion.get_forth(),
                                        SymbolItem.ARRAY_DOU,
                                        s_level=cls.scope_level)
                    symbol.get_value().set_value(
                        quaternion.get_third())  # maybe not work
                    cls.symbol_table.insert(symbol)
                else:
                    int_value = 0
                    if quaternion.get_second() is not None:
                        int_value = Value(SymbolItem.INT,
                                          quaternion.get_second())
                    symbol = SymbolItem(quaternion.get_forth(),
                                        SymbolItem.DOUBLE, int_value,
                                        cls.scope_level)
                cls.symbol_table.insert(symbol)
            elif instr_type == Quaternion.ASSIGN:
                value = cls.get_value(quaternion.get_second())
                cls.set_value(quaternion.get_forth(), value)
            elif instr_type == Quaternion.PLUS:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).plus(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.MINUS:
                if quaternion.get_third() is not None:
                    cls.set_value(
                        quaternion.get_forth(),
                        cls.get_value(quaternion.get_second()).minus(
                            cls.get_value(quaternion.get_third())))
                else:
                    cls.set_value(
                        quaternion.get_forth(),
                        Value.negative(cls.get_value(quaternion.get_second())))
            elif instr_type == Quaternion.MUL:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).multiple(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.DIV:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).division(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.GT:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).greater(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.GET:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).greater_equal(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.LT:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).less(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.LET:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).less_equal(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.EQ:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).equal(
                        cls.get_value(quaternion.get_third())))
            elif instr_type == Quaternion.NEQ:
                cls.set_value(
                    quaternion.get_forth(),
                    cls.get_value(quaternion.get_second()).not_equal(
                        cls.get_value(quaternion.get_third())))
            cls.pc += 1
        except ErrorInterpret as e:
            print(e.content)

    # 取值,1 , b[1]
    @classmethod
    def get_value(cls, str_id):
        try:

            if type(str_id) == float:
                value = Value(SymbolItem.DOUBLE, str_id)
                return value
            elif type(str_id) == int:
                value = Value(SymbolItem.INT, str_id)
                return value
            index = -1
            if cls.is_array(str_id):
                index = cls.get_array_index(str_id)
            return cls.symbol_table.get_symbol_value(cls.get_identify(str_id),
                                                     index)
        except ErrorInterpret as e:
            print(e.content)

    # 赋值,a = 2  a[2] = 2
    @classmethod
    def set_value(cls, str_id, value):
        try:
            index = cls.get_array_index(str_id) if cls.is_array(str_id) else -1
            ident = cls.get_identify(str_id)
            symbol_type = cls.symbol_table.get_symbol_type(ident)
            if symbol_type == SymbolItem.INT:
                if value.get_type() == SymbolItem.INT:
                    cls.symbol_table.set_symbol_value(ident, value)
                elif value.get_type() == SymbolItem.DOUBLE:
                    raise ErrorInterpret("表达式{0}与变量类型不匹配".format(str_id))
            elif symbol_type == SymbolItem.DOUBLE:
                cls.symbol_table.set_symbol_value(ident, value.to_double())
            elif symbol_type == SymbolItem.ARRAY_INT:
                if cls.symbol_table.get_symbol_value(
                        ident, index).get_type() == SymbolItem.ARRAY_INT:
                    cls.symbol_table.set_symbol_value(ident, value.get_value(),
                                                      index)
                else:
                    raise ErrorInterpret("表达式{0}与变量类型不匹配".format(str_id))
            elif symbol_type == SymbolItem.ARRAY_DOU:
                cls.symbol_table.set_symbol_value(ident,
                                                  float(value.get_value()),
                                                  index)
            elif symbol_type == SymbolItem.TEMP:
                cls.symbol_table.set_symbol_value(ident, value)
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def is_array(cls, str_id):
        return str_id.endswith("]")

    @classmethod
    def get_array_index(cls, str_id):
        return int(str_id[str_id.index("[") + 1:str_id.index("]")])

    @classmethod
    def get_identify(cls, str_id):
        if cls.is_array(str_id):
            return int(str_id[0:str_id.index("[")])
        return str_id

    @classmethod
    def parse_input(cls, content):
        try:
            if re.match('-?([0-9]+.[0-9]+)', content):
                value = Value(SymbolItem.DOUBLE, string.atof(content))
                return value
            elif re.match('-?[0-9]+]', content):
                value = Value(SymbolItem.INT, string.atoi(content))
                return value
            raise ErrorInterpret("输入非法")
        except ErrorInterpret as e:
            print(e.content)
Beispiel #11
0
class Generator:
    def __init__(self):
        pass

    symbol_table = SymbolTable()
    codes = []
    lineCount = -1
    scope_level = 0

    @classmethod
    def generate(cls, node_list):
        cls.symbol_table.new_table()
        for i in node_list:
            cls.translate_switch(i)
        cls.symbol_table.delete_table()
        temp = cls.codes
        cls.codes = []
        return temp

    @classmethod
    def translate_switch(cls, node):
        while True:
            node_type = node.get_type()
            if node_type == Node.IF_STMT:
                cls.translate_if(node)
            elif node_type == Node.WHILE_STMT:
                cls.translate_while(node)
            elif node_type == Node.READ_STMT:
                cls.translate_read(node)
            elif node_type == Node.WRITE_STMT:
                cls.translate_write(node)
            elif node_type == Node.DECLARE_STMT:
                cls.translate_declare(node)
            elif node_type == Node.ASSIGN_STMT:
                cls.translate_assign(node)
            cls.symbol_table.clear_temp_name()
            if node.get_next() is not None:
                node = node.get_next()
                continue
            break

    @classmethod
    def translate_if(cls, node):
        false_go = Quaternion(Quaternion.GO,
                              cls.translate_exp(node.get_left()))
        cls.codes.append(false_go)
        cls.lineCount += 1
        cls.codes.append(Quaternion(Quaternion.IN))
        # 进入语句块
        cls.lineCount += 1
        # 代码层级加一
        cls.scope_level += 1
        # 处理这一层级
        cls.translate_switch(node.get_middle())
        # 清除局部变量
        cls.symbol_table.pop(cls.scope_level)
        # 代码层级恢复
        cls.scope_level -= 1
        cls.codes.append(Quaternion(Quaternion.OUT))
        cls.lineCount += 1
        # 判断else部分子节点是否存在
        if node.get_right() is not None:
            out_go = Quaternion(Quaternion.GO)
            cls.codes.append(out_go)
            cls.lineCount += 1
            false_go.set_forth(str(cls.lineCount + 1))
            cls.codes.append(Quaternion(Quaternion.IN))
            cls.lineCount += 1
            cls.scope_level += 1
            cls.translate_switch(node.get_right())
            cls.symbol_table.pop(cls.scope_level)
            cls.scope_level -= 1
            cls.codes.append(Quaternion(Quaternion.OUT))
            cls.lineCount += 1
            out_go.set_forth(str(cls.lineCount + 1))
        else:
            false_go.set_forth(str(cls.lineCount + 1))

    @classmethod
    def translate_while(cls, node):
        go_line = cls.lineCount + 1
        false_go = Quaternion(Quaternion.GO,
                              cls.translate_exp(node.get_left()))
        cls.codes.append(false_go)
        cls.lineCount += 1
        cls.codes.append(Quaternion(Quaternion.IN))
        cls.lineCount += 1
        cls.scope_level += 1
        cls.translate_switch(node.get_middle())
        cls.symbol_table.pop(cls.scope_level)
        cls.scope_level -= 1
        cls.codes.append(Quaternion(Quaternion.OUT))
        cls.lineCount += 1
        cls.codes.append(Quaternion(Quaternion.GO, None, None, go_line))
        cls.lineCount += 1
        false_go.set_forth(cls.lineCount + 1)

    @classmethod
    def translate_read(cls, node):
        try:
            # 变量类型
            var_type = cls.symbol_table.get_symbol_type(
                node.get_left().get_value())
            if var_type in [SymbolItem.INT, SymbolItem.DOUBLE]:
                cls.codes.append(
                    Quaternion(first=Quaternion.READ,
                               forth=node.get_left().get_value()))
                cls.lineCount += 1
                return
            elif var_type in [SymbolItem.ARRAY_INT, SymbolItem.ARRAY_DOU]:
                cls.codes.append(
                    Quaternion(first=Quaternion.READ,
                               forth=node.get_left().get_left() + "[" +
                               cls.translate_exp(node.get_left().get_left()) +
                               "]"))
                cls.lineCount += 1
                return
            raise ErrorInterpret("语句有误")
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def translate_write(cls, node):
        cls.codes.append(
            Quaternion(first=Quaternion.WRITE,
                       forth=cls.translate_exp(node.get_left())))
        cls.lineCount += 1

    @classmethod
    def translate_declare(cls, node):
        var = node.get_left()
        if var.get_left() is None:
            value = None
            if node.get_middle() is not None:
                value = cls.translate_exp(node.get_middle())
            if var.get_data_type() == Token.INT:
                cls.codes.append(
                    Quaternion(Quaternion.INT, value, None, var.get_value()))
                cls.lineCount += 1
                symbol = SymbolItem(s_name=var.get_value(),
                                    s_type=SymbolItem.INT,
                                    s_level=cls.scope_level)
                cls.symbol_table.insert(symbol)
            elif var.get_data_type() == Token.DOUBLE:
                cls.codes.append(
                    Quaternion(Quaternion.DOUBLE, value, None,
                               var.get_value()))
                cls.lineCount += 1
                symbol = SymbolItem(s_name=var.get_value(),
                                    s_type=SymbolItem.DOUBLE,
                                    s_level=cls.scope_level)
                cls.symbol_table.insert(symbol)
        else:
            # 数组
            len = cls.translate_exp(var.get_left())
            if var.get_data_type() == Token.INT:
                cls.codes.append(
                    Quaternion(Quaternion.INT, None, len, var.get_value()))
                cls.lineCount += 1
                symbol = SymbolItem(s_name=var.get_value(),
                                    s_type=SymbolItem.ARRAY_INT,
                                    s_level=cls.scope_level)
                cls.symbol_table.insert(symbol)
            elif var.get_data_type() == Token.DOUBLE:
                cls.codes.append(
                    Quaternion(Quaternion.DOUBLE, None, len, var.get_value()))
                cls.lineCount += 1
                symbol = SymbolItem(s_name=var.get_value(),
                                    s_type=SymbolItem.ARRAY_DOU,
                                    s_level=cls.scope_level)
                cls.symbol_table.insert(symbol)

    # 赋值
    @classmethod
    def translate_assign(cls, node):
        value = cls.translate_exp(node.get_middle())
        var = node.get_left()
        if var.get_left() is None:
            cls.codes.append(
                Quaternion(Quaternion.ASSIGN, value, None, var.get_value()))
            cls.lineCount += 1
        else:
            index = cls.translate_exp(var.get_left())
            cls.codes.append(
                Quaternion(Quaternion.ASSIGN, value, None,
                           var.get_value() + "[" + index + "]"))
            cls.lineCount += 1

    @classmethod
    def translate_exp(cls, sub_node):
        try:
            if sub_node.get_type() == Node.EXP:
                data_type = sub_node.get_data_type()
                if data_type == Token.LOGIC_EXP:
                    return cls.translate_logic_exp(sub_node)
                elif data_type == Token.MULTI_TERM_EXP:
                    return cls.translate_multi_term_exp(sub_node)
                elif data_type == Token.TERM_EXP:
                    return cls.translate_term_exp(sub_node)
                raise ErrorInterpret("表达式非法")
            elif sub_node.get_type() == Node.FACTOR:
                if sub_node.get_data_type() == Token.MINUS:
                    temp = cls.symbol_table.get_temp_symbol().get_name()
                    cls.codes.append(
                        Quaternion(Quaternion.MINUS,
                                   cls.translate_exp(sub_node.get_left()),
                                   None, temp))
                    cls.lineCount += 1
                    return temp
                return cls.translate_exp(sub_node.get_left())
            elif sub_node.get_type() == Node.VAR:
                if sub_node.get_left() is None:
                    if cls.symbol_table.get_symbol_type(
                            sub_node.get_value()) in [
                                SymbolItem.INT, SymbolItem.DOUBLE
                            ]:
                        return sub_node.get_value()
                # 数组
                else:
                    if cls.symbol_table.get_symbol_type(
                            sub_node.get_value()) in [
                                SymbolItem.ARRAY_INT, SymbolItem.ARRAY_DOU
                            ]:
                        temp = cls.symbol_table.get_temp_symbol().get_name()
                        index = cls.translate_exp(sub_node.get_left())
                        cls.codes.append(
                            Quaternion(
                                Quaternion.ASSIGN,
                                sub_node.get_value() + "[" + index + "]", None,
                                temp))
                        cls.lineCount += 1
                        return temp
            elif sub_node.get_type() == Node.LITERAL:
                return sub_node.get_value()
            raise ErrorInterpret("表达式非法")
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def translate_logic_exp(cls, node):
        try:
            temp = cls.symbol_table.get_temp_symbol().get_name()
            data_type = node.get_middle().get_data_type()
            if data_type == Token.GT:
                cls.codes.append(
                    Quaternion(Quaternion.GT,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.GET:
                cls.codes.append(
                    Quaternion(Quaternion.GET,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.LT:
                cls.codes.append(
                    Quaternion(Quaternion.LT,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.LET:
                cls.codes.append(
                    Quaternion(Quaternion.LET,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.EQ:
                cls.codes.append(
                    Quaternion(Quaternion.EQ,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.NEQ:
                cls.codes.append(
                    Quaternion(Quaternion.NEQ,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            else:
                raise ErrorInterpret("逻辑运算非法")
            cls.lineCount += 1
            return temp
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def translate_multi_term_exp(cls, node):
        try:
            temp = cls.symbol_table.get_temp_symbol().get_name()
            data_type = node.get_middle().get_data_type()
            if data_type == Token.PLUS:
                cls.codes.append(
                    Quaternion(Quaternion.PLUS,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            elif data_type == Token.MINUS:
                cls.codes.append(
                    Quaternion(Quaternion.MINUS,
                               cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
            else:
                raise ErrorInterpret("算数运算错误")
            cls.lineCount += 1
            return temp
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def translate_term_exp(cls, node):
        try:
            op = cls.get_op(node.get_middle().get_data_type())
            temp = cls.symbol_table.get_temp_symbol().get_name()
            if node.get_right().get_type() == Node.FACTOR:
                cls.codes.append(
                    Quaternion(op, cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_right()), temp))
                cls.lineCount += 1
            else:
                cls.codes.append(
                    Quaternion(op, cls.translate_exp(node.get_left()),
                               cls.translate_exp(node.get_left().get_right()),
                               temp))
                cls.lineCount += 1
                node = node.get_right()
                while node.get_right(
                ) is not None and node.get_right().get_type() != Node.FACTOR:
                    op = cls.get_op(node.get_middle().get_data_type())
                    temp2 = cls.symbol_table.get_temp_symbol().get_name()
                    cls.codes.append(
                        Quaternion(
                            op, temp,
                            cls.translate_exp(node.get_right().get_left()),
                            temp2))
                    cls.lineCount += 1
                    node = node.get_right()
                    temp = temp2
                op = cls.get_op(node.get_middle().get_data_type())
                temp2 = cls.symbol_table.get_temp_symbol().get_name()
                cls.codes.append(
                    Quaternion(op, temp, cls.translate_exp(node.get_right()),
                               temp2))
                cls.lineCount += 1
                temp = temp2
            return temp
        except ErrorInterpret as e:
            print(e.content)

    @classmethod
    def get_op(cls, op):
        if op == Token.MUL:
            return Quaternion.MUL
        elif op == Token.DIV:
            return Quaternion.DIV
    def LoopStatement(self, node):
        if not node.visited:
            node.save_origin()
            scope = self.get_scope()
            self.push_scope(SymbolTable(node, scope),
                            node.get_excutable_lineno() + 1)

        if node.init_stmt is not None:
            init_stmt_terminated, init_stmt_result, init_stmt_jump_stmt = self.accept(
                node.init_stmt)
            if not init_stmt_terminated:
                return False, None, None

        while True:
            to_return, expr_terminated, expr_result, expr_jump_stmt = self.visit_with_linecount(
                node.expr)
            if to_return:
                node.terminated = expr_terminated
                node.result = expr_result
                return node.terminated, node.result, expr_jump_stmt

            if not expr_result:
                self.pop_scope()
                node.terminated = True
                self.update_lineno(node.linespan[1])
                self.line_num -= 1
                return node.terminated, node.result, None

            to_return, terminated, result, jump_stmt = self.visit_with_linecount(
                node.section)
            if to_return:
                if jump_stmt is not None:
                    if isinstance(jump_stmt, ast.Return):
                        self.pop_scope()
                        self.update_lineno(node.linespan[1])
                        node.terminated = terminated
                        node.result = result
                        return node.terminated, node.result, jump_stmt
                    elif isinstance(jump_stmt, ast.Break):
                        self.pop_scope()
                        self.update_lineno(node.linespan[1])
                        node.terminated = terminated
                        return node.terminated, None, None
                    elif isinstance(jump_stmt, ast.Continue):
                        pass
                    else:
                        raise ValueError
                else:
                    node.terminated = terminated
                    return node.terminated, None, None

            if node.term_stmt is not None:
                term_stmt_terminated, term_stmt_result, term_stmt_jump_stmt = self.accept(
                    node.term_stmt)
                if (not term_stmt_terminated):
                    return False, None, None

            self.update_lineno(node.linespan[0])
            self.line_num -= 1

            node.load_origin()
Beispiel #13
0
import sys
from model.ast import TypeNode, EmptyNode
from model.symbol_table import SymbolTable
import codecs


class Function:
    def __init__(self, function, name):
        self.function = function
        self.name = name

    def run(self, *args):
        return self.function(*args)


def printf(format, *args):
    format_ = codecs.escape_decode(format)[0].decode('unicode_escape')
    return sys.stdout.write(format_ % args)


globalFunctionTable = SymbolTable(EmptyNode())
globalFunctionTable.define('printf', TypeNode(), 0, Function(printf, 'printf'))
globalFunctionTable.set_pure_function('printf', False)