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_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_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_switch(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): cond_list.append(ele) index += 1 ele = parent[index] cond = self.parse_as_part(cond_list) body_block = self.parse_as_block(ele) res = ab.parse_switch(cond, body_block, lfp) builder.add_node(res) return index
def process_export(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos): index += 1 ele = parent[index] if tl.is_brace(ele): block = self.parse_as_block(ele) builder.add_node(ast.ExportStmt(block, lfp)) elif isinstance(ele, tl.AtomicElement) and isinstance(ele.atom, tl.IdToken): block = ast.BlockStmt(lfp) line = ast.Line(lfp) line.parts.append(ast.NameNode(ele.atom.identifier, lfp)) block.lines.append(line) builder.add_node(ast.ExportStmt(block, lfp)) else: raise errs.TplCompileError("Invalid export. ", lfp) return index
def process_one(self, parent: tl.CollectiveElement, index: int, result_parent: tl.CollectiveElement) -> int: ele = parent[index] if isinstance(ele, tl.AtomicElement): if isinstance(ele.atom, tl.IdToken): symbol = ele.atom.identifier lf = ele.atom.lfp if symbol == "macro": index += 1 name_ele = parent[index] if isinstance(name_ele, tl.AtomicElement) and isinstance( name_ele.atom, tl.IdToken): name = name_ele.atom.identifier index += 1 prob_params = parent[index] if isinstance(prob_params, tl.CollectiveElement): if prob_params.is_brace(): # macro name { ... } macro = SimpleMacro(prob_params, lf) self.macros.add_macro(name, macro, lf) return index + 1 elif prob_params.is_bracket( ): # macro name(...) ... index += 1 body = parent[index] if tl.is_brace(body): macro = CallMacro( get_name_list(prob_params), body, lf) self.macros.add_macro(name, macro, lf) return index + 1 raise errs.TplSyntaxError("Invalid macro syntax. ", lf) elif symbol == "exportmacro": index += 1 exports = parent[index] if tl.is_brace(exports): for exp in exports: if isinstance(exp, tl.AtomicElement) and isinstance( exp.atom, tl.IdToken): if exp.atom.identifier != ",": self.macros.add_export(exp.atom.identifier) else: raise errs.TplSyntaxError( "Invalid exportmacro syntax. ", lf) elif isinstance(exports, tl.AtomicElement) and isinstance( exports.atom, tl.IdToken): self.macros.add_export(exports.atom.identifier) else: raise errs.TplSyntaxError( "Invalid exportmacro syntax. ", lf) return index + 1 elif symbol == "import": index += 1 includes = parent[index] if isinstance(includes, tl.AtomicElement): self.import_one(includes.atom, result_parent, lf) elif tl.is_brace(includes): for inc in includes: if isinstance(inc, tl.AtomicElement): self.import_one(inc.atom, result_parent, lf) else: raise errs.TplSyntaxError( "Invalid include. ", lf) else: raise errs.TplSyntaxError("Invalid include. ", lf) return index + 1 elif self.macros.is_macro(symbol): # replace macro macro = self.macros.get_macro(symbol) if isinstance(macro, CallMacro): index += 1 args = parent[index] if not tl.is_bracket(args): raise errs.TplSyntaxError("Invalid macro syntax. ", args.lfp) arg_list = list_ify_macro_arg(args) if len(arg_list) != len(macro.params): raise errs.TplSyntaxError( "Macro syntax arity mismatch. ", args.lfp) body_with_arg = tl.CollectiveElement( tl.CE_BRACE, lf, None) for body_ele in macro.body: if isinstance(body_ele, tl.AtomicElement) and \ isinstance(body_ele.atom, tl.IdToken) and \ body_ele.atom.identifier in macro.params: arg_index = macro.params.index( body_ele.atom.identifier) body_with_arg.extend(arg_list[arg_index]) else: body_with_arg.append(body_ele) macro_res = self.process_block(body_with_arg, None) else: macro_res = self.process_block(macro.body, None) result_parent.extend(macro_res) return index + 1 result_parent.append(ele) elif isinstance(ele, tl.CollectiveElement): res = self.process_block(ele, result_parent) result_parent.append(res) else: raise errs.TplError("Unexpected element. ", parent.lfp) return index + 1