예제 #1
0
파일: lox.py 프로젝트: tonyallan/pylox
class Lox:
    def __init__(self):
        self.interpreter = Interpreter()
        self.error = LoxError()

    def run_prompt(self):
        errors = []
        s = input("lox >")
        if s != "exit":
            if s[len(s) - 1] is not ";":
                s = s + ";"
            self.run(s, errors)
            self.run_prompt()

    def run_files(self, files):
        errors = []
        for file in files:
            try:
                with open(file, 'r') as f:
                    source = f.read()
                    lox.run(source, errors)
            except:
                print("cannot read file {}".format(file))

    def run(self, source, errors):
        #print("source : \n{}".format(source))
        tokens = []
        statements = []
        scan_tokens(source, {
            'start': 0,
            'current': 0,
            'line': 1
        }, tokens, errors)
        if len(tokens) is 1:
            if tokens[0].type is Tk.EOF:
                LoxError.error(tokens[0], "Source file is empty.")
        parser = Parser(tokens)
        # print("Tokens:\n")
        # for t in tokens:
        #     print(t)
        #print("Lox: ready to parse")
        statements = parser.parse()
        #print("Lox: ready to resolve")
        resolver = Resolver(self.interpreter)
        resolver.resolvelist(statements)
        if LoxError.haderror:
            print("Syntax errors detected during compilation")
            return
        #print("Lox: ready to interpret")
        self.interpreter.interpret(statements)
예제 #2
0
class Lox:
    def __init__(self):
        self.had_error = False
        self.had_runtime_error = False
        self.interpreter = Interpreter(self)
        self.resolver = Resolver(self, self.interpreter)

    def _report(self, line, where, message):
        # Should we pipe to `sys.stderr`?
        print(f'[Line {line}] Error{where}: {message}')

    def error(self, token, message):
        self.had_error = True
        if token.tokentype == TokenType.EOF:
            self._report(token.line, " at end", message)
        else:
            self._report(token.line, f" at '{token.lexeme}'", message)

    def runtime_error(self, err):
        print(f'[Line {err.token.line}] {err}')
        self.had_runtime_error = True

    def run_file(self, filename):
        with open(filename, 'r') as f:
            self.run(f.read())

        EXIT_CODE = 0
        if self.had_error:
            EXIT_CODE = 64
        elif self.had_runtime_error:
            EXIT_CODE = 70
        sys.exit(EXIT_CODE)

    def run_prompt(self):
        while True:
            reader = input('> ')
            self.run(reader)
            self.had_error = False

    def run(self, source):
        scanner = Scanner(source, self)
        tokens = scanner.scan_tokens()
        statements = Parser(tokens, self).parse()
        if self.had_error:
            return
        resolver = self.resolver.resolve(statements)
        if self.had_error:
            return
        self.interpreter.interpret(statements)
예제 #3
0
def test_interpreter():
    from lox.scanner import Scanner
    from lox.parser import Parser
    from lox.ast.ast_printer import ASTPrinter
    from lox.interpreter import Interpreter

    source = """ 1 + 999 """

    lox_scan = Scanner(source)

    tokens = lox_scan.scanTokens()

    print("Tokens:")
    for tok in tokens:
        print(tok)
    print("\n")

    lox_parser = Parser(tokens)
    result = lox_parser.parse()

    printer = ASTPrinter()

    print(printer.print(result))

    print(Interpreter().evaluate(result))
예제 #4
0
def run(source):
    scan = Scanner(source)
    tokens = scan.scanTokens()

    # for token in tokens:
    #     print(token)

    pars = Parser(tokens)
    result = pars.parse()

    print(ASTPrinter().print(result))
    print(Interpreter().interpret(result))
예제 #5
0
class Lox:
    has_error = False
    has_runtime_error = False

    def __init__(self):
        self.interpreter = Interpreter(report_error=self.runtime_error)

    def run_code(self, source_code):
        scanner = Scanner(source_code, self.error)
        tokens = scanner.scan_tokens()

        parser = Parser(tokens, self.error_token)
        expr = parser.parse()

        if Lox.has_error:
            return

        # print(AstPrinter().print(expr))
        self.interpreter.interpret(expr)

    def run_file(self, path):
        with open(path, 'r') as file:
            code_lines = file.readlines()

        code = '\n'.join(code_lines)
        self.run_code(code)

        if self.has_error:
            exit(65)
        if self.has_runtime_error:
            exit(70)

    def run_prompt(self, ):
        while True:
            self.run_code(input('>'))
            Lox.has_error = False
            Lox.has_runtime_error = False

    def run(self):
        if len(sys.argv) > 2:
            print("Usage: pylox [script]")
            exit(64)
        elif len(sys.argv) == 2:
            self.run_file(sys.argv[1])
        else:
            self.run_prompt()

    @staticmethod
    def error(line: int, message: str):
        Lox.report(line, "", message)

    @staticmethod
    def error_token(token: Token, message: str):
        if token.type == TokenType.EOF:
            Lox.report(token.line, 'at end', message)
        else:
            Lox.report(token.line, f'at "{token.lexeme}"', message)

    @staticmethod
    def runtime_error(error: LoxRuntimeError):
        Lox.has_runtime_error = True
        print(f'[line {error.token.line}] {error.message}')

    @staticmethod
    def report(line: int, where: str, message: str):
        Lox.has_error = True
        print(f'[line {line}] Error {where}: {message}')
예제 #6
0
 def __init__(self):
     self.interpreter = Interpreter(report_error=self.runtime_error)
예제 #7
0
 def __init__(self):
     self.had_error = False
     self.had_runtime_error = False
     self.interpreter = Interpreter(self)
     self.resolver = Resolver(self, self.interpreter)
예제 #8
0
파일: lox.py 프로젝트: tonyallan/pylox
 def __init__(self):
     self.interpreter = Interpreter()
     self.error = LoxError()
예제 #9
0
파일: lox.py 프로젝트: ehomrich/lox
class Lox:
    interpreter = Interpreter()
    had_error = False
    had_runtime_error = False

    @staticmethod
    def repl_intro() -> None:
        python_version = '.'.join(str(i) for i in version_info[:3])

        print('Lox REPL',
              f'[CPython {python_version}] on {platform}',
              'Type "copyright", "credits" or "license" for more information.',
              'Type "exit" or press Ctrl-D (i.e. EOF) to leave.',
              sep='\n')

    @staticmethod
    def usage(code: int) -> None:
        print('Usage: lox [file]')
        exit(code)

    @staticmethod
    def report(line: int, where: str, message: str) -> None:
        print(f'[line {line}] Error{where}: {message}')

        Lox.had_error = True

    @staticmethod
    def error(token: Token, message: str) -> None:
        if token.type == TokenType.EOF:
            Lox.report(token.line, ' at end', message)
        else:
            Lox.report(token.line, f" at '{token.lexeme}'", message)

    @staticmethod
    def runtime_error(error: LoxRuntimeError) -> None:
        print(f'{error}\n[line {error.token.line}]')

        Lox.had_runtime_error = True

    @staticmethod
    def run(source: str) -> None:
        try:
            scanner = Scanner(source)
            tokens = scanner.scan_tokens()
            parser = Parser(tokens)
            stmts = parser.parse()

            Lox.interpreter.interpret(stmts)
        except ParseError as pe:
            Lox.error(pe.token, str(pe))
        except LoxRuntimeError as lre:
            Lox.runtime_error(lre)

    @staticmethod
    def run_file(filename) -> None:
        path = Path(filename).absolute()
        source = path.read_text(encoding='utf-8', errors='strict')
        Lox.run(source)

        if Lox.had_error:
            exit(65)
        elif Lox.had_runtime_error:
            exit(70)

    @staticmethod
    def prompt() -> None:
        Lox.repl_intro()

        while True:
            try:
                print('>>> ', end='')

                expr = input()
                first = expr.split(' ')[0]

                if first in COMMANDS:
                    COMMANDS[first]()
                else:
                    Lox.run(expr)
                    Lox.had_error = False
                    Lox.had_runtime_error = False
            except KeyboardInterrupt as ki:
                print(f'\n{ki.__class__.__name__}')
            except EOFError:
                exit(0)