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}")
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")
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)")
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])
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])
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])
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" )
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}")
def eat_func_return(self): '''Eat return statements''' rtrn_statement = self.eat_operation() return ASTDataNode("RETURN", rtrn_statement)
def eat_variable_assignment(self, var_name): '''Eat variable assignments''' return ASTMultiNode("ASSIGNMENT", "=", ASTDataNode("VARIABLE_NAME", var_name), self.eat_operation())