def parse_left(self, required=True):
        result = self.hooks.unary_prehook() if self.hooks != None else None
        if result != None:
            return result

        unary = self.reader.read_any_of(self.config.unary)
        if unary != None:
            right = self.parse(self.prefix_precedence)
            return exprs.UnaryExpression(exprs.UNARY_TYPE.PREFIX, unary, right)

        id = self.reader.read_identifier()
        if id != None:
            return exprs.Identifier(id)

        num = self.reader.read_number()
        if num != None:
            return exprs.NumericLiteral(num)

        str = self.reader.read_string()
        if str != None:
            return exprs.StringLiteral(str)

        if self.reader.read_token("("):
            expr = self.parse()
            self.reader.expect_token(")")
            return exprs.ParenthesizedExpression(expr)

        if required:
            self.reader.fail(
                f'''unknown (literal / unary) token in expression''')

        return None
 def parse_block(self, indent_len = 0):
     block = nodes.TemplateBlock([])
     indent_man = BlockIndentManager(block, indent_len)
     while not self.reader.get_eof():
         if self.reader.peek_exactly("{{/"):
             break
         if self.reader.read_exactly("${"):
             expr = self.parser.parse_expression()
             block.items.append(nodes.ExpressionNode(expr))
             self.reader.expect_token("}")
         elif self.reader.read_exactly("$"):
             id = self.reader.expect_identifier()
             block.items.append(nodes.ExpressionNode(exprs.Identifier(id)))
         elif self.reader.read_exactly("{{"):
             block_indent_len = indent_man.remove_prev_indent()
             
             if self.reader.read_token("for"):
                 var_name = self.reader.expect_identifier()
                 self.reader.expect_token("of")
                 items_expr = self.parser.parse_expression()
                 attrs = self.parse_attributes()
                 self.reader.expect_token("}}")
                 body = self.parse_block(block_indent_len)
                 self.reader.expect_token("{{/for}}")
                 block.items.append(nodes.ForNode(var_name, items_expr, body, attrs.get("joiner")))
             else:
                 expr = self.parser.parse_expression()
                 block.items.append(nodes.ExpressionNode(expr))
                 self.reader.expect_token("}}")
         else:
             literal = self.reader.read_regex("([^\\\\]\\\\(\\{\\{|\\$)|\r|\n|(?!\\{\\{|\\$\\{|\\$).)*")[0]
             if literal == "":
                 raise Error("This should not happen!")
             block.items.append(indent_man.deindent(nodes.LiteralNode(literal)))
     
     if indent_len != 0:
         indent_man.remove_prev_indent()
     
     return block
    def unary_prehook(self):
        if self.reader.read_token("null"):
            return exprs.NullLiteral()
        elif self.reader.read_token("true"):
            return exprs.BooleanLiteral(True)
        elif self.reader.read_token("false"):
            return exprs.BooleanLiteral(False)
        elif self.reader.read_token("`"):
            parts = []
            lit_part = ""
            while True:
                if self.reader.read_exactly("`"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    break
                elif self.reader.read_exactly("${"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    expr = self.parse_expression()
                    parts.append(exprs.TemplateStringPart.expression(expr))
                    self.reader.expect_token("}")
                elif self.allow_dollar_ids and self.reader.read_exactly("$"):
                    if lit_part != "":
                        parts.append(
                            exprs.TemplateStringPart.literal(lit_part))
                        lit_part = ""

                    id = self.reader.read_identifier()
                    parts.append(
                        exprs.TemplateStringPart.expression(
                            exprs.Identifier(id)))
                elif self.reader.read_exactly("\\"):
                    chr = self.reader.read_char()
                    if chr == "n":
                        lit_part += "\n"
                    elif chr == "r":
                        lit_part += "\r"
                    elif chr == "t":
                        lit_part += "\t"
                    elif chr == "`":
                        lit_part += "`"
                    elif chr == "$":
                        lit_part += "$"
                    elif chr == "\\":
                        lit_part += "\\"
                    else:
                        self.reader.fail("invalid escape",
                                         self.reader.offset - 1)
                else:
                    chr = self.reader.read_char()
                    chr_code = ord(chr[0])
                    if not (32 <= chr_code
                            and chr_code <= 126) or chr == "`" or chr == "\\":
                        self.reader.fail(
                            f'''not allowed character (code={chr_code})''',
                            self.reader.offset - 1)
                    lit_part += chr
            return exprs.TemplateString(parts)
        elif self.reader.read_token("new"):
            type = self.parse_type()
            if isinstance(type, astTypes.UnresolvedType):
                self.reader.expect_token("(")
                args = self.expression_parser.parse_call_arguments()
                return exprs.UnresolvedNewExpression(type, args)
            else:
                raise Error(
                    f'''[TypeScriptParser2] Expected UnresolvedType here!''')
        elif self.reader.read_token("<"):
            new_type = self.parse_type()
            self.reader.expect_token(">")
            expression = self.parse_expression()
            return exprs.CastExpression(new_type, expression)
        elif self.reader.read_token("/"):
            pattern = ""
            while True:
                chr = self.reader.read_char()
                if chr == "\\":
                    chr2 = self.reader.read_char()
                    pattern += "/" if chr2 == "/" else "\\" + chr2
                elif chr == "/":
                    break
                else:
                    pattern += chr
            modifiers = self.reader.read_modifiers(["g", "i"])
            return exprs.RegexLiteral(pattern, "i" in modifiers, "g"
                                      in modifiers)
        elif self.reader.read_token("typeof"):
            expr = self.expression_parser.parse(
                self.expression_parser.prefix_precedence)
            self.reader.expect_token("===")
            check = self.reader.expect_string()

            ts_type = None
            if check == "string":
                ts_type = "TsString"
            elif check == "boolean":
                ts_type = "TsBoolean"
            elif check == "object":
                ts_type = "Object"
            elif check == "function":
                # TODO: ???
                ts_type = "Function"
            elif check == "undefined":
                # TODO: ???
                ts_type = "Object"
            else:
                self.reader.fail("unexpected typeof comparison")

            return exprs.InstanceOfExpression(
                expr, astTypes.UnresolvedType(ts_type, []))
        elif self.reader.peek_regex("\\([A-Za-z0-9_]+\\s*[:,]|\\(\\)") != None:
            params = self.parse_lambda_params()
            self.reader.expect_token("=>")
            block = self.parse_lambda_block()
            return types.Lambda(params, block)
        elif self.reader.read_token("await"):
            expression = self.parse_expression()
            return exprs.AwaitExpression(expression)

        map_literal = self.expression_parser.parse_map_literal()
        if map_literal != None:
            return map_literal

        array_literal = self.expression_parser.parse_array_literal()
        if array_literal != None:
            return array_literal

        return None