Exemple #1
0
    def process_import(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos):
        file_atom: tl.AtomicElement = parent[index + 1]
        file_tk: tl.StrToken = file_atom.atom
        includes: tl.CollectiveElement = parent[index + 2]
        included_block = self.parse_as_block(includes)
        builder.add_node(ast.ImportStmt(file_tk.value, included_block, lfp))

        return index + 2
Exemple #2
0
 def process_annotation(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder,
                        lfp: tl.LineFilePos):
     index += 1
     ele = parent[index]
     if isinstance(ele, tl.AtomicElement) and isinstance(ele.atom, tl.IdToken):
         builder.add_node(ast.AnnotationNode(ele.atom.identifier, lfp))
     else:
         raise errs.TplSyntaxError("Invalid annotation. ", lfp)
     return index
Exemple #3
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
Exemple #4
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
Exemple #5
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
Exemple #6
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
Exemple #7
0
    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
Exemple #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
Exemple #9
0
 def _process_inc_dec_operator(self, op, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder,
                               lfp: tl.LineFilePos):
     if index == 0:  # e.g.  ++i;
         post = False
     elif index == len(parent) - 1:
         post = True
     else:
         if is_call_obj(parent[index - 1]):  # a trick here is that all callable 'thing' can be use with ++ or --
             post = True
         elif is_call_obj(parent[index + 1]):
             post = False
         else:
             raise errs.TplParseError(f"Invalid syntax with {op}. ", lfp)
     if post:
         builder.add_node(ast.PostIncDecOperator(op, lfp))
     else:
         builder.add_node(ast.PreIncDecOperator(op, lfp))
Exemple #10
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
Exemple #11
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
Exemple #12
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
Exemple #13
0
 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
Exemple #14
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
Exemple #15
0
 def process_instanceof(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder,
                        lfp: tl.LineFilePos):
     builder.add_node(ast.InstanceOfExpr(lfp))
Exemple #16
0
 def process_eol(self, p, i, builder: ab.AstBuilder, lfp):
     builder.finish_part()
     builder.finish_line()
     self.var_level = ast.VAR_VAR
Exemple #17
0
 def process_comma(self, p, i, builder: ab.AstBuilder, lfp):
     builder.finish_part()
Exemple #18
0
 def process_fallthrough(self, p, i, builder: ab.AstBuilder, lfp):
     builder.add_node(ast.FallthroughStmt(lfp))
Exemple #19
0
 def process_continue(self, p, i, builder: ab.AstBuilder, lfp):
     builder.add_node(ast.ContinueStmt(lfp))
Exemple #20
0
 def process_break(self, p, i, builder: ab.AstBuilder, lfp):
     builder.add_node(ast.BreakStmt(lfp))
Exemple #21
0
    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
Exemple #22
0
 def process_declare(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos):
     builder.add_node(ast.Declaration(self.var_level, self.permission, lfp))
     self.permission = ast.PUBLIC
Exemple #23
0
 def process_super(self, parent: tl.CollectiveElement, index: int, builder: ab.AstBuilder, lfp: tl.LineFilePos):
     builder.add_node(ast.SuperExpr(lfp))