Exemplo n.º 1
0
    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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
 def process_block(
         self, block: tl.CollectiveElement,
         result_parent: tl.CollectiveElement) -> tl.CollectiveElement:
     result = tl.CollectiveElement(block.ce_type, block.lfp, result_parent)
     i = 0
     while i < len(block):
         i = self.process_one(block, i, result)
     return result
Exemplo n.º 5
0
    def make_tree(self, cur_active: tl.CollectiveElement,
                  index: int) -> tl.CollectiveElement:
        tk = self.tokens[index]
        if isinstance(tk, tl.IdToken):
            symbol = tk.identifier
            if symbol == "(":
                return tl.CollectiveElement(tl.CE_BRACKET, tk.lfp, cur_active)
            if symbol == "[":
                return tl.CollectiveElement(tl.CE_SQR_BRACKET, tk.lfp,
                                            cur_active)
            if symbol == "{":
                return tl.CollectiveElement(tl.CE_BRACE, tk.lfp, cur_active)
            if symbol == ")":
                if cur_active.ce_type == tl.CE_BRACKET:
                    cur_active.parent.append(cur_active)
                    return cur_active.parent
                else:
                    raise errs.TplSyntaxError("Parenthesis does not close. ",
                                              tk.lfp)
            if symbol == "]":
                if cur_active.ce_type == tl.CE_SQR_BRACKET:
                    cur_active.parent.append(cur_active)
                    return cur_active.parent
                else:
                    raise errs.TplSyntaxError("Parenthesis does not close. ",
                                              tk.lfp)
            if symbol == "}":
                if cur_active.ce_type == tl.CE_BRACE:
                    cur_active.parent.append(cur_active)
                    return cur_active.parent
                else:
                    raise errs.TplSyntaxError("Parenthesis does not close. ",
                                              tk.lfp)
            if symbol == "<":
                if has_closing_arrow(self.tokens, index):
                    return tl.CollectiveElement(tl.CE_ARROW_BRACKET, tk.lfp,
                                                cur_active)
            if symbol == ">":
                if tl.is_arrow_bracket(cur_active):
                    cur_active.parent.append(cur_active)
                    return cur_active.parent

        cur_active.append(tl.AtomicElement(tk, cur_active))
        return cur_active
Exemplo n.º 6
0
 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
Exemplo n.º 7
0
    def process_while_stmt(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos):
        index += 1
        item = parent[index]
        cond_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None)
        while not (isinstance(item, tl.CollectiveElement) and item.is_brace()):
            cond_list.append(item)
            index += 1
            item = parent[index]

        cond = self.parse_as_part(cond_list)
        body = self.parse_as_block(item)
        builder.add_node(ast.WhileStmt(cond, body, lfp))

        return index
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
 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
Exemplo n.º 10
0
 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
Exemplo n.º 11
0
    def process_for_stmt(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos):
        index += 1
        item = parent[index]
        cond_list = tl.CollectiveElement(tl.CE_BRACKET, lfp, None)
        while not (isinstance(item, tl.CollectiveElement) and item.is_brace()):
            cond_list.append(item)
            index += 1
            item = parent[index]

        cond = self.parse_as_block(cond_list)
        body = self.parse_as_block(item)
        if len(cond) == 3:
            builder.add_node(ast.ForStmt(cond[0], cond[1], cond[2], body, lfp))
        elif len(cond) == 1 and len(cond[0]) == 1 and isinstance(cond[0][0], ast.InStmt):
            builder.add_node(ast.ForEachStmt(cond[0][0], body, lfp))
        else:
            raise errs.TplCompileError("For loop title must contains 3 parts. ", lfp)

        return index
Exemplo n.º 12
0
 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
Exemplo n.º 13
0
    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
Exemplo n.º 14
0
    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
Exemplo n.º 15
0
 def make_root_tree(self):
     root = tl.CollectiveElement(tl.CE_BRACE, tl.LF_TOKENIZER, None)
     cur_active = root
     for i in range(len(self.tokens)):
         cur_active = self.make_tree(cur_active, i)
     return root