Exemple #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}")
Exemple #2
0
    def eat_undef(self):
        '''Eat undefinitions'''
        ctok = self.tok
        if self.tok.type == "IDN":
            self.consume("IDN")
            return ASTDataNode("UNDEF", ASTDataNode("VARIABLE_NAME", ctok.value))

        self.er_h.construct_error("undef statement missing identifier")
Exemple #3
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)")
Exemple #4
0
    def eat_for_loop(self):
        '''Eats for ... in ... loops'''
        v_expands = ASTListNode("FOR_LOOP_VARS", [])

        while self.tok.type != "EOF" and self.tok.value != "in":
            ctok = self.tok
            if self.tok.type == "IDN":
                self.consume("IDN")
                v_expands.add(ASTDataNode("VARIABLE_NAME", ctok.value))
            if self.tok.type != "EOF" and self.tok.value != "in":
                self.consume("COM")
        self.consume("IDN")

        v_expr = self.eat_operation()

        if self.tok.value == "do":
            self.consume("IDN")
        self.consume("NWL")

        for_events = ASTListNode("STATEMENTS", [])
        while self.tok.value != "end" and self.tok.type != "EOF":
            for_events.add(self.eat_statement())
            if self.tok.type == "SMC":
                self.consume("SMC")
            elif self.tok.type == "NWL":
                self.consume("NWL")
            elif self.tok.type == "EOF":
                break
            else: self.er_h.construct_error("line ended with incorrect character")

        self.consume("IDN")
        return ASTListNode("FOR_LOOP", [v_expands, v_expr, for_events])
Exemple #5
0
    def eat_function(self, func_name):
        '''Eat functions'''
        f_params = ASTListNode("FUNCTION_ARGS", [])

        if self.tok.type == "PRL":
            self.consume("PRL")

            while self.tok.type not in ["PRR", "EOF"]:
                ctok = self.tok
                var_args = False
                if self.tok.type == "MUL":
                    self.consume("MUL")
                    var_args = True
                if self.tok.type == "IDN":
                    ctok = self.tok
                    self.consume("IDN")
                    default_val = None
                    if self.tok.type == "EQL":
                        self.consume("EQL")
                        default_val = self.eat_operation()
                    f_params.add(ASTListNode("FUNCTION_ARGS_EXT",
                    [ASTDataNode("VARIABLE_NAME", ctok.value), default_val, var_args]))

                if self.tok.type not in ["PRR", "EOF"]:
                    self.consume("COM")

            self.consume("PRR")
        self.consume("NWL")

        acts = ASTListNode("STATEMENTS", [])
        while self.tok.type != "EOF" and (self.tok.value != "end" and self.tok.type == "IDN"):
            acts.add(self.eat_statement())

            if self.tok.type == "SMC":
                self.consume("SMC")
            elif self.tok.type == "NWL":
                while self.tok.type == "NWL":
                    self.consume("NWL")
            elif self.tok.type == "EOF":
                break
            else:
                self.er_h.construct_error(f"line ended with incorrect character ({self.tok.value})")

        self.consume("IDN")

        return ASTListNode("FUNCTION", [ASTDataNode("FUNC_NAME", func_name), f_params, acts])
Exemple #6
0
    def eat_block(self, name):
        '''Eats blocks'''
        block_args = ASTListNode("BLOCK_ARGS", [])
        if self.tok.type == "PIP":
            self.consume("PIP")
            while self.tok.type not in ["PIP", "EOF"]:
                ctok = self.tok
                if self.tok.type == "IDN":
                    self.consume("IDN")
                    block_args.add(ASTDataNode("VARIABLE_NAME", ctok.value))
                if self.tok.type == "PIP":
                    break
                if self.tok.type == "COM":
                    self.consume("COM")
                if self.tok.type not in ["IDN", "COM", "PIP"]:
                    self.er_h.construct_error(f"unexpected symbol {self.tok.type} in block arguments")
            self.consume("PIP")

        if self.tok.type == "NWL":
            self.consume("NWL")

        acts = ASTListNode("STATEMENTS", [])
        while self.tok.type not in ["CUR", "EOF"]:
            acts.add(self.eat_statement())

            if self.tok.type != "CUR":
                if self.tok.type == "SMC":
                    self.consume("SMC")
                elif self.tok.type == "NWL":
                    while self.tok.type == "NWL":
                        self.consume("NWL")
                elif self.tok.type == "EOF":
                    break
                else:
                    self.er_h.construct_error(f"line ended with incorrect character ({self.tok.value})")

        self.consume("CUR")

        return ASTListNode("BLOCK_STATE", [ASTDataNode("BLOCK_NAME", name), block_args, acts])
Exemple #7
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"
        )
Exemple #8
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}")
Exemple #9
0
 def eat_func_return(self):
     '''Eat return statements'''
     rtrn_statement = self.eat_operation()
     return ASTDataNode("RETURN", rtrn_statement)
Exemple #10
0
 def eat_variable_assignment(self, var_name):
     '''Eat variable assignments'''
     return ASTMultiNode("ASSIGNMENT", "=",
         ASTDataNode("VARIABLE_NAME", var_name),
         self.eat_operation())