Esempio n. 1
0
def compiler(showSource, input_file, output_file):
    """This function goes through the classic phases of a modern compiler,
    each phase organized in its own module. The phases are:

    parsing:
        handled using the ply package - the parser module includes a lexer,
        and it builds an abstract syntax tree (AST).

    symbol collection:
        collects function, parameter, and variables names, and stores these
        in a symbol table.

    code generation:
        from the AST and symbol table, code is produced in an intermediate
        representation, quite close to the final assembler code.

    emit:
        the slightly abstract intermediate code is transformed to assembler
        code.
    """

    # Read and verify ASCII input:
    encodingError = False
    try:
        if input_file:
            with open(input_file) as f:
                text = f.read()
        else:
            text = sys.stdin.read()
        try:
            text.encode("ascii")
        except UnicodeEncodeError:  # Check for non-ascii
            encodingError = True
    except UnicodeDecodeError:  # Check for unicode
        encodingError = True
    if encodingError:
        error_message("Set-Up", "The input is not in ASCII.", 1)

    # Parse input text:
    parser.parse(text)

    # the_program is the resulting AST:
    if interfacing_parser.parsing_error:
        exit()
    the_program = interfacing_parser.the_program

    if showSource:

        # Pretty print program:
        pp = ASTPrettyPrinterVisitor()
        the_program.accept(pp)
        return pp.getPrettyProgram()

    else:

        # Collect names of functions, parameters, and local variables:
        symbols_collector = ASTSymbolVisitor()
        the_program.accept(symbols_collector)
        symbol_table = symbols_collector.getSymbolTable()

        # Type check use of functions, parameters, and local variables:
        type_checker = ASTTypeCheckingVisitor(symbol_table)
        the_program.accept(type_checker)

        # Assign unique labels to functions:
        pre_intermediate_code_generator = ASTPreCodeGenerationVisitor()
        the_program.accept(pre_intermediate_code_generator)

        # Generate intermediate code:
        intermediate_code_generator = ASTCodeGenerationVisitor(
            symbol_table, pre_intermediate_code_generator.getLabelsGenerator())
        the_program.accept(intermediate_code_generator)
        intermediate_code = intermediate_code_generator.get_code()

        # Emit the target code:
        emitter = Emit(intermediate_code,
                       pre_intermediate_code_generator.getLabelsGenerator())
        emitter.emit()
        code = emitter.get_code()

        return code