Esempio n. 1
0
    def visit_this_expr(self, expr):
        if self.current_class == ClassType.NONE:
            Error.error(expr.keyword, "Cannot use 'this' outside of a class.")
            return None

        self.resolve_local(expr, expr.keyword)
        return None
Esempio n. 2
0
    def visit_class_stmt(self, stmt):
        enclosing_class = self.current_class
        self.current_class = ClassType.CLASS

        self.declare(stmt.name)
        self.define(stmt.name)

        if stmt.superclass is not None:
            if stmt.name.lexem == stmt.superclass.name.lexem:
                Error.error(stmt.superclass.name,
                            "A class cannot inherit from itself.")
            else:
                self.current_class = ClassType.SUBCLASS
                self.resolve(stmt.superclass)
                self.begin_scope()
                self.scopes[-1]["super"] = True

        self.begin_scope()
        self.scopes[-1]["this"] = True

        for method in stmt.methods:
            declaration = Function.method
            if method.name.lexem == "init":
                declaration = Function.initializer
            self.resolve_function(method, declaration)

        self.end_scope()

        if stmt.superclass is not None:
            self.end_scope()

        self.current_class = enclosing_class
        return None
Esempio n. 3
0
 def interpret(self, statements):
     try:
         for statement in statements:
             if statement is not None:
                 self.execute(statement)
     except RuntimeException as error:
         Error.runtime_error(error)
Esempio n. 4
0
    def visit_variable_expr(self, expr):
        if not len(self.scopes) == 0 and self.scopes[-1].keys().__contains__(expr.name.lexem) and \
                not self.scopes[-1][expr.name.lexem]:
            Error.error(expr.name,
                        "Cannot read local variable in its own initializer.")

        self.resolve_local(expr, expr.name)
        return None
Esempio n. 5
0
 def visit_super_expr(self, expr):
     if self.current_class == ClassType.NONE:
         Error.error(expr.keyword, "Cannot use 'super' outside of a class.")
     elif self.current_class != ClassType.SUBCLASS:
         Error.error(
             expr.keyword,
             "Cannot use 'super' in a class without a super class.")
     self.resolve_local(expr, expr.keyword)
     return None
Esempio n. 6
0
    def visit_return_stmt(self, stmt):
        if self.current_function == Function.none:
            Error.error(stmt.keyword, "Cannot return from top-level code")

        if stmt.value is not None:
            if self.current_function == Function.initializer:
                Error.error(stmt.keyword, "Cannot return from an initializer.")
            self.resolve(stmt.value)

        return None
Esempio n. 7
0
 def scan_token(self):
     c = self.advance()
     if c == '(':
         self.add_token(TokenType.LEFT_PAREN)
     elif c == ')':
         self.add_token(TokenType.RIGHT_PAREN)
     elif c == '{':
         self.add_token(TokenType.LEFT_BRACE)
     elif c == '}':
         self.add_token(TokenType.RIGHT_BRACE)
     elif c == ',':
         self.add_token(TokenType.COMMA)
     elif c == '.':
         self.add_token(TokenType.DOT)
     elif c == '-':
         self.add_token(TokenType.MINUS)
     elif c == '%':
         self.add_token(TokenType.MODULO)
     elif c == '+':
         self.add_token(TokenType.PLUS)
     elif c == ';':
         self.add_token(TokenType.SEMICOLON)
     elif c == '*':
         self.add_token(TokenType.STAR)
     elif c == '!':
         self.add_token(
             TokenType.BANG_EQUAL if self.match('=') else TokenType.BANG)
     elif c == '=':
         self.add_token(
             TokenType.EQUAL_EQUAL if self.match('=') else TokenType.EQUAL)
     elif c == '<':
         self.add_token(
             TokenType.LESS_EQUAL if self.match('=') else TokenType.LESS)
     elif c == '>':
         self.add_token(TokenType.GREATER_EQUAL if self.
                        match('=') else TokenType.GREATER)
     elif c == '/':
         if self.match('/'):
             while (not self.peek() == '\n') and not self.is_at_end():
                 self.advance()
         else:
             self.add_token(TokenType.SLASH)
     elif c == ' ' or c == '\r' or c == '\t':
         return
     elif c == '"':
         self.string()
     elif c == '\n':
         self.line += 1
     else:
         if c.isdigit():
             self.number()
         elif c.isalpha() or c == '_':
             self.identifier()
         else:
             Error.error(self.line, "Unexpected character.")
Esempio n. 8
0
    def declare(self, name):
        if len(self.scopes) == 0:
            return

        scope = self.scopes[-1]
        if scope.keys().__contains__(name.lexem):
            Error.error(
                name,
                "Variable with this name already declared in this scope.")

        scope[name.lexem] = False
Esempio n. 9
0
    def string(self):
        while not self.peek() == '"' and not self.is_at_end():
            if self.peek() == '\n':
                self.line += 1
            self.advance()

        if self.is_at_end():
            Error.error(self.line, "Unterminated string.")
            return

        self.advance()

        value = self.source[self.start + 1:self.current - 1]
        self.add_token(TokenType.STRING, value)
Esempio n. 10
0
 def error(token, message):
     Error.error(token, message)
     raise ParseError()