def process_case(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): index += 1 cond_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) ele = parent[index] while not (tl.is_brace(ele) or tl.identifier_of(ele, "->")): cond_list.append(ele) index += 1 ele = parent[index] cond = self.parse_as_part(cond_list) if tl.identifier_of(ele, "->"): # case expr index += 1 ele = parent[index] if tl.is_brace(ele): body_block = self.parse_as_block(ele) builder.add_node(ast.CaseExpr(body_block, lfp, cond)) else: body_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) while not tl.identifier_of(ele, ";"): body_list.append(ele) index += 1 ele = parent[index] builder.add_node(ast.CaseExpr(self.parse_as_part(body_list), lfp, cond)) else: # case stmt body_block = self.parse_as_block(ele) builder.add_node(ast.CaseStmt(body_block, lfp, cond)) return index
def process_fn(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): abstract = self.abstract self.abstract = False const = self.var_level == ast.VAR_CONST self.var_level = ast.VAR_VAR permission = self.permission self.permission = ast.PUBLIC inline = self.inline self.inline = False index += 1 name_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) next_ele = parent[index] while not tl.is_bracket(next_ele): name_list.append(next_ele) index += 1 next_ele = parent[index] if len(name_list) == 0: fn_name = None else: fn_name = self.parse_as_part(name_list) param_list = next_ele params = self.parse_as_line(param_list) prob_arrow = parent[index + 1] if tl.identifier_of(prob_arrow, "->"): builder.add_node(ast.FunctionTypeExpr(params, lfp)) return index index += 1 rtype_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) while not (tl.is_brace(parent[index]) or tl.identifier_of(parent[index], ";")): rtype_list.append(parent[index]) index += 1 rtype = self.parse_as_part(rtype_list) body_list = parent[index] if tl.identifier_of(body_list, ";"): body = None else: body = self.parse_as_block(body_list) if not abstract and body is None: raise errs.TplSyntaxError("Non-abstract method must have body. ", lfp) if abstract and body is not None: raise errs.TplSyntaxError("Abstract method must not have body. ", lfp) fd = ast.FunctionDef(fn_name, params, rtype, abstract, const, permission, body, lfp) fd.inline = inline builder.add_node(fd) return index
def process_if_expr(self, cond_list: tl.CollectiveElement, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): cond = self.parse_as_part(cond_list) index += 1 then_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) while not tl.identifier_of(parent[index], "else"): then_list.append(parent[index]) index += 1 then_expr = self.parse_as_part(then_list) index += 1 else_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) while index < len(parent) and not tl.identifier_of(parent[index], ";"): else_list.append(parent[index]) index += 1 else_expr = self.parse_as_part(else_list) ife = ast.IfExpr(cond, then_expr, else_expr, lfp) builder.add_node(ife) if index < len(parent): # last loop terminated by a ';', add an eol self.process_eol(parent, index, builder, lfp) return index
def process_if_stmt(self, parent: tl.CollectiveElement, index, builder, lfp): index += 1 condition_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) item = parent[index] while not (isinstance(item, tl.CollectiveElement) and item.is_brace()): condition_list.append(item) index += 1 item = parent[index] if tl.identifier_of(item, "then"): # is a if-expr instead of if-stmt return self.process_if_expr(condition_list, parent, index, builder, lfp) cond = self.parse_as_part(condition_list) body = self.parse_as_block(item) if index + 1 < len(parent) and tl.identifier_of(parent[index + 1], "else"): index += 2 else_block = self.parse_as_block(parent[index]) else: else_block = None ifs = ast.IfStmt(cond, body, else_block, lfp) builder.add_node(ifs) return index
def list_ify_macro_arg(args: tl.CollectiveElement) -> list: res = [] cur = tl.CollectiveElement(tl.CE_BRACE, args.lfp, None) for arg in args: if tl.identifier_of(arg, ","): res.append(cur) cur = tl.CollectiveElement(tl.CE_BRACE, args.lfp, None) else: cur.append(arg) res.append(cur) return res
def process_default(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): index += 1 ele = parent[index] if tl.is_brace(ele): builder.add_node(ast.CaseStmt(self.parse_as_block(ele), lfp)) elif tl.identifier_of(ele, "->"): index += 1 ele = parent[index] if tl.is_brace(ele): builder.add_node(ast.CaseExpr(self.parse_as_block(ele), lfp)) else: body_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) while not tl.identifier_of(ele, ";"): body_list.append(ele) index += 1 ele = parent[index] builder.add_node(ast.CaseExpr(self.parse_as_part(body_list), lfp)) else: raise errs.TplParseError("Invalid syntax of 'default'. ", lfp) return index
def process_require(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): index += 1 item = parent[index] if isinstance(item, tl.CollectiveElement): content = self.parse_as_block(item) else: bracket = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) bracket.append(item) index += 1 while not tl.identifier_of(parent[index], ";"): bracket.append(parent[index]) index += 1 content = self.parse_as_part(bracket) builder.add_node(ast.RequireStmt(content, lfp)) self.process_eol(parent, index, builder, lfp) return index
def process_lambda(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): index += 1 params_bracket = parent[index] if not tl.is_bracket(params_bracket): raise errs.TplSyntaxError("Invalid syntax for lambda expression. ", lfp) params = self.parse_as_line(params_bracket) body_bracket = tl.CollectiveElement(tl.CE_BRACKET, lfp, None) index += 1 next_tk = parent[index] while not tl.identifier_of(next_tk, ";"): body_bracket.append(next_tk) index += 1 next_tk = parent[index] body = self.parse_as_part(body_bracket) builder.add_node(ast.LambdaExpr(params, body, lfp)) return index
def process_class(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp): if index > 0 and tl.identifier_of(parent[index - 1], "."): builder.add_node(ast.NameNode("class", lfp)) return None abstract = self.abstract self.abstract = False index += 1 name = parent[index].atom.identifier index += 1 templates = None extensions = None next_ele = parent[index] if tl.is_arrow_bracket(next_ele): templates = self.parse_as_line(next_ele) index += 1 next_ele = parent[index] if tl.is_bracket(next_ele): extensions = self.parse_as_line(next_ele) index += 1 next_ele = parent[index] body = self.parse_as_block(next_ele) class_stmt = ast.ClassStmt(name, extensions, templates, abstract, body, lfp) builder.add_node(class_stmt) return index
def parse_one(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder) -> int: ele: tl.Element = parent[index] if isinstance(ele, tl.AtomicElement): token = ele.atom lfp = token.lfp if isinstance(token, tl.IntToken): builder.add_node(ast.FakeIntLit(token.value, lfp)) elif isinstance(token, tl.FloatToken): builder.add_node(ast.FakeFloatLit(token.value, lfp)) elif isinstance(token, tl.CharToken): builder.add_node(ast.FakeCharLit(token.char, lfp)) elif isinstance(token, tl.ByteToken): builder.add_node(ast.FakeByteLit(token.value, lfp)) elif isinstance(token, tl.StrToken): builder.add_node(ast.FakeStrLit(token.value, lfp)) elif isinstance(token, tl.IdToken): symbol = token.identifier if symbol == "-": if index < 1 or is_unary(parent[index - 1]): builder.add_node(ast.UnaryOperator("neg", ast.UNA_ARITH, lfp)) else: builder.add_node(ast.BinaryOperator("-", ast.BIN_ARITH, lfp)) elif symbol == "*": if index < 1 or is_unary(parent[index - 1]): builder.add_node(ast.StarExpr(lfp)) else: builder.add_node(ast.BinaryOperator("*", ast.BIN_ARITH, lfp)) elif symbol == "&": if index < 1 or is_unary(parent[index - 1]): builder.add_node(ast.AddrExpr(lfp)) else: builder.add_node(ast.BinaryOperator("&", ast.BIN_BITWISE, lfp)) elif symbol == "is": if index < len(parent) - 1 and tl.identifier_of(parent[index + 1], "not"): builder.add_node(ast.BinaryOperator("is not", ast.BIN_LOGICAL, lfp)) index += 1 else: builder.add_node(ast.BinaryOperator("is", ast.BIN_LOGICAL, lfp)) elif symbol == "not": # 'not is', a tribute to Isabepla. if index < len(parent) - 1 and tl.identifier_of(parent[index + 1], "is"): builder.add_node(ast.BinaryOperator("is not", ast.BIN_LOGICAL, lfp)) index += 1 else: builder.add_node(ast.UnaryOperator("not", ast.UNA_LOGICAL, lfp)) elif symbol in tl.ARITH_BINARY: builder.add_node(ast.BinaryOperator(symbol, ast.BIN_ARITH, lfp)) elif symbol in tl.LOGICAL_BINARY: builder.add_node(ast.BinaryOperator(symbol, ast.BIN_LOGICAL, lfp)) elif symbol in tl.BITWISE_BINARY: builder.add_node(ast.BinaryOperator(symbol, ast.BIN_BITWISE, lfp)) elif symbol in tl.LAZY_BINARY: builder.add_node(ast.BinaryOperator(symbol, ast.BIN_LAZY, lfp)) elif symbol in tl.ARITH_UNARY: builder.add_node(ast.UnaryOperator(symbol, ast.UNA_ARITH, lfp)) elif symbol in tl.LOGICAL_UNARY: builder.add_node(ast.UnaryOperator(symbol, ast.UNA_LOGICAL, lfp)) elif symbol in tl.ARITH_BINARY_ASS: builder.add_node(ast.BinaryOperatorAssignment(symbol, ast.BIN_ARITH, lfp)) elif symbol in tl.BITWISE_BINARY_ASS: builder.add_node(ast.BinaryOperatorAssignment(symbol, ast.BIN_BITWISE, lfp)) elif symbol in self.special_binary: node_class = self.special_binary[symbol] builder.add_node(node_class(lfp)) elif symbol in self.special_unary: node_class = self.special_unary[symbol] builder.add_node(node_class(lfp)) elif symbol in self.symbol_lib: ftn = self.symbol_lib[symbol] res = ftn(parent, index, builder, lfp) if res: index = res else: builder.add_node(ast.NameNode(symbol, lfp)) else: raise Exception("Unexpected error. ") elif isinstance(ele, tl.CollectiveElement): if ele.is_bracket(): lfp = ele.lfp if index > 0: prob_call_obj = parent[index - 1] if tl.is_arrow_bracket(prob_call_obj): prob_call_obj = parent[index - 2] if is_call_obj(prob_call_obj): args = self.parse_as_line(ele) call_obj = builder.remove_last() call = ast.FunctionCall(call_obj, args, lfp) builder.add_node(call) return index + 1 parenthesis = self.parse_as_part(ele) builder.add_node(parenthesis) elif ele.is_sqr_bracket(): lfp = ele.lfp if index > 0: prob_call_obj = parent[index - 1] if tl.is_arrow_bracket(prob_call_obj): prob_call_obj = parent[index - 2] if is_call_obj(prob_call_obj): args = self.parse_as_line(ele) call_obj = builder.remove_last() call = ast.IndexingExpr(call_obj, args, lfp) builder.add_node(call) return index + 1 elif ele.is_arrow_bracket(): lfp = ele.lfp if index > 0: prob_call_obj = parent[index - 1] if is_call_obj(prob_call_obj): args = self.parse_as_line(ele) call_obj = builder.remove_last() call = ast.GenericNode(call_obj, args, lfp) builder.add_node(call) return index + 1 else: raise Exception("Unexpected error. ") return index + 1