Exemplo n.º 1
0
    def if_expr_cases(self, case_keyword):
        res = ParseResult()
        cases = []
        else_case = None

        if not self.current_tok.matches(token.T_KEYWORD, case_keyword):
            return res.failure(
                errors.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.type == token.T_COLON:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          "Expected ':'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_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(token.T_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))
Exemplo n.º 2
0
    def comp_expr(self):
        res = ParseResult()

        if self.current_tok.matches(token.T_KEYWORD, 'not'):
            op_tok = self.current_tok
            res.register_advancement()
            self.advance()

            node = res.register(self.comp_expr())
            if res.error: return res
            return res.success(nodes.UnaryOpNode(op_tok, node))

        node = res.register(
            self.bin_op(self.arithm_expr,
                        (token.T_EE, token.T_NE, token.T_LT, token.T_GT,
                         token.T_LTE, token.T_GTE)))

        if res.error:
            return res.failure(
                errors.InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    "Expected int or float, identifier, '+', '-', '(', '[' or 'not'"
                ))

        return res.success(node)
Exemplo n.º 3
0
	def statement(self):
		res = ParseResult()
		pos_start = self.current_tok.pos_start.copy()

		if self.current_tok.matches(token.T_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(nodes.ReturnNode(expr, pos_start, self.current_tok.pos_end.copy()))

		if self.current_tok.matches(token.T_KEYWORD, 'continue'):
			res.register_advancement()
			self.advance()
			return res.success(nodes.ContinueNode(pos_start, self.current_tok.pos_end.copy()))

		if self.current_tok.matches(token.T_KEYWORD, 'break'):
			res.register_advancement()
			self.advance()
			return res.success(nodes.BreakNode(pos_start, self.current_tok.pos_end.copy()))

		expr = res.register(self.expr())
		if res.error:
			return res.failure(errors.InvalidSyntaxError(
				self.current_tok.pos_start, self.current_tok.pos_end,
				"Expected 'break', 'continue', 'return', 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', ')' '[' or 'not'"
			))

		return res.success(expr)
Exemplo n.º 4
0
    def while_expr(self):
        res = ParseResult()

        if not self.current_tok.matches(token.T_KEYWORD, 'while'):
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected 'while'"))

        res.register_advancement()
        self.advance()

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

        if not self.current_tok.type == token.T_COLON:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          "Expected ':'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_NEWLINE:
            res.register_advancement()
            self.advance()

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

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

            res.register_advancement()
            self.advance()

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

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

        return res.success(nodes.WhileNode(condition, body, False))
Exemplo n.º 5
0
 def parse(self):
     res = self.statements()
     if not res.error and self.current_tok.type != token.T_EOF:
         return res.failure(
             errors.InvalidSyntaxError(self.current_tok.pos_start,
                                       self.current_tok.pos_end,
                                       "Expected '+', '-', '*' or '/'"))
     return res
Exemplo n.º 6
0
    def list_expr(self):
        res = ParseResult()
        element_nodes = []
        pos_start = self.current_tok.pos_start.copy()

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

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_RSQUARE:
            res.register_advancement()
            self.advance()
        else:
            element_nodes.append(res.register(self.expr()))
            if res.error:
                return res.failure(
                    errors.InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        "Expected ']', 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', '[' or 'not'"
                    ))

            while self.current_tok.type == token.T_COMMA:
                res.register_advancement()
                self.advance()

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

            if self.current_tok.type != token.T_RSQUARE:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ',' or ']'"))

            res.register_advancement()
            self.advance()
        return res.success(
            nodes.ListNode(element_nodes, pos_start,
                           self.current_tok.pos_end.copy()))
Exemplo n.º 7
0
    def expr(self):
        res = ParseResult()

        if self.current_tok.matches(token.T_KEYWORD, 'var'):
            res.register_advancement()
            self.advance()

            if self.current_tok.type != token.T_IDENTIFIER:
                return res.failure(
                    errors.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 != token.T_EQ:
                return res.failure(
                    errors.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(nodes.VarAssignNode(var_name, expr))

        node = res.register(
            self.bin_op(self.comp_expr,
                        ((token.T_KEYWORD, 'and'), (token.T_KEYWORD, 'or'))))

        if res.error:
            return res.failure(
                errors.InvalidSyntaxError(
                    self.current_tok.pos_start, self.current_tok.pos_end,
                    "Expected int or float, identifier, 'var', 'if', 'for', 'while', 'func', '+', '-', '(' or '['"
                ))

        return res.success(node)
Exemplo n.º 8
0
    def call(self):
        res = ParseResult()

        atom = res.register(self.atom())
        if res.error: return res

        if self.current_tok.type == token.T_LPAREN:
            res.register_advancement()
            self.advance()
            arg_nodes = []

            if self.current_tok.type == token.T_RPAREN:
                res.register_advancement()
                self.advance()
            else:
                arg_nodes.append(res.register(self.expr()))
                if res.error:
                    return res.failure(
                        errors.InvalidSyntaxError(
                            self.current_tok.pos_start,
                            self.current_tok.pos_end,
                            "Expected ')', 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', '[' or 'not'"
                        ))

                while self.current_tok.type == token.T_COMMA:
                    res.register_advancement()
                    self.advance()

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

                if self.current_tok.type != token.T_RPAREN:
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  "Expected ',' or ')'"))

                res.register_advancement()
                self.advance()

            return res.success(nodes.CallNode(atom, arg_nodes))
        return res.success(atom)
Exemplo n.º 9
0
	def parse(self):
		if len(self.tokens) == 1 and self.tokens[0].type == token.T_EOF:
			return ParseResult().success(nodes.ListNode([], self.tokens[0].pos_start, self.tokens[0].pos_end))

		res = self.statements()
		if not res.error and self.current_tok.type != token.T_EOF:
			return res.failure(errors.InvalidSyntaxError(
				self.current_tok.pos_start, self.current_tok.pos_end,
				"Expected '+', '-', '*' or '/'"
			))
		return res
Exemplo n.º 10
0
    def if_expr_c(self):
        res = ParseResult()
        else_case = None

        if self.current_tok.matches(token.T_KEYWORD, 'else'):
            res.register_advancement()
            self.advance()

            if self.current_tok.type != token.T_COLON:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ':'"))

            res.register_advancement()
            self.advance()

            if self.current_tok.type == token.T_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(token.T_KEYWORD, 'end'):
                    res.register_advancement()
                    self.advance()
                else:
                    return res.failure(
                        errors.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)
Exemplo n.º 11
0
    def func_def(self):
        res = ParseResult()

        if not self.current_tok.matches(token.T_KEYWORD, 'func'):
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected 'func'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_IDENTIFIER:
            var_name_tok = self.current_tok
            res.register_advancement()
            self.advance()
            if self.current_tok.type != token.T_LPAREN:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected '('"))
        else:
            var_name_tok = None
            if self.current_tok.type != token.T_LPAREN:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected identifier or '('"))

        res.register_advancement()
        self.advance()
        arg_name_toks = []

        if self.current_tok.type == token.T_IDENTIFIER:
            arg_name_toks.append(self.current_tok)
            res.register_advancement()
            self.advance()

            while self.current_tok.type == token.T_COMMA:
                res.register_advancement()
                self.advance()

                if self.current_tok.type != token.T_IDENTIFIER:
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  f"Expected identifier"))

                arg_name_toks.append(self.current_tok)
                res.register_advancement()
                self.advance()

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

        else:
            if self.current_tok.type != token.T_RPAREN:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected identifier or ')'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_ARROW:
            res.register_advancement()
            self.advance()

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

            return res.success(
                nodes.FunctionDefNode(var_name_tok, arg_name_toks, body, True))

        if self.current_tok.type != token.T_LCURLY:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          "Expected '{'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type != token.T_NEWLINE:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected '->' or a new line"))

        res.register_advancement()
        self.advance()

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

        if self.current_tok.type != token.T_RCURLY:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          "Expected '}'"))

        res.register_advancement()
        self.advance()

        return res.success(
            nodes.FunctionDefNode(var_name_tok, arg_name_toks, body, False))
Exemplo n.º 12
0
    def for_expr(self):
        res = ParseResult()

        if not self.current_tok.matches(token.T_KEYWORD, 'for'):
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected 'for'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type != token.T_IDENTIFIER:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected identifier"))

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

        if self.current_tok.type == token.T_EQ:
            res.register_advancement()
            self.advance()

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

            if not self.current_tok.matches(token.T_KEYWORD, 'to'):
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected 'to'"))

            res.register_advancement()
            self.advance()

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

            if self.current_tok.matches(token.T_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.type == token.T_COLON:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ':'"))

            res.register_advancement()
            self.advance()

            if self.current_tok.type == token.T_NEWLINE:
                res.register_advancement()
                self.advance()

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

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

                res.register_advancement()
                self.advance()

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

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

            return res.success(
                nodes.ForNode(var_name, start_value, end_value, step_value,
                              body, False))
        elif self.current_tok.matches(token.T_KEYWORD, 'in'):
            res.register_advancement()
            self.advance()

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

            if not self.current_tok.type == token.T_COLON:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ':'"))

            res.register_advancement()
            self.advance()

            if self.current_tok.type == token.T_NEWLINE:
                res.register_advancement()
                self.advance()

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

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

                res.register_advancement()
                self.advance()

                return res.success(
                    nodes.ForEachNode(var_name, array, body, True))

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

            return res.success(
                nodes.ForNode(var_name, start_value, end_value, step_value,
                              body, False))
        else:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          f"Expected '='"))
Exemplo n.º 13
0
    def dict_expr(self):
        res = ParseResult()
        element_nodes = {}
        pos_start = self.current_tok.pos_start.copy()

        if self.current_tok.type != token.T_LCURLY:
            return res.failure(
                errors.InvalidSyntaxError(self.current_tok.pos_start,
                                          self.current_tok.pos_end,
                                          "Expected '{'"))

        res.register_advancement()
        self.advance()

        if self.current_tok.type == token.T_RCURLY:
            res.register_advancement()
            self.advance()
        else:
            key = res.register(self.expr())
            if res.error:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected string"))

            if not isinstance(key, nodes.StringNode):
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected string"))

            if self.current_tok.type != token.T_COLON:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              f"Expected ':'"))

            res.register_advancement()
            self.advance()

            value = res.register(self.expr())
            if res.error:
                return res.failure(
                    errors.InvalidSyntaxError(
                        self.current_tok.pos_start, self.current_tok.pos_end,
                        "Expected 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', '[' or 'not'"
                    ))

            element_nodes[key] = value

            while self.current_tok.type == token.T_COMMA:
                added = False
                res.register_advancement()
                self.advance()

                key = res.register(self.expr())
                if res.error:
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  "Expected string"))

                if not isinstance(key, nodes.StringNode):
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  f"Expected string"))

                if self.current_tok.type != token.T_COLON:
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  f"Expected ':'"))

                res.register_advancement()
                self.advance()

                value = res.register(self.expr())
                if res.error:
                    return res.failure(
                        errors.InvalidSyntaxError(
                            self.current_tok.pos_start,
                            self.current_tok.pos_end,
                            "Expected 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', '[' or 'not'"
                        ))

                for i in element_nodes:
                    if i.tok.value == key.tok.value:
                        added = True
                        element_nodes[i] = value

                if not added:
                    element_nodes[key] = value

                added = False

            if self.current_tok.type != token.T_RCURLY:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ',' or '}'"))

            res.register_advancement()
            self.advance()

        return res.success(
            nodes.DictNode(element_nodes, pos_start,
                           self.current_tok.pos_end.copy()))
Exemplo n.º 14
0
    def atom(self):
        res = ParseResult()
        tok = self.current_tok

        if tok.type in (token.T_INT, token.T_FLOAT):
            res.register_advancement()
            self.advance()
            return res.success(nodes.NumberNode(tok))

        elif tok.type in (token.T_STRING):
            res.register_advancement()
            self.advance()
            return res.success(nodes.StringNode(tok))

        elif tok.type == token.T_IDENTIFIER:
            res.register_advancement()
            self.advance()
            return res.success(nodes.VarAccessNode(tok))

        elif tok.type == token.T_LPAREN:
            res.register_advancement()
            self.advance()
            expr = res.register(self.expr())
            if res.error: return res
            if self.current_tok.type == token.T_RPAREN:
                res.register_advancement()
                self.advance()
                return res.success(expr)
            else:
                return res.failure(
                    errors.InvalidSyntaxError(self.current_tok.pos_start,
                                              self.current_tok.pos_end,
                                              "Expected ')'"))

        elif tok.type == token.T_LSQUARE:
            list_expr = res.register(self.list_expr())
            if res.error: return res
            return res.success(list_expr)

        elif tok.type == token.T_LCURLY:
            dict_expr = res.register(self.dict_expr())
            if res.error: return res
            return res.success(dict_expr)

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

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

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

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

        return res.failure(
            errors.InvalidSyntaxError(
                tok.pos_start, tok.pos_end,
                "Expected int or float, identifier, '+', '-' or '(', , '[', 'if', 'for', 'while' or 'func'"
            ))
Exemplo n.º 15
0
    def call(self):
        res = ParseResult()

        atom = res.register(self.atom())
        if res.error: return res

        if self.current_tok.type == token.T_LPAREN:
            res.register_advancement()
            self.advance()
            arg_nodes = []
            optional_arg_name_nodes = []
            optional_arg_value_nodes = []

            if self.current_tok.type == token.T_RPAREN:
                res.register_advancement()
                self.advance()
            else:
                arg_nodes.append(res.register(self.expr()))
                if res.error:
                    return res.failure(
                        errors.InvalidSyntaxError(
                            self.current_tok.pos_start,
                            self.current_tok.pos_end,
                            "Expected ')', 'var', 'if', 'for', 'while', 'func', int, float, identifier, '+', '-', '(', '[' or 'not'"
                        ))

                while self.current_tok.type == token.T_COMMA:
                    res.register_advancement()
                    self.advance()

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

                if self.current_tok.type == token.T_EQ:
                    ident = arg_nodes.pop(-1)
                    if type(ident) != nodes.VarAccessNode:
                        return res.failure(
                            errors.InvalidSyntaxError(
                                self.current_tok.pos_start,
                                self.current_tok.pos_end,
                                "Expected an identifier"))

                    optional_arg_name_nodes.append(ident.var_name_tok)

                    res.register_advancement()
                    self.advance()

                    optional_arg_value_nodes.append(res.register(self.expr()))
                    if res.error:
                        return res.failure(
                            errors.InvalidSyntaxError(
                                self.current_tok.pos_start,
                                self.current_tok.pos_end,
                                "Expected int, float, string or boolean"))

                    while self.current_tok.type == token.T_COMMA:
                        res.register_advancement()
                        self.advance()

                        if self.current_tok.type != token.T_IDENTIFIER:
                            return res.failure(
                                errors.InvalidSyntaxError(
                                    self.current_tok.pos_start,
                                    self.current_tok.pos_end,
                                    f"Expected identifier"))

                        optional_arg_name_nodes.append(self.current_tok)
                        res.register_advancement()
                        self.advance()

                        if self.current_tok.type != token.T_EQ:
                            return res.failure(
                                errors.InvalidSyntaxError(
                                    self.current_tok.pos_start,
                                    self.current_tok.pos_end, f"Expected ="))

                        res.register_advancement()
                        self.advance()

                        value = res.register(self.atom())
                        if res.error: return res

                        optional_arg_value_nodes.append(value)

                if self.current_tok.type != token.T_RPAREN:
                    return res.failure(
                        errors.InvalidSyntaxError(self.current_tok.pos_start,
                                                  self.current_tok.pos_end,
                                                  "Expected ',' or ')'"))

                res.register_advancement()
                self.advance()

            return res.success(
                nodes.CallNode(atom, arg_nodes, optional_arg_name_nodes,
                               optional_arg_value_nodes))
        return res.success(atom)