示例#1
0
class NodeVisitor(object):
    def __init__(self):
        self.symbol_table = SymbolTable(None, None)
        self.should_stop_processing = False

    def visit(self, node):
        # print("visiting:", node.__class__.__name__)
        if self.symbol_table.getParentScope(
        ) == "return" and node.type == "INSTRUCTION":
            print(
                "[line: {}]: Error, instruction after 'return' is unreachable".
                format(node.lineno))
            self.should_stop_processing = True
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, self.generic_visit)
        return visitor(node)

    def generic_visit(
            self,
            node):  # Called if no explicit visitor function exists for a node.
        if isinstance(node, list):
            for elem in node:
                self.visit(elem)
        else:
            for child in node.children:
                if isinstance(child, list):
                    for item in child:
                        if isinstance(item, AST.Node):
                            self.visit(item)
                elif isinstance(child, AST.Node):
                    self.visit(child)
示例#2
0
    def execute(self, args):
        res = RTResult()
        interpreter = inter.Interpreter()

        new_context = Context(self.name, self.context, self.pos_start)
        new_context.symbol_table = SymbolTable(new_context.parent.symbol_table)

        if len(args) < len(self.arg_names):
            return res.failure(
                RTError(
                    self.pos_start, self.pos_end,
                    f"'{len(self.arg_names) - len(args)}' less args than expected passed into '{self.name}",
                    self.context))

        if len(args) > len(self.arg_names):
            return res.failure(
                RTError(
                    self.pos_start, self.pos_end,
                    f"'{len(args) - len(self.arg_names)}' more args than expected passed into '{self.name}",
                    self.context))

        for i in range(len(args)):
            arg_name = self.arg_names[i]
            arg_value = args[i]
            arg_value.set_context(new_context)
            new_context.symbol_table.set(arg_name, arg_value)

        value = res.register(interpreter.visit(self.body_node, new_context))
        if res.error: return res
        return res.success(value)
示例#3
0
文件: builder.py 项目: doffm/dbuf
def compile (filenames):
        """
        Parse all the provided files and then resolve
        symbols between them.

        Return a 'SymbolTable' containing symbols defined in all the
        files.
        """

        table = SymbolTable ()
        parsed = []

        for filename in filenames:
                defined, root, tokens = parse (filename)
                table.addModuleSymbols (defined)
                parsed.append ((root, tokens))

        for root, tokens in parsed:
                nodes = antlr3.tree.CommonTreeNodeStream (root)
                nodes.setTokenStream (tokens)
                linker = dbuflink (nodes)
                linker.idl (table)

        return table
示例#4
0
def main(argc, argv):

    # Check arguments
    if argc != 5:
        fatal(
            'Usage: %s <symbol table> <symbol base> <new symbol base> <output linker script>'
            % argv[0])

    sym_path = argv[1]
    sym_path_out = argv[4]

    try:
        sym_base = int(argv[2], 0)
    except:
        fatal('Parsing symbol base failed!')

    try:
        sym_base_new = int(argv[3], 0)
    except:
        fatal('Parsing new symbol base failed!')

    try:
        sym_table = SymbolTable.from_file(sym_path, False,
                                          sym_base - sym_base_new)
    except:
        fatal('Opening symbol table failed!')

    try:
        out_file = open(sym_path_out, "w")
    except:
        fatal('Opening output file failed!')

    # Create linker script with relocated symbols
    for sym_name, sym_address in sorted(sym_table.mangled_dict.items(),
                                        key=itemgetter(1)):
        sym_line = '%s = %s;\n' % (sym_name, hex(sym_address))
        out_file.write(sym_line)

    print('Relocated %s from %s to %s into %s' %
          (sym_path, hex(sym_base), hex(sym_base_new), sym_path_out))

    sys.exit(0)
示例#5
0
 def __init__(self):
     self.symbol_table = SymbolTable()
     self.type_checker = TypeChecker()
     self.GLOBAL_MEMORY = {}
示例#6
0
class SemanticHandler(NodeVisitor):
    def __init__(self):
        self.symbol_table = SymbolTable()
        self.type_checker = TypeChecker()
        self.GLOBAL_MEMORY = {}

    def visit_Program(self, node: Program) -> None:
        """Visit the Block node in AST and call it.

        Args:
            node (Program): Program node (root)
        """

        self.visit(node.block)

    def visit_Block(self, node: Block) -> None:
        """Visit the variable declaration section (VAR) and call the visit_VarDeclaration
        method to identify and add the symbols and the Symbol Table. After this, call
        visit_Compound method to handle with the compound statements (assigments).

        Args:
            node (Block): the block containing the VAR and BEGIN sections
        """

        for declaration in node.declarations:
            self.visit(declaration)
        self.visit(node.compound_statement)

    def visit_VarDeclaration(self, node: VarDeclaration) -> None:
        """Var declaration section (VAR), finds and adds symbols in the Symbol Table.

        Args:
            node (VarDeclaration): node containing the variable type and the var_node
            represeting the variable
        """

        type_name = node.type_node.value
        type_symbol = self.symbol_table.get_token(type_name)
        var_name = node.var_node.value
        var_symbol = VarSymbol(var_name, type_symbol)

        if self.symbol_table.get_token(var_name) is not None:
            SemanticErrorHandler.error(
                error_code=ErrorCode.DUPLICATE_ID,
                token=node.var_node.token,
                var_name=var_name,
            )

        self.symbol_table.add_token(var_symbol)

    def visit_Compound(self, node: Compound) -> None:
        """Central component that coordinates the compound statements (assigments and
        writeln statement) and calls the methods according to their type.

        Args:
            node (Compound): node containing all of the compound statements (assigments
            and writeln statement)
        """

        for child in node.children:
            self.visit(child)

    def visit_Assign(self, node: Assign) -> None:
        """Search the variable of the assigment in the Symbol Table and verify if it exists,
        if found triggers the next symbol (if it exists), else show an error stating that
        the variable has not been declared.

        Args:
            node (Assign): node containing the assignment content
        """

        self.visit(node.left)
        self.visit(node.right)

        if node.right is not None and not isinstance(node.right,
                                                     BinaryOperator):
            while isinstance(node.right, UnaryOperator):
                node.right = node.right.expression

            self.GLOBAL_MEMORY[node.left.value] = node.right.token.type

    def visit_Var(self, node: Var) -> None:
        """ "Search the variable in the Symbol Table and verify if it exists, if not found
        shows an error stating has not been declared.

        Args:
            node (Var): variable token
        """

        var_name = node.value
        var_symbol = self.symbol_table.get_token(var_name)

        if var_symbol is None:
            SemanticErrorHandler.error(error_code=ErrorCode.ID_NOT_FOUND,
                                       token=node.token,
                                       var_name=var_name)

    def visit_BinaryOperator(self, node: BinaryOperator) -> None:
        """Calls the methods according to the value of the nodes that are to the left and
        right of the expression.

        Args:
            node (BinaryOperator): node containing the node with binary operations
        """

        self.visit(node.left)
        self.visit(node.right)

        # Zero division
        if isinstance(node.right, Num) and node.right.value == 0:
            while isinstance(node.left, UnaryOperator):
                node.left = node.left.expression
            SemanticErrorHandler.error_zero_division(node.left.value)

        if isinstance(node.left, (Var, Boolean, String)):
            left_symbol = self.symbol_table.get_token(node.left.value)

            if left_symbol is None:
                SemanticErrorHandler.type_error(node.left.token.type.name,
                                                token=node.left.token)

            left_symbol_token = self.GLOBAL_MEMORY[left_symbol.name]
            variable_type_not_allowed = not self.type_checker.is_allowed_type(
                Context.BIN_OP, left_symbol.type.name)
            value_type_not_allowed = not self.type_checker.is_allowed_type(
                Context.BIN_OP, left_symbol_token.name)

            if variable_type_not_allowed or value_type_not_allowed:
                if node.right.token.type == TokenType.ID:
                    right_symbol = self.symbol_table.get_token(
                        node.right.value)
                    right_var_type = right_symbol.type.name
                else:
                    right_var_type = node.right.token.type.value

                if value_type_not_allowed:
                    left_var_type = left_symbol_token.name
                else:
                    left_var_type = left_symbol.type.name

                SemanticErrorHandler.type_error(left_var_type,
                                                right_var_type,
                                                token=node.left.token)

        if isinstance(node.right, (Var, Boolean, String)):
            right_symbol = self.symbol_table.get_token(node.right.value)

            if right_symbol is None:
                SemanticErrorHandler.type_error(node.right.token.type.name,
                                                token=node.right.token)

            right_symbol_token = self.GLOBAL_MEMORY[right_symbol.name]
            variable_type_not_allowed = not self.type_checker.is_allowed_type(
                Context.BIN_OP, right_symbol.type.name)
            value_type_not_allowed = not self.type_checker.is_allowed_type(
                Context.BIN_OP, right_symbol_token.name)

            if variable_type_not_allowed or value_type_not_allowed:
                if node.left.token.type == TokenType.ID:
                    left_symbol = self.symbol_table.get_token(node.left.value)
                    left_var_type = left_symbol.type.name
                else:
                    left_var_type = node.left.token.type.value

                if value_type_not_allowed:
                    right_var_type = right_symbol_token.name
                else:
                    right_var_type = right_symbol.type.name

                SemanticErrorHandler.type_error(left_var_type,
                                                right_var_type,
                                                token=node.right.token)

    def visit_UnaryOperator(self, node: UnaryOperator) -> None:
        """Calls the method that performs the Unary Operations.

        Args:
            node (UnaryOperator): node containing a Unary Operation
        """

        self.visit(node.expression)

        if isinstance(node.expression, (Var, Boolean, String)):
            expr_symbol = self.symbol_table.get_token(node.expression.value)

            if expr_symbol is None:
                SemanticErrorHandler.type_error(
                    node.expression.token.type.name,
                    token=node.expression.token)

            if not self.type_checker.is_allowed_type(Context.UN_OP,
                                                     expr_symbol.type.name):
                SemanticErrorHandler.type_error(expr_symbol.type.name,
                                                token=node.expression.token)

    def visit_Writeln(self, node: Writeln) -> None:
        """Calls the methods according to content type and check if they are valid.

        Args:
            node (Writeln): content passed in the command writeln
        """

        for index, item in enumerate(node.content):
            previous_content = node.content[index - 1]
            if previous_content == item:
                self.visit(item)
            elif isinstance(
                    previous_content,
                (UnaryOperator,
                 BinaryOperator)) and not self.type_checker.is_allowed_type(
                     Context.BIN_OP, item.value):
                node_name = previous_content.__class__.__name__
                SemanticErrorHandler.type_error(node_name,
                                                item.token.type.name,
                                                token=item.token)

    def visit_Num(self, node: Num) -> None:
        pass

    def visit_String(self, node: String) -> None:
        pass

    def visit_Boolean(self, node: Boolean) -> None:
        pass

    def visit_Empty(self, node: Empty) -> None:
        pass
示例#7
0
def main():
    """
    Transforms a program written in assembly code into binary machine code
    that can be run on the Hack hardware.
    """
    if len(sys.argv) < 2:
        raise Exception("Usage: python HackAssembler.py filename")

    filename = sys.argv[1]
    hack_filename = re.sub('.asm$', '.hack', filename)

    try:
        # Initiate a parser and binary output file.
        hackfile = open(hack_filename, 'w')
        parser = Parser(filename)

        # Initiate a code and symbol table modules.
        code = Code()
        table = SymbolTable()

        # Determines the ROM count (actuall program instructions). Incremented
        # whenever a C-instruction or an A-instruction is encountered.
        instructions_count = 0

        # First pass - build the symbol table without generating any code
        while parser.has_more_commands():
            parser.advance()

            command = parser.current_command
            t = parser.command_type()

            if t == 'L_COMMAND':
                # Add a new entry to the symbol table, associating
                # Xxx with the ROM address that will eventually
                # store the next command in the program
                symbol = parser.symbol()
                table.add_entry(symbol, instructions_count)
            else:
                instructions_count += 1

        # Second pass - Parse each line
        parser.rollback()
        while parser.has_more_commands():
            parser.advance()
            command = parser.current_command

            output = None
            t = parser.command_type()

            # Create a binary representation of the current
            # command according to the Hack contract.
            if t == 'C_COMMAND':
                comp = code.comp(parser.comp())
                dest = code.dest(parser.dest())
                jump = code.jump(parser.jump())
                output = '111' + comp + dest + jump

            elif t == 'A_COMMAND':
                symbol = parser.symbol()

                if not symbol.isdigit():
                    if not table.contains(symbol):
                        table.add_entry(symbol, table.next_ram_addr)
                        table.next_ram_addr += 1

                    # Get the symbol numeric meaning
                    symbol = table.symbols[symbol]

                output = format(int(symbol), '016b')

            if output is not None:
                hackfile.write(output + '\n')

        print "Done writing (binary) hack file: {0}".format(hack_filename)
        hackfile.close()
    except IOError, err:
        print "Encountered an I/O Error:", str(err)
示例#8
0
##################################
# IMPORTS
##################################

from numbers import Number
from symbols import SymbolTable
from lexer import Lexer
from parse import Parser
from interpreter import Interpreter
from context import Context

##################################
# RUN
##################################
global_symbol_table = SymbolTable()
global_symbol_table.set('NULL', Number(0))
global_symbol_table.set('TRUE', Number(1))
global_symbol_table.set('FALSE', Number(0))


def run(fn, text):
    lexer = Lexer(fn, text)
    tokens, error = lexer.make_tokens()
    if error: return None, error

    #Generate Abstract Syntax Tree
    parser = Parser(tokens)
    ast = parser.parse()
    if ast.error: return None, ast.error

    #Run the AST through the Interpreter
示例#9
0
def main(argc, argv):

    if argc != 5:
        fatal(
            'Usage: %s <hooks file/directory> <symbol table> <symbol table offset> <output ips>'
            % argv[0])

    # Parse relocate symbol table
    if os.path.isfile(argv[2]) == False:
        fatal("Symbol table file does not exist!")

    try:
        sym_offset = int(argv[3], 0)
    except:
        fatal("Symbol table offset is invalid!")

    try:
        sym_table = SymbolTable.from_file(argv[2], True, sym_offset)
    except:
        fatal('Opening symbol table failed!')

    # Load hooks
    hks_path = argv[1]

    hooks = []

    if os.path.isfile(hks_path):
        hooks += load_hooks(hks_path)

    elif os.path.isdir(hks_path):
        for file in os.listdir(hks_path):
            hks_file = os.fsdecode(file)
            if hks_file.endswith(".hks"):
                hooks += load_hooks(os.path.join(hks_path, hks_file))

    else:
        fatal("Hooks path is invalid!")

    # Apply hooks
    out_path = argv[4]

    try:
        out_file = open(out_path, "wb")
    except:
        fatal('Opening output file failed!')

    ips32.write_header(out_file)

    for hook in hooks:
        try:
            hook.write_ips(out_file, sym_table)
        except Exception as e:
            cprint(
                '%s:%d: applying hook \"%s\" failed: %s' %
                (hook.path, hook.line, hook.name, str(e)), 'red')

    ips32.write_eof(out_file)

    out_file.close()

    print('Hook IPS written to %s' % out_path)
示例#10
0
 def __init__(self):
     self.symbol_table = SymbolTable(None, None)
     self.should_stop_processing = False
示例#11
0
 def __init__(self):
     self.var_counter = 0
     self.if_counter = 0
     self.while_counter = 0
     self.symbols = SymbolTable()