Beispiel #1
0
    def eat_statement(self):
        '''Eat statements'''
        if self.tok.type in ["ADD", "SUB", "NUM", "PRL", "STR"]:
            return self.eat_operation()

        if self.tok.type == "IDN":
            ctok = self.tok
            self.consume("IDN")

            match ctok.value:
                case "def":
                    ctok = self.tok
                    self.consume("IDN")
                    return self.eat_function(ctok.value)
                case "if":
                    return self.eat_conditional()
                case "unless":
                    return self.eat_cond_unless()
                case "case":
                    return self.eat_case_state()
                case "while":
                    return self.eat_while_loop(while_type = "forward")
                case "begin":
                    return self.eat_while_loop(while_type = "backwards")
                case "until":
                    return self.eat_while_loop(while_type = "until")
                case "break"|"next"|"redo"|"retry":
                    return ASTDataNode("KNOWN_CALL", ctok.value)
                case "for":
                    return self.eat_for_loop()
                case "return":
                    return self.eat_func_return()
                case "alias":
                    return self.eat_alias()
                case "undef":
                    return self.eat_undef()
                case "yield":
                    return self.eat_yield_call()

            match self.tok.type:
                case "PRL":
                    self.consume("PRL")
                    return ASTMultiNode("FUNC_CALL", "fn",
                        ASTDataNode("FUNC_NAME", ctok.value),
                        self.eat_params(look_for = "PRR"))
                case "CUL":
                    self.consume("CUL")
                    return self.eat_block(ctok.value)
                case "EQL":
                    self.consume("EQL")
                    return self.eat_variable_assignment(ctok.value)

            return ASTMultiNode("FUNC_CALL", "fn",
                ASTDataNode("FUNC_NAME", ctok.value),
                self.eat_params())

        if self.tok.type == "NWL":
            return ASTDataNode("NONETYPE", None)

        self.er_h.construct_error(f"unrecognized pattern, found {self.tok.type}")
Beispiel #2
0
    def eat_equalities(self):
        '''Eats equalities'''
        node = self.eat_expression()

        while self.tok.type in ["EQLS", "NEQL", "GTHE", "LTHE", "COMB", "CEQL", "GTH", "LTH"]:
            ctok = self.tok

            if ctok.type == "EQLS":
                self.consume("EQLS")
            elif ctok.type == "NEQL":
                self.consume("NEQL")
            elif ctok.type == "GTHE":
                self.consume("GTHE")
            elif ctok.type == "LTHE":
                self.consume("LTHE")
            elif ctok.type == "COMB":
                self.consume("COMB")
            elif ctok.type == "CEQL":
                self.consume("CEQL")
            elif ctok.type == "GTH":
                self.consume("GTH")
            elif ctok.type == "LTH":
                self.consume("LTH")
            else: self.er_h.construct_error("unrecognized symbol when trying to eat equality")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_expression())

        return node
Beispiel #3
0
    def eat_factor(self):
        '''Eats factor values'''
        ctok = self.tok
        match self.tok.type:
            case "NUM":
                self.consume("NUM")
                return ASTDataNode("NUMBER", ctok.value)
            case "BOOL":
                self.consume("BOOL")
                return ASTDataNode("BOOLEAN", ctok.value)
            case "ADD":
                self.consume("ADD")
                return ASTMultiNode("UNARY_OP", "+", None, self.eat_factor())
            case "SUB":
                self.consume("SUB")
                return ASTMultiNode("UNARY_OP", "-", None, self.eat_factor())
            case "NOT":
                self.consume("NOT")
                return ASTMultiNode("UNARY_OP", "!", None, self.eat_factor())
            case "PRL":
                self.consume("PRL")
                oper = self.eat_operation()
                self.consume("PRR")
                return oper
            case "SQL":
                return self.eat_arrays()
            case "STR":
                self.consume("STR")
                return ASTDataNode("STRING", ctok.value)
            case "IDN":
                last_tok = self.ltok
                self.consume("IDN")
                if last_tok.type == "DOT":
                    return ASTDataNode("FUNC_NAME", ctok.value)
                elif self.tok.type == "PRL":
                    self.consume("PRL")
                    call = ASTMultiNode("FUNC_CALL", "fn",
                        ASTDataNode("FUNC_NAME", ctok.value),
                        self.eat_params(look_for = "PRR"))
                    return call
                elif self.tok.type == "SQL":
                    return self.eat_array_index(ctok.value)
                return ASTDataNode("VARIABLE", ctok.value)

        self.er_h.construct_error(
            f"unrecognized symbol is {self.tok.type} when trying to eat factors"
        )
Beispiel #4
0
    def eat_yield_call(self):
        '''Eats yields to blocks'''
        args = ASTListNode("YIELD_ARGS", [])
        while self.tok.type not in ["SMC", "NWL", "EOF"]:
            args.add(self.eat_operation())
            if self.tok.type == "COM":
                self.consume("COM")
            elif self.tok.type not in ["SMC", "NWL"]:
                self.er_h.construct_error(f"unrecognized pattern in yield arguments, found {self.tok.type}")

        return ASTMultiNode("YIELD_CALL", "yield", None, args)
Beispiel #5
0
    def eat_alias(self):
        '''Eat alias statements'''
        ctok = self.tok
        if self.tok.type == "IDN":
            self.consume("IDN")
            alias = ASTDataNode("VARIABLE_NAME", ctok.value)
            ctok = self.tok
            if self.tok.type == "IDN":
                self.consume("IDN")
                original = ASTDataNode("VARIABLE_NAME", ctok.value)

                return ASTMultiNode("NAME_ALIAS", "alias", alias, original)

        self.er_h.construct_error("alias statement missing identifier(s)")
Beispiel #6
0
    def eat_inlines(self):
        '''Eats inline if/unless calls'''
        node = self.eat_andornot()

        while self.tok.type in ["IDN", "RANGE"] and self.tok.value in ["if", "unless", ".."]:
            ctok = self.tok
            if ctok.type == "IDN":
                self.consume("IDN")
            elif ctok.type == "RANGE":
                self.consume("RANGE")
            else: self.er_h.construct_error("unrecognized symbol in inlines")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_andornot())

        return node
Beispiel #7
0
    def eat_andornot(self):
        '''Eats && || ! operators'''
        node = self.eat_equalities()

        while self.tok.type in ["AND", "NOT", "ORO"]:
            ctok = self.tok
            if ctok.type == "AND":
                self.consume("AND")
            elif ctok.type == "ORO":
                self.consume("ORO")
            else: self.er_h.construct_error("unrecognized symbol when trying to eat AND OR NOT")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_equalities())

        return node
Beispiel #8
0
    def eat_expression(self):
        '''Eats expressions'''
        node = self.eat_term()

        while self.tok.type in ["ADD", "SUB"]:
            ctok = self.tok
            if ctok.type == "ADD":
                self.consume("ADD")
            elif ctok.type == "SUB":
                self.consume("SUB")
            else: self.er_h.construct_error("unrecognized symbol when trying to eat expression")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_term())

        return node
Beispiel #9
0
    def eat_power(self):
        '''Eat powers and dot operations'''
        node = self.eat_factor()

        while self.tok.type in ["POW", "DOT"]:
            ctok = self.tok
            if ctok.type == "POW":
                self.consume("POW")
            elif ctok.type == "DOT":
                self.consume("DOT")
            else: self.er_h.construct_error("unrecognized symbol when trying to eat powers")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_factor())

        return node
Beispiel #10
0
    def eat_term(self):
        '''Eat terms'''
        node = self.eat_power()

        while self.tok.type in ["MUL", "DIV", "PER"]:
            ctok = self.tok
            if ctok.type == "MUL":
                self.consume("MUL")
            elif ctok.type == "DIV":
                self.consume("DIV")
            elif ctok.type == "PER":
                self.consume("PER")
            else: self.er_h.construct_error("unrecognized symbol when trying to eat terms")

            node = ASTMultiNode("OPERATION", ctok.value, node, self.eat_power())

        return node
Beispiel #11
0
    def eat_array_index(self, var_name: str, depth: int = 0):
        '''Eats array index syntax'''
        self.consume("SQL")
        index = self.eat_factor()
        self.consume("SQR")

        sub_indexes = []
        if self.tok.type == "SQL":
            sub_indexes = self.eat_array_index("", depth + 1)

        if sub_indexes:
            rtrn_val =  [index, *sub_indexes]
        else:
            rtrn_val =  [index]

        if depth > 0:
            return rtrn_val

        return ASTMultiNode("ARRAY_VARIABLE",
        "array",
        var_name, rtrn_val)
Beispiel #12
0
            to_undef = self.traverse(node.value)
            if to_undef in self.memory:
                del self.memory[to_undef]
            elif to_undef in self.memory[self.scope][3]:
                del self.memory[self.scope][3][to_undef]
            else:
                self.er_h.interpreter(f"cannot undefine '{to_undef}'")
            return None

        if node.type == "BLOCK_STATE":
            block_name = self.traverse(node.sub_nodes[0])
            block_args = self.traverse(node.sub_nodes[1])

            self.memory[block_name][4] = [
                "BLOCK",
                block_args,
                node.sub_nodes[2]
            ]
            self.traverse(ASTMultiNode("FUNC_CALL", "fn",
                ASTDataNode("FUNC_NAME", block_name),
                ASTListNode("FUNC_PARAMS", [])))
            # self.traverse(self.memory[block_name][4][2])
            return None

        if node.type == "YIELD_CALL":
            arguments = self.traverse(node.right)

            return ["yield", *arguments]

        self.er_h.interpret_error(f"unrecognized node is {node.type}")
Beispiel #13
0
 def eat_variable_assignment(self, var_name):
     '''Eat variable assignments'''
     return ASTMultiNode("ASSIGNMENT", "=",
         ASTDataNode("VARIABLE_NAME", var_name),
         self.eat_operation())