コード例 #1
0
    def var_assign(self):
        result = ParseResult()

        if self.current_token.type != Token.IDENTIFIER:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   'Expected identifier'))

        var_name = self.current_token
        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.EQ:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected '='"))

        result.register_advancement()
        self.advance()

        var_value = result.register(self.var_value())
        if result.error: return result

        if self.current_input_token.type == Token.COMMA and self.current_input_token != Token.EOL:
            self.input_advance()

        return result.success(VarAssignNode(var_name, var_value))
コード例 #2
0
    def comp_expr(self):
        result = ParseResult()

        if self.current_token.matches(Token.KEYWORD, Token.NOT):
            operator_token = self.current_token
            result.register_advancement()
            self.advance()

            node = result.register(self.comp_expr())
            if result.error: return result
            return result.success(UnaryOperatorNode(operator_token, node))

        node = result.register(
            self.binary_operation(self.arith_expr,
                                  (Token.EE, Token.NE, Token.LT, Token.GT,
                                   Token.LTE, Token.GTE)))

        if result.error:
            return result.failure(
                InvalidSyntaxError(
                    self.current_token.pos_start,
                    "Expected int, float, char, bool, identifier, '+', '-', '(', 'NOT', 'IF', or 'WHILE'"
                ))

        return result.success(node)
コード例 #3
0
    def if_expr_b_or_c(self):
        result = ParseResult()
        cases, else_case = [], None

        if self.current_token.matches(Token.KEYWORD, Token.ELIF):
            all_cases = result.register(self.if_expr_b())
            if result.error: return result
            cases, else_case = all_cases
        elif self.current_token.matches(Token.KEYWORD, Token.ELSE):
            else_case = result.register(self.if_expr_c())
            if result.error: return result

        return result.success((cases, else_case))
コード例 #4
0
    def factor(self):
        result = ParseResult()
        token = self.current_token

        if token.type in (Token.PLUS, Token.MINUS):
            result.register_advancement()
            self.advance()
            factor = result.register(self.factor())
            if result.error: return result
            return result.success(UnaryOperatorNode(token, factor))

        return self.atom()
コード例 #5
0
    def expr(self):
        result = ParseResult()

        if self.current_token.type == Token.IDENTIFIER:
            var_name = self.current_token

        node = result.register(
            self.binary_operation(self.comp_expr, ((Token.KEYWORD, Token.AND),
                                                   (Token.KEYWORD, Token.OR))))
        if result.error: return result

        if self.current_token.type == Token.EQ:
            result.register_advancement()
            self.advance()

            expr = result.register(self.expr())
            if result.error: return result
            return result.success(VarAssignNode(var_name, expr))

        return result.success(node)
コード例 #6
0
    def binary_operation(self, func_a, ops, func_b=None):
        if func_b == None: func_b = func_a

        result = ParseResult()
        left = result.register(func_a())
        if result.error: return result

        while self.current_token.type in ops or (
                self.current_token.type, self.current_token.value) in ops:
            operator_token = self.current_token
            result.register_advancement()
            self.advance()

            right = result.register(func_b())
            if result.error: return result
            left = BinaryOperatorNode(left, operator_token, right)

        return result.success(left)
コード例 #7
0
    def while_expr(self):
        result = ParseResult()
        body = []

        if not self.current_token.matches(Token.KEYWORD, Token.WHILE):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'WHILE'"))

        result.register_advancement()
        self.advance()

        condition = result.register(self.expr())
        if result.error: return result

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.START):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'START'"))

        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        while True:
            # TODO check bool expr if it has a counter in the body
            statement = result.register(self.statement())
            if result.error: return result
            body.append(statement)

            if self.current_token.type != Token.NEWLINE:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Expected 'NEWLINE'"))

            result.register_advancement()
            self.advance()

            while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
                result.register_advancement()
                self.advance()

            if self.current_token.matches(Token.KEYWORD, Token.STOP):
                result.register_advancement()
                self.advance()
                break

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        return result.success(WhileNode(condition, body))
コード例 #8
0
    def if_expr_cases(self, case_keyword):
        result = ParseResult()
        cases = []
        else_case = None

        if not self.current_token.matches(Token.KEYWORD, case_keyword):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   f"Expected '{case_keyword}'"))

        result.register_advancement()
        self.advance()

        condition = result.register(self.expr())
        if result.error: return result

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.START):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'START'"))

        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        while True:
            # TODO proceed if-elif conditionals without statements
            statement = result.register(self.statement())
            if result.error: return result
            cases.append((condition, statement))

            if self.current_token.type != Token.NEWLINE:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Expected 'NEWLINE'"))

            result.register_advancement()
            self.advance()

            while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
                result.register_advancement()
                self.advance()

            if self.current_token.matches(Token.KEYWORD, Token.STOP):
                result.register_advancement()
                self.advance()
                break

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        all_cases = result.register(self.if_expr_b_or_c())
        if result.error: return result
        new_cases, else_case = all_cases
        cases.extend(new_cases)

        return result.success((cases, else_case))
コード例 #9
0
    def statements(self):
        result = ParseResult()
        statements = []
        pos_start = self.current_token.pos_start.copy()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.START):
            statement = result.register(self.var_statement())
            if result.error: return result
            statements.extend(statement)

            more_var_statements = True

            while True:
                newline_count = 0
                while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
                    result.register_advancement()
                    self.advance()
                    newline_count += 1
                if newline_count == 0:
                    more_var_statements = False

                if not more_var_statements or self.current_token.matches(
                        Token.KEYWORD, Token.START):
                    break
                statement = result.register(self.var_statement())
                if result.error: return result
                statements.extend(statement)

        if self.current_token.type == Token.EOL:
            return result.success(ListNode(statements, pos_start))

        pos_start = self.current_token.pos_start.copy()

        if not self.current_token.matches(Token.KEYWORD, Token.START):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'START'"))

        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.OUTPUT):
            statement = result.register(self.statement())
            if result.error: return result
            statements.append(statement)

        more_statements = True

        while True:
            newline_count = 0
            while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
                result.register_advancement()
                self.advance()
                newline_count += 1
            if newline_count == 0:
                more_statements = False

            # TODO evaluate the output variables with its data types
            if self.current_token.matches(Token.KEYWORD, Token.OUTPUT):
                var_name = self.current_token
                result.register_advancement()
                self.advance()

                if self.current_token.type != Token.COLON:
                    return result.failure(
                        InvalidSyntaxError(self.current_token.pos_start,
                                           "Expected 'COLON'"))

                result.register_advancement()
                self.advance()

                output = result.register(self.expr())
                if result.error:
                    return result.failure(
                        InvalidSyntaxError(self.current_token.pos_start,
                                           "Invalid output statement"))

                statements.append(VarAssignNode(var_name, output))

                if self.current_token.type != Token.NEWLINE:
                    return result.failure(
                        InvalidSyntaxError(self.current_token.pos_start,
                                           "Expected 'NEWLINE'"))

                result.register_advancement()
                self.advance()

            if self.current_token.type == Token.EOL:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Expected 'STOP'"))

            if not more_statements or self.current_token.matches(
                    Token.KEYWORD, Token.STOP):
                break
            statement = result.register(self.statement())
            if result.error: return result
            statements.append(statement)

        if not self.current_token.matches(Token.KEYWORD, Token.STOP):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'STOP'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()
            if self.current_token.type == Token.EOL: break

        return result.success(ListNode(statements, pos_start))
コード例 #10
0
    def if_expr_c(self):
        result = ParseResult()
        else_case = None

        if not self.current_token.matches(Token.KEYWORD, Token.ELSE):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'ELSE'"))

        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.START):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'START'"))

        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        while True:
            # TODO proceed else conditional without statements
            statement = result.register(self.statement())
            if result.error: return result
            else_case = statement

            if self.current_token.type != Token.NEWLINE:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Expected 'NEWLINE'"))

            result.register_advancement()
            self.advance()

            while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
                result.register_advancement()
                self.advance()

            if self.current_token.matches(Token.KEYWORD, Token.STOP):
                result.register_advancement()
                self.advance()
                break

        if self.current_token.type != Token.NEWLINE:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'NEWLINE'"))

        result.register_advancement()
        self.advance()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        return result.success(else_case)
コード例 #11
0
 def if_expr(self):
     result = ParseResult()
     all_cases = result.register(self.if_expr_cases(Token.IF))
     if result.error: return result
     cases, else_case = all_cases
     return result.success(IfNode(cases, else_case))
コード例 #12
0
    def atom(self):
        result = ParseResult()
        token = self.current_token

        if token.type in (Token.INT, Token.FLOAT):
            result.register_advancement()
            self.advance()
            return result.success(NumberNode(token))

        elif token.type in (Token.CHAR, Token.CONCAT):
            result.register_advancement()
            self.advance()
            return result.success(StringNode(token))

        elif token.type == Token.BOOL:
            result.register_advancement()
            self.advance()
            return result.success(BoolNode(token))

        elif token.type == Token.IDENTIFIER:
            result.register_advancement()
            self.advance()
            return result.success(VarAccessNode(token))

        elif token.type == Token.LPAREN:
            result.register_advancement()
            self.advance()

            expr = result.register(self.expr())
            if result.error: return result

            if self.current_token.type != Token.RPAREN:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Expected ')'"))

            result.register_advancement()
            self.advance()
            return result.success(expr)

        elif token.matches(Token.KEYWORD, Token.IF):
            if_expr = result.register(self.if_expr())
            if result.error: return result
            return result.success(if_expr)

        elif token.matches(Token.KEYWORD, Token.WHILE):
            while_expr = result.register(self.while_expr())
            if result.error: return result
            return result.success(while_expr)

        return result.failure(
            InvalidSyntaxError(token.pos_start, "Expected expr"))
コード例 #13
0
    def statement(self):
        result = ParseResult()

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if self.current_token.value in Token.KEYWORDS:
            expr = result.register(self.expr())
            if result.error:
                return result.failure(
                    InvalidSyntaxError(self.current_token.pos_start,
                                       "Invalid expr"))

            return result.success(expr)

        if self.current_token.type != Token.IDENTIFIER:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected identifier"))

        var_name = self.current_token
        result.register_advancement()
        self.advance()

        if self.current_token.type != Token.EQ:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected '='"))

        result.register_advancement()
        self.advance()

        expr = result.register(self.expr())
        if result.error:
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Invalid statement"))

        return result.success(VarAssignNode(var_name, expr))
コード例 #14
0
    def var_value(self):
        result = ParseResult()
        token = self.current_token
        if self.current_input_token.type in (
                Token.INT, Token.FLOAT, Token.CHAR,
                Token.BOOL) and self.current_input_token != Token.EOL:
            token = self.current_input_token
            self.input_advance()

        if token.type in (Token.INT, Token.FLOAT):
            result.register_advancement()
            self.advance()
            return result.success(NumberNode(token))
        elif token.type == Token.CHAR:
            result.register_advancement()
            self.advance()
            return result.success(StringNode(token))
        elif token.type == Token.BOOL:
            result.register_advancement()
            self.advance()
            return result.success(BoolNode(token))
        elif token.type == Token.IDENTIFIER:
            result.register_advancement()
            self.advance()
            return result.success(VarAccessNode(token))
        else:
            return result.failure(
                InvalidSyntaxError(
                    token.pos_start,
                    "Expected int, float, char, bool, or identifier"))
コード例 #15
0
    def var_statement(self):
        result = ParseResult()
        variables = []

        while self.current_token.type == Token.NEWLINE or self.current_token.type == Token.COMMENT:
            result.register_advancement()
            self.advance()

        if not self.current_token.matches(Token.KEYWORD, Token.VAR):
            return result.failure(
                InvalidSyntaxError(self.current_token.pos_start,
                                   "Expected 'VAR'"))

        result.register_advancement()
        self.advance()

        while True:
            var_assign = result.register(self.var_assign())
            if result.error: return result
            variables.append(var_assign)

            if self.current_token.type == Token.COMMA:
                result.register_advancement()
                self.advance()
            else:
                if not self.current_token.matches(Token.KEYWORD, Token.AS):
                    return result.failure(
                        InvalidSyntaxError(self.current_token.pos_start,
                                           "Expected 'AS'"))

                result.register_advancement()
                self.advance()

                if self.current_token.type != Token.DATA_TYPE:
                    return result.failure(
                        InvalidSyntaxError(self.current_token.pos_start,
                                           "Invalid 'DATA_TYPE'"))

                result.register_advancement()
                self.advance()

                return result.success(variables)

        return result.failure(
            InvalidSyntaxError(
                self.current_token.pos_start,
                "Expected 'VAR', int, float, char, bool, identifier, 'AS', 'DATA_TYPE'"
            ))