Beispiel #1
0
    def atom(self):
        res = ParseResult()
        tok = self.current_token

        if tok.type in (TT_INT, TT_FLOAT):
            res.register(self.advance())
            return res.success(NumberNode(tok))

        elif tok.type == TT_LPAREN:
            res.register(self.advance())
            expr = res.register(self.expr())

            if res.error:
                return res

            if self.current_token.type == TT_RPAREN:
                res.register(self.advance())
                return res.success(expr)
            else:
                return res.failure(InvalidSyntaxError(
                    self.current_token.pos_start, self.current_token.pos_end,
                    "Expected ')'"
                ))

        return res.failure(InvalidSyntaxError(
            tok.pos_start, tok.pos_end,
            "Expected INT, FLOAT, '+', '-' or '('"
        ))
Beispiel #2
0
    def atom(self):
        res = ParseResult()
        token = self.current_token

        if token._type in [TokenTypes.TT_INT, TokenTypes.TT_FLOAT]:
            res.register_advancement()
            self.advance()
            return res.success(NumberNode(token))

        elif token.get_type() == TokenTypes.TT_IDENTIFIER:
            res.register_advancement()
            self.advance()
            return res.success(VariableAccessNode(token))

        elif token._type == TokenTypes.TT_LPAREN:
            res.register_advancement()
            self.advance()
            expr = res.register(self.expression())
            if res._error:
                return res
            if self.current_token._type == TokenTypes.TT_RPAREN:
                res.register_advancement()
                self.advance()
                return res.success(expr)
            else:
                return res.failed(
                    InvalidSyntaxError(self.current_token._start_pos,
                                       self.current_token._end_pos,
                                       "Expected ')'"))
        return res.failed(
            InvalidSyntaxError(
                self.current_token._start_pos, self.current_token._end_pos,
                "Expected INT, FLOAT, IDENTIFIER, '+', '-', '*' or '('"))
Beispiel #3
0
    def if_expr_cases(self, case_keyword):
        res = ParseResult()
        cases = []
        else_case = None

        if not self.current_tok.matches(Constants.TOK_KEYWORD, case_keyword):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected '{case_keyword}'"
            ))

        res.register_advancement()
        self.advance()

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

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'then'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected 'then'"
            ))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == Constants.TOK_NEWLINE:
            res.register_advancement()
            self.advance()

            statements = res.register(self.statements())
            if res.error:
                return res
            cases.append((condition, statements, True))

            if self.current_tok.matches(Constants.TOK_KEYWORD, 'end'):
                res.register_advancement()
                self.advance()
            else:
                all_cases = res.register(self.if_expr_b_or_c())
                if res.error:
                    return res
                new_cases, else_case = all_cases
                cases.extend(new_cases)
        else:
            expr = res.register(self.statement())
            if res.error:
                return res
            cases.append((condition, expr, False))

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

        return res.success((cases, else_case))
    def factor(self):
        position_start = self.current_tok.position_start
        tok = self.current_tok

        if tok.type == LPAREN:
            self.advance()

            result = self.parse_math_expression()
            if self.current_tok.type != RPAREN:
                self.errors.register_error(
                    InvalidSyntaxError(
                        "Expected ')'",
                        self.current_tok.position_start,
                        self.current_tok.position_end,
                    ))
                return None
            self.advance()
            return result
        elif tok.type == INT or tok.type == FLOAT:
            self.advance()
            return NumberNode(tok, position_start,
                              self.current_tok.position_end)
        elif tok.type == STRING:
            self.advance()
            return StringNode(tok, position_start,
                              self.current_tok.position_end)
        elif tok.type == IDENTIFIER:
            self.advance()
            return IdentifierNode(tok, position_start,
                                  self.current_tok.position_end)
        elif tok.type in (PLUS, MINUS) or tok.matches(KEYWORD, "nu"):
            op_tok = self.current_tok
            self.advance()
            right = self.factor()
            return UnaryOperationNode(op_tok, right, position_start,
                                      self.current_tok.position_end)
        elif tok.type == LSQUAREBRACKET:
            self.advance()

            result = self.parse_math_expression()
            if self.current_tok.type != RPAREN:
                self.errors.register_error(
                    InvalidSyntaxError(
                        "Expected ']'",
                        self.current_tok.position_start,
                        self.current_tok.position_end,
                    ))
                return None
            self.advance()
            return IntCastNode(result)
        self.errors.register_error(
            InvalidSyntaxError(
                "Expected INT, IDENTIFIER, '+', '-', '(', '[', 'if'",
                self.current_tok.position_start,
                self.current_tok.position_end,
            ))
Beispiel #5
0
    def while_expr(self):
        res = ParseResult()

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'while'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'while\''
            ))
        res.register_advancement()
        self.advance()

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

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'then'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'then\''
            ))
        res.register_advancement()
        self.advance()


        if self.current_tok.type == Constants.TOK_NEWLINE:
            res.register_advancement()
            self.advance()

            body = res.register(self.statements())
            if res.error: return res

            if not self.current_tok.matches(Constants.TOK_KEYWORD, 'END'):
                return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected 'end'"
                ))

            res.register_advancement()
            self.advance()

            return res.success(WhileNode(condition, body, True))
        



        body = res.register(self.statement())
        if res.error:
            return res

        return res.success(WhileNode(condition, body, False))
Beispiel #6
0
    def if_expr_c(self):
        res = ParseResult()
        else_case = None

        if self.current_tok.matches(Constants.TOK_KEYWORD, 'else'):
            res.register_advancement()
            self.advance()

            if self.current_tok.type == Constants.TOK_NEWLINE:
                res.register_advancement()
                self.advance()

                statements = res.register(self.statements())
                if res.error:
                    return res
                else_case = (statements, True)

                if self.current_tok.matches(Constants.TOK_KEYWORD, 'end'):
                    res.register_advancement()
                    self.advance()
                else:
                    return res.failure(InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        "Expected 'end'"
                    ))
            else:
                expr = res.register(self.statement())
                if res.error:
                    return res
                else_case = (expr, False)

        return res.success(else_case)
Beispiel #7
0
    def comp_expr(self):
        res = ParseResult()
        if self.current_tok.matches(Constants.TOK_KEYWORD, 'not'):
            operator = self.current_tok
            res.register_advancement()
            self.advance()

            node = res.register(self.comp_expr())

            if res.error:
                return res
            return res.success(UnaryOperatorNode(operator, node))

        node = res.register(self.binary_operation(
            self.arith_expr,
                (Constants.TOK_EE,
                Constants.TOK_NE,
                Constants.TOK_LT,
                Constants.TOK_GT,
                Constants.TOK_LTE,
                Constants.TOK_GTE)))

        if res.error:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected int, float, identifier, operators'
            ))

        return res.success(node)
Beispiel #8
0
    def statement(self):
        res = ParseResult()
        pos_start = self.current_tok.pos_start.copy()

        if self.current_tok.matches(Constants.TOK_KEYWORD, 'return'):
            res.register_advancement()
            self.advance()

            expr = res.try_register(self.expr())
            if not expr:
                self.reverse(res.to_reverse_count)
            return res.success(ReturnNode(expr, pos_start, self.current_tok.pos_start.copy()))
        
        if self.current_tok.matches(Constants.TOK_KEYWORD, 'continue'):
            res.register_advancement()
            self.advance()
            return res.success(ContinueNode(pos_start, self.current_tok.pos_start.copy()))
        
        if self.current_tok.matches(Constants.TOK_KEYWORD, 'break'):
            res.register_advancement()
            self.advance()
            return res.success(BreakNode(pos_start, self.current_tok.pos_start.copy()))

        expr = res.register(self.expr())
        if res.error:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                "Expected 'return', 'continue', 'break', 'var', identifier, '+', '-', '(', '[' or 'not'"
            ))
        return res.success(expr)
    def parse_block_statement(self, end_token_types, end_token_values):
        position_start = self.current_tok.position_start

        self.advance()

        block = Block()
        while not self.current_tok.matches(end_token_types[0],
                                           end_token_values[0]):
            if len(end_token_types) == 2:
                if self.current_tok.matches(end_token_types[1],
                                            end_token_values[1]):
                    break

            while self.current_tok.type == NEWLINE:
                self.advance()

            if self.current_tok.type == EOF:
                self.errors.register_error(
                    InvalidSyntaxError(
                        "Unexpected end of file",
                        position_start,
                        self.current_tok.position_end,
                    ))
                return None

            stmt = self.parse_statement()

            if stmt:
                block.statements.append(stmt)

            while self.current_tok.type == NEWLINE:
                self.advance()

        return block
Beispiel #10
0
    def list_expr(self):
        res = ParseResult()
        element_nodes = []
        pos_start = self.current_tok.pos_start.copy()

        if self.current_tok.type != Constants.TOK_LSQUARE:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected '['"
            ))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == Constants.TOK_RSQUARE:
            res.register_advancement()
            self.advance()
        else:
            element_nodes.append(res.register(self.expr()))
            if res.error:
                return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                "Expected ']', 'VAR', 'IF', 'FOR', 'WHILE', 'FUN', int, float, identifier, '+', '-', '(', '[' or 'NOT'"
                ))

            while self.current_tok.type == Constants.TOK_COMMA:
                res.register_advancement()
                self.advance()

                element_nodes.append(res.register(self.expr()))
                if res.error: return res

            if self.current_tok.type != Constants.TOK_RSQUARE:
                return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected ',' or ']'"
                ))

            res.register_advancement()
            self.advance()

        return res.success(ListNode(
        element_nodes,
        pos_start,
        self.current_tok.pos_end.copy()
        ))
        
    def parse_declaration_statement(self):
        position_start = self.current_tok.position_start
        self.advance()
        if not self.current_tok.type == COLON:
            self.errors.register_error(
                InvalidSyntaxError("Expected ':'",
                                   self.current_tok.position_start,
                                   self.current_tok.position_end))
            return

        self.advance()

        elements = []
        types = []
        element = self.current_tok
        elements.append(element)

        self.advance()

        if self.is_type():
            types.append(self.current_tok.value)
            self.advance()

        while self.current_tok.type == COMMA:
            self.advance()
            element = self.current_tok
            self.advance()
            elements.append(element)

            if self.is_type():
                types.append(self.current_tok.value)
                self.advance()

        if len(types) == 1:
            t = types[0]
            for _ in range(len(elements) - 1):
                types.append(t)

        if len(types) != len(elements):
            self.errors.register_error(
                InvalidSyntaxError(
                    "The length of elements mismatch the length of types.",
                    position_start, self.current_tok.position_end))
            return None

        return DeclarationNode(elements, types, position_start,
                               self.current_tok.position_end)
Beispiel #12
0
 def parse(self):
     res = self.expr()
     if not res.error and self.current_token.type != TT_EOF:
         return res.failure(InvalidSyntaxError(
             self.current_token.pos_start, self.current_token.pos_end,
             "Expected '+', '-', '*' or '/'"
         ))
     return res
Beispiel #13
0
 def parse(self):
     res = self.expression()
     if not res._error and self.current_token._type != TokenTypes.TT_EOF:
         return res.failed(
             InvalidSyntaxError(self.current_token._start_pos,
                                self.current_token._end_pos,
                                "Expected '+', '-', '*' or '/'"))
     return res
Beispiel #14
0
    def parse(self):
        res = self.statements()

        if not res.error and self.current_tok.type!=Constants.TOK_EOF:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected +, -, * or /'
            ))
        return res
Beispiel #15
0
    def expr(self):
        res = ParseResult()

        ### New variable declaration
        if self.current_tok.matches(Constants.TOK_KEYWORD, 'var'):
            res.register_advancement()
            self.advance()

            if self.current_tok.type != Constants.TOK_IDENTIFIER:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected Identifier'
                ))

            var_name = self.current_tok
            res.register_advancement()
            self.advance()
            
            if self.current_tok.type != Constants.TOK_EQUALS:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected \'=\''
                ))

            res.register_advancement()
            self.advance()
            expr = res.register(self.expr())

            if res.error:
                return res
            return res.success(VarAssignNode(var_name, expr))

        node = res.register(self.binary_operation(self.comp_expr, ((Constants.TOK_KEYWORD, 'and'), (Constants.TOK_KEYWORD, 'or'))))

        if res.error:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'var\', int, float, identifier or operator or keywords'
            ))

        return res.success(node)
 def parse_math_expression(self):
     if self.current_tok.type in (INT, FLOAT, STRING, IDENTIFIER, PLUS,
                                  MINUS, LPAREN, LSQUAREBRACKET, KEYWORD):
         return self.parse_and_or_expression()
     else:
         self.errors.register_error(
             InvalidSyntaxError(
                 "Expected INT, IDENTIFIER, '+', '-', '(', '['",
                 self.current_tok.position_start,
                 self.current_tok.position_end,
             ))
         return None
Beispiel #17
0
    def expression(self):
        res = ParseResult()
        if self.current_token.matches(TokenTypes.TT_KEYWORD, "VAR"):
            res.register_advancement()
            self.advance()

            if self.current_token.get_type() != TokenTypes.TT_IDENTIFIER:
                res.failed(
                    InvalidSyntaxError(self.current_token.get_start_pos(),
                                       self.current_token.get_end_pos(),
                                       "Expected identifier"))
            var_name = self.current_token
            res.register_advancement()
            self.advance()

            if self.current_token.get_type() != TokenTypes.TT_EQ:
                res.failed(
                    InvalidSyntaxError(self.current_token.get_start_pos(),
                                       self.current_token.get_end_pos(),
                                       "Expected '='"))
            res.register_advancement()
            self.advance()

            expr = res.register(self.expression())
            if res._error:
                return res
            return res.success(VariableAssignNode(var_name, expr))

        node = res.register(
            self.binary_operation(self.term,
                                  [TokenTypes.TT_PLUS, TokenTypes.TT_MINUS]))
        if res._error:
            return res.failed(
                InvalidSyntaxError(
                    self.current_token._start_pos, self.current_token._end_pos,
                    "Expected VAR, int, float, identifier, '+', '-', '*' or '('"
                ))
        return res.success(node)
Beispiel #18
0
    def call(self):
        res = ParseResult()
        atom = res.register(self.atom())
        if res.error: return res

        if self.current_tok.type == Constants.TOK_LPAREN:
            res.register_advancement()
            self.advance()
            arg_nodes = []

            if self.current_tok.type == Constants.TOK_RPAREN:
                res.register_advancement()
                self.advance()
            else:
                arg_nodes.append(res.register(self.expr()))
                if res.error:
                    return res.failure(InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        "Expected ')', 'VAR', 'IF', 'FOR', 'WHILE', 'FUN', int, float, identifier, '+', '-', '(' or 'NOT'"
                    ))

                while self.current_tok.type == Constants.TOK_COMMA:
                    res.register_advancement()
                    self.advance()

                    arg_nodes.append(res.register(self.expr()))
                    if res.error: return res

                if self.current_tok.type != Constants.TOK_RPAREN:
                    return res.failure(InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        f"Expected ',' or ')'"
                    ))

                res.register_advancement()
                self.advance()
            return res.success(CallNode(atom, arg_nodes))
        return res.success(atom)
    def parse_assign_expression(self):
        position_start = self.current_tok.position_start
        left = self.parse_math_expression()
        if self.current_tok.type == BACKWORD_ARROW:
            if not isinstance(left, IdentifierNode):
                self.errors.register_error(
                    InvalidSyntaxError(
                        f"You can't assign a value to {left}",
                        self.current_tok.position_start,
                        self.current_tok.position_end,
                    ))
                return None

            self.advance()

            if self.current_tok.type == LPAREN:
                self.advance()
                type_ = self.current_tok.value
                self.advance()

                if self.current_tok.type != RPAREN:
                    self.errors.register_error(
                        InvalidSyntaxError(
                            f"Expected ')'",
                            self.current_tok.position_start,
                            self.current_tok.position_end,
                        ))
                    return None

                self.advance()
            else:
                type_ = None

            right = self.parse_math_expression()
            return AssignNode(type_, left, right, position_start,
                              self.current_tok.position_end)
        return left
    def term(self):
        position_start = self.current_tok.position_start
        left = self.factor()

        while self.current_tok is not None and self.current_tok.type in (MUL,
                                                                         DIV):
            if not self.current_tok.type in (MUL, DIV):
                self.errors.register_error(
                    InvalidSyntaxError(
                        "Expected '*' or '/'",
                        self.current_tok.position_start,
                        self.current_tok.position_end,
                    ))
                return None
            operation_tok = self.current_tok
            self.advance()
            right = self.factor()
            left = BinaryOperationNode(left, operation_tok, right,
                                       position_start,
                                       self.current_tok.position_end)

        return left
    def expression(self):
        position_start = self.current_tok.position_start
        left = self.term()

        while self.current_tok is not None and self.current_tok.type in (
                PLUS, MINUS):
            if not self.current_tok.type in (PLUS, MINUS):
                self.errors.register_error(
                    InvalidSyntaxError(
                        "Expected '+' or '-'",
                        self.current_tok.position_start,
                        self.current_tok.position_end,
                    ))
                return None
            operation_tok = self.current_tok
            self.advance()
            right = self.term()
            left = BinaryOperationNode(left, operation_tok, right,
                                       position_start,
                                       self.current_tok.position_end)

        return left
 def parse_statement(self):
     if self.current_tok.matches(KEYWORD, "scrie"):
         return self.parse_write_statement()
     elif self.current_tok.matches(KEYWORD, "citeste"):
         return self.parse_read_statement()
     elif self.current_tok.matches(KEYWORD, "Di"):
         return self.parse_declaration_statement()
     elif self.current_tok.matches(KEYWORD, "Do"):
         return self.parse_declaration_statement()
     elif self.current_tok.matches(KEYWORD, "daca"):
         return self.parse_if_statement()
     elif self.current_tok.type in (INT, FLOAT, STRING, IDENTIFIER, PLUS,
                                    MINUS, LPAREN, LSQUAREBRACKET, KEYWORD):
         stmt = self.parse_expression_statement()
         return stmt
     else:
         self.errors.register_error(
             InvalidSyntaxError(
                 "Expected INT, IDENTIFIER, '+', '-', '(', '['",
                 self.current_tok.position_start,
                 self.current_tok.position_end,
             ))
         self.advance()
         return None
Beispiel #23
0
    def func_def(self):
        res = ParseResult()

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'func'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected keyword \'func\''
            ))
        res.register_advancement()
        self.advance()

        if self.current_tok.type == Constants.TOK_IDENTIFIER:
            var_name_tok = self.current_tok
            res.register_advancement()
            self.advance()

            if self.current_tok.type != Constants.TOK_LPAREN:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected parantheses \'(\''
                ))
        else:
            var_name_tok = None
            if self.current_tok.type != Constants.TOK_LPAREN:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected parantheses \'(\''
                ))

        res.register_advancement()
        self.advance()

        arg_name_toks =  []

        if self.current_tok.type == Constants.TOK_IDENTIFIER:
            arg_name_toks.append(self.current_tok)
            res.register_advancement()
            self.advance()

            while self.current_tok.type == Constants.TOK_COMMA:
                res.register_advancement()
                self.advance()

                if self.current_tok.type != Constants.TOK_IDENTIFIER:
                    return res.failure(InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        'Expected Identifier'
                    ))
                arg_name_toks.append(self.current_tok)
                res.register_advancement()
                self.advance()
            
            if self.current_tok.type != Constants.TOK_RPAREN:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected \',\' or \')\''
                ))
        else:
            if self.current_tok.type != Constants.TOK_RPAREN:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected identifier or \')\''
                ))
        res.register_advancement()
        self.advance()

        if self.current_tok.type == Constants.TOK_ARROW:
            res.register_advancement()
            self.advance()
            body = res.register(self.expr())
            if res.error:
                return res
            return res.success(FuncDefNode(var_name_tok, arg_name_toks, body, True))
        
        
        
        if self.current_tok.type != Constants.TOK_NEWLINE:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected '->' or NEWLINE"
            ))

        res.register_advancement()
        self.advance()

        body = res.register(self.statements())
        if res.error:
            return res

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'end'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected 'end'"
            ))

        res.register_advancement()
        self.advance()
        
        return res.success(FuncDefNode(
            var_name_tok,
            arg_name_toks,
            body,
            False
        ))
Beispiel #24
0
 def _process_tokens(self, tokens):
     try:
         backup_stack = self._stacks.copy()
         backup_vars = self._variables.copy()
         valid, tokens = RpnTokens.check_syntax(tokens)
         if valid:
             for token in tokens:
                 if RpnTokens.contains_space(token):
                     continue
                 if RpnTokens.is_number(token):
                     num = RpnTokens.get_number(token,
                                                self._print.precision)
                     if num is not None:
                         if self._print.mode == 'dec':
                             self._stacks.append(num)
                         else:
                             if isinstance(num, float):
                                 raise UnsupportedDecimalError(token)
                             else:
                                 self._stacks.append(num)
                 elif RpnTokens.is_keyword(token):
                     if token[1] == RpnTokens.HEX[0]:
                         self._print.change_mode('hex', self._stacks,
                                                 self._variables)
                     elif token[1] == RpnTokens.DEC[0]:
                         self._print.change_mode('dec', self._stacks,
                                                 self._variables)
                     elif token[1] == RpnTokens.OCT[0]:
                         self._print.change_mode('oct', self._stacks,
                                                 self._variables)
                     elif token[1] == RpnTokens.BIN[0]:
                         self._print.change_mode('bin', self._stacks,
                                                 self._variables)
                     elif token[1] == RpnTokens.HELP[0]:
                         self._print.help()
                     elif token[1] == RpnTokens.EXIT[0]:
                         self._print.bye()
                         return 1
                     # Limit showing the number of digits after .
                     elif token[1] == RpnTokens.PREC[0]:
                         if len(self._stacks) < 1:
                             raise StackUnderflowError(token)
                         p = self._stacks.pop()
                         if not isinstance(p, int):
                             raise IntegerOperationError(token)
                         if p <= 0 or p > 100:
                             raise DomainError(token, 1, 100)
                         self._print.precision = p
                     # Limit showing the number of items in stack
                     elif token[1] == RpnTokens.LIMIT[0]:
                         if len(self._stacks) < 1:
                             raise StackUnderflowError(token)
                         p = self._stacks.pop()
                         if not isinstance(p, int):
                             raise IntegerOperationError(token)
                         if p <= 0 or p > 100:
                             raise DomainError(token, 1, 100)
                         self._print.precision = p
                     elif token[1] == RpnTokens.STACK[0]:
                         self._print.toggle_display()
                     elif token[1] == RpnTokens.THEME[0]:
                         self._print.toggle_theme()
                 elif RpnTokens.is_literal(token):
                     if token[1] in self._variables:
                         val = self._variables[token[1]]
                         if self._print.mode == 'dec':
                             self._stacks.append(val)
                         else:
                             if isinstance(val, float):
                                 raise UnsupportedDecimalError(token)
                             else:
                                 self._stacks.append(val)
                     elif token[1] in self._macros:
                         exp = self._macros[token[1]]
                         new_tokens = self._lexer.get_tokens(exp)
                         self._process_tokens(new_tokens)
                     else:
                         raise InvalidSyntaxError(token)
                 else:
                     if token[1].startswith('macro'):
                         cmd_str = token[1].split()
                         if len(cmd_str) <= 2:
                             raise InvalidSyntaxError(token)
                         mc = ' '.join(cmd_str[2:])
                         self._macros[cmd_str[1]] = mc
                     else:
                         ret = RpnOperations.execute(
                             token, self._stacks, self._variables,
                             self._print.mode)
                         if ret is not None:
                             self._stacks.append(ret)
     except RpnErrors as e:
         # Rollback to previous backup data if errors occur
         self._stacks = backup_stack
         self._variables = backup_vars
         self._print.error(e.get_message())
     return 0
Beispiel #25
0
    def atom(self):
        res= ParseResult()
        tok = self.current_tok
        
        if tok.type == Constants.TOK_IDENTIFIER:
            res.register_advancement()
            self.advance()
            return res.success(VarAccessNode(tok))


        elif tok.type in (Constants.TOK_INT, Constants.TOK_FLOAT):
            res.register_advancement()
            self.advance()
            return res.success(NumberNode(tok))
        
        elif tok.type == Constants.TOK_STRING:
            res.register_advancement()
            self.advance()
            return res.success(StringNode(tok))

        

        elif tok.type == Constants.TOK_LPAREN:
            res.register_advancement()
            self.advance()
            expr = res.register(self.expr())

            if res.error:
                return res
            if self.current_tok.type == Constants.TOK_RPAREN:
                res.register_advancement()
                self.advance()
                return res.success(expr)
            else:
                return res.failure(InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    'Expected \')\''
                ))
                
        elif tok.type == Constants.TOK_LSQUARE:
            list_expr = res.register(self.list_expr())
            if res.error: return res
            return res.success(list_expr)

        
        elif tok.matches(Constants.TOK_KEYWORD, 'if'):
            if_expr = res.register(self.if_expr())
            if res.error:
                return res
            return res.success(if_expr)

        elif tok.matches(Constants.TOK_KEYWORD, 'for'):
            for_expr = res.register(self.for_expr())
            if res.error:
                return res
            return res.success(for_expr)

        elif tok.matches(Constants.TOK_KEYWORD, 'while'):
            while_expr = res.register(self.while_expr())
            if res.error:
                return res
            return res.success(while_expr)

        elif tok.matches(Constants.TOK_KEYWORD, 'func'):
            func_def = res.register(self.func_def())
            if res.error:
                return res
            return res.success(func_def)
        

        return res.failure(InvalidSyntaxError(
            tok.pos_start, tok.pos_end,
            'Expected int, float, +, -, *, /. keywords - if, for, while, func etc.'
        ))
Beispiel #26
0
 def is_valid(token):
     if token[0] == Token.Error:
         raise InvalidSyntaxError(token)
     return True
Beispiel #27
0
    def for_expr(self):
        res = ParseResult()

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'for'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'for\''
            ))

        res.register_advancement()
        self.advance()

        if self.current_tok.type != Constants.TOK_IDENTIFIER:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected identifier'
            ))

        var_name = self.current_tok
        res.register_advancement()
        self.advance()

        if self.current_tok.type != Constants.TOK_EQUALS:
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'=\''
            ))

        res.register_advancement()
        self.advance()

        start_value = res.register(self.expr())
        if res.error:
            return res
        
        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'to'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'to\''
            ))
        
        res.register_advancement()
        self.advance()

        end_value = res.register(self.expr())
        if res.error:
            return res

        if self.current_tok.matches(Constants.TOK_KEYWORD, 'step'):
            res.register_advancement()
            self.advance()

            step_value = res.register(self.expr())
            if res.error:
                return res

        else:
            step_value = None

        if not self.current_tok.matches(Constants.TOK_KEYWORD, 'then'):
            return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                'Expected \'then\''
            ))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == Constants.TOK_NEWLINE:
            res.register_advancement()
            self.advance()

            body = res.register(self.statements())
            if res.error:
                return res

            if not self.current_tok.matches(Constants.TOK_KEYWORD, 'end'):
                return res.failure(InvalidSyntaxError(
                self.current_tok.pos_start, self.current_tok.pos_end,
                f"Expected 'end'"
                ))

            res.register_advancement()
            self.advance()

            return res.success(ForNode(var_name, start_value, end_value, step_value, body, True))
            
        body = res.register(self.statement())
        if res.error: return res

        return res.success(ForNode(var_name, start_value, end_value, step_value, body, False))