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 transform(self, expr): if isinstance(expr, exprs.BinaryExpression) and expr.operator == "||": lit_types = self.main.current_file.literal_types expr.left = self.main.run_plugins_on(expr.left) left_type = expr.left.get_type() if isinstance(expr.right, exprs.ArrayLiteral) and len( expr.right.items) == 0: if isinstance(left_type, astTypes.ClassType ) and left_type.decl == lit_types.array.decl: expr.right.set_actual_type(left_type) return exprs.NullCoalesceExpression(expr.left, expr.right) if isinstance(expr.right, exprs.MapLiteral) and len( expr.right.items) == 0: if isinstance(left_type, astTypes.ClassType ) and left_type.decl == lit_types.map.decl: expr.right.set_actual_type(left_type) return exprs.NullCoalesceExpression(expr.left, expr.right) expr.right = self.main.run_plugins_on(expr.right) right_type = expr.right.get_type() if isinstance(expr.right, exprs.NullLiteral): # something-which-can-be-undefined || null return expr.left elif astTypes.TypeHelper.is_assignable_to( right_type, left_type) and not astTypes.TypeHelper.equals( right_type, self.main.current_file.literal_types.boolean): return exprs.NullCoalesceExpression(expr.left, expr.right) return expr
def parse_map_literal(self, key_separator=":", start_token="{", end_token="}"): if not self.reader.read_token(start_token): return None items = [] while True: if self.reader.peek_token(end_token): break name = self.reader.read_string() if name == None: name = self.reader.expect_identifier( "expected string or identifier as map key") self.reader.expect_token(key_separator) initializer = self.parse() items.append(exprs.MapLiteralItem(name, initializer)) if not (self.reader.read_token(",")): break self.reader.expect_token(end_token) return exprs.MapLiteral(items)
def transform(self, expr): unary_expr = expr if unary_expr.operator == "!": self.main.process_expression(expr) type = unary_expr.operand.actual_type lit_types = self.main.current_file.literal_types if isinstance(type, astTypes.ClassType) and type.decl != lit_types.boolean.decl and type.decl != lit_types.numeric.decl: return exprs.BinaryExpression(unary_expr.operand, "==", exprs.NullLiteral()) return expr
def visit_expression(self, expr): orig_expr = expr expr = super().visit_expression(expr) if isinstance(expr, exprs.BinaryExpression) and expr.operator == "in": expr = exprs.UnresolvedCallExpression( exprs.PropertyAccessExpression(expr.right, "hasKey"), [], [expr.left]) expr.parent_node = orig_expr.parent_node return expr
def transform_method_call(self, expr): if isinstance(expr.object, refs.ClassReference) or isinstance( expr.object, refs.StaticThisReference): cls_ = expr.object.decl if isinstance( expr.object, refs.ClassReference) else expr.object.cls_ if isinstance( expr.object, refs.StaticThisReference) else None method = self.find_method(cls_, expr.method_name, True, expr.args) result = exprs.StaticMethodCallExpression( method, expr.type_args, expr.args, isinstance(expr.object, refs.StaticThisReference)) self.resolve_return_type(result, genRes.GenericsResolver()) return result else: resolved_object = expr.object if expr.object.actual_type != None else self.main.run_plugins_on( expr.object) object_type = resolved_object.get_type() intf_type = object_type.decl if isinstance( object_type, astTypes.ClassType) else object_type.decl if isinstance( object_type, astTypes.InterfaceType) else None if intf_type != None: lambda_field = next( filter( lambda x: x.name == expr.method_name and isinstance( x.type, astTypes.LambdaType) and len( x.type.parameters) == len(expr.args), intf_type.fields), None) if lambda_field != None: lambda_call = exprs.LambdaCallExpression( refs.InstanceFieldReference(expr.object, lambda_field), expr.args) lambda_call.set_actual_type( (lambda_field.type).return_type, True) return lambda_call method = self.find_method(intf_type, expr.method_name, False, expr.args) result = exprs.InstanceMethodCallExpression( resolved_object, method, expr.type_args, expr.args) self.resolve_return_type( result, genRes.GenericsResolver.from_object(resolved_object)) return result elif isinstance(object_type, astTypes.AnyType): expr.set_actual_type(astTypes.AnyType.instance) return expr else: pass return resolved_object
def infix_prehook(self, left): if isinstance( left, exprs.PropertyAccessExpression ) and self.reader.peek_regex("<[A-Za-z0-9_<>]*?>\\(") != None: type_args = self.parse_type_args() self.reader.expect_token("(") args = self.expression_parser.parse_call_arguments() return exprs.UnresolvedCallExpression(left, type_args, args) elif self.reader.read_token("instanceof"): type = self.parse_type() return exprs.InstanceOfExpression(left, type) elif isinstance(left, exprs.Identifier) and self.reader.read_token("=>"): block = self.parse_lambda_block() return types.Lambda( [types.MethodParameter(left.text, None, None, None)], block) return None
def visit_expression(self, expr): expr = super().visit_expression(expr) if isinstance(expr, exprs.UnresolvedCallExpression) and isinstance( expr.func, exprs.PropertyAccessExpression): return exprs.UnresolvedMethodCallExpression( expr.func.object, expr.func.property_name, expr.type_args, expr.args) return expr
def parse(self, precedence=0, required=True): self.reader.skip_whitespace() left_start = self.reader.offset left = self.parse_left(required) if left == None: return None self.add_node(left, left_start) while True: if self.hooks != None: parsed = self.hooks.infix_prehook(left) if parsed != None: left = parsed self.add_node(left, left_start) continue op = self.parse_operator() if op == None or op.precedence <= precedence: break self.reader.expect_token(op.text) op_text = self.config.aliases.get( op.text) if op.text in self.config.aliases else op.text if op.is_binary: right = self.parse(op.precedence - 1 if op.is_right_assoc else op.precedence) left = exprs.BinaryExpression(left, op_text, right) elif op.is_postfix: left = exprs.UnaryExpression(exprs.UNARY_TYPE.POSTFIX, op_text, left) elif op.text == "?": when_true = self.parse() self.reader.expect_token(":") when_false = self.parse(op.precedence - 1) left = exprs.ConditionalExpression(left, when_true, when_false) elif op.text == "(": args = self.parse_call_arguments() left = exprs.UnresolvedCallExpression(left, [], args) elif op.text == "[": element_expr = self.parse() self.reader.expect_token("]") left = exprs.ElementAccessExpression(left, element_expr) elif op.text in self.config.property_access_ops: prop = self.reader.expect_identifier( "expected identifier as property name") left = exprs.PropertyAccessExpression(left, prop) else: self.reader.fail( f'''parsing \'{op.text}\' is not yet implemented''') self.add_node(left, left_start) if isinstance(left, exprs.ParenthesizedExpression) and isinstance( left.expression, exprs.Identifier): expr = self.parse(0, False) if expr != None: return exprs.CastExpression( astTypes.UnresolvedType(left.expression.text, []), expr) return left
def transform(self, expr): call_expr = expr if isinstance(call_expr.func, refs.GlobalFunctionReference): new_expr = exprs.GlobalFunctionCallExpression( call_expr.func.decl, call_expr.args) call_expr.args = list( map(lambda arg: self.main.run_plugins_on(arg), call_expr.args)) new_expr.set_actual_type(call_expr.func.decl.returns) return new_expr else: self.main.process_expression(expr) if isinstance(call_expr.func.actual_type, astTypes.LambdaType): new_expr = exprs.LambdaCallExpression(call_expr.func, call_expr.args) new_expr.set_actual_type( call_expr.func.actual_type.return_type) return new_expr else: return expr
def transform(self, expr): # TODO: convert ElementAccess to ElementGet and ElementSet expressions if isinstance(expr, exprs.BinaryExpression) and isinstance( expr.left, exprs.ElementAccessExpression): expr.left.object = self.main.run_plugins_on(expr.left.object) if self.is_map_or_array_type(expr.left.object.get_type()): #const right = expr.operator === "=" ? expr.right : new BinaryExpression(<Expression>expr.left.clone(), expr.operator === "+=" ? "+" : "-", expr.right); return exprs.UnresolvedMethodCallExpression( expr.left.object, "set", [], [expr.left.element_expr, expr.right]) elif isinstance(expr, exprs.ElementAccessExpression): expr.object = self.main.run_plugins_on(expr.object) if self.is_map_or_array_type(expr.object.get_type()): return exprs.UnresolvedMethodCallExpression( expr.object, "get", [], [expr.element_expr]) elif isinstance(expr.element_expr, exprs.StringLiteral): return exprs.PropertyAccessExpression( expr.object, expr.element_expr.string_value) return expr
def visit_expression(self, expr): if isinstance(expr, exprs.UnresolvedNewExpression): cls_type = self.visit_type(expr.cls_) if isinstance(cls_type, astTypes.ClassType): new_expr = exprs.NewExpression(cls_type, expr.args) new_expr.parent_node = expr.parent_node super().visit_expression(new_expr) return new_expr else: self.error_man.throw( f'''Excepted ClassType, but got {cls_type}''') return expr else: return super().visit_expression(expr)
def parse_array_literal(self, start_token="[", end_token="]"): if not self.reader.read_token(start_token): return None items = [] if not self.reader.read_token(end_token): while True: item = self.parse() items.append(item) if not (self.reader.read_token(",")): break self.reader.expect_token(end_token) return exprs.ArrayLiteral(items)
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 class_like(self, cls_): self.current_class = cls_ res_list = [] static_constructor_stmts = [] complex_field_inits = [] if isinstance(cls_, types.Class): field_reprs = [] for field in cls_.fields: is_initializer_complex = field.initializer != None and not ( isinstance(field.initializer, exprs.StringLiteral) ) and not (isinstance( field.initializer, exprs.BooleanLiteral)) and not ( isinstance(field.initializer, exprs.NumericLiteral)) prefix = f'''{self.vis(field.visibility)} {self.pre_if("static ", field.is_static)}''' if len(field.interface_declarations) > 0: init = f''' = {self.expr(field.initializer)};''' if field.initializer != None else "" field_reprs.append( f'''{prefix}{self.var_wo_init(field, field)} {{ get; set; }}{init}''' ) elif is_initializer_complex: if field.is_static: static_constructor_stmts.append( stats.ExpressionStatement( exprs.BinaryExpression( refs.StaticFieldReference(field), "=", field.initializer))) else: complex_field_inits.append( stats.ExpressionStatement( exprs.BinaryExpression( refs.InstanceFieldReference( refs.ThisReference(cls_), field), "=", field.initializer))) field_reprs.append( f'''{prefix}{self.var_wo_init(field, field)};''') else: field_reprs.append( f'''{prefix}{self.var(field, field)};''') res_list.append("\n".join(field_reprs)) res_list.append("\n".join( list( map( lambda prop: f'''{self.vis(prop.visibility)} {self.pre_if("static ", prop.is_static)}''' + self.var_wo_init(prop, prop) + (f''' {{\n get {{\n{self.pad(self.block(prop.getter))}\n }}\n}}''' if prop.getter != None else "") + (f''' {{\n set {{\n{self.pad(self.block(prop.setter))}\n }}\n}}''' if prop.setter != None else ""), cls_.properties)))) if len(static_constructor_stmts) > 0: res_list.append( f'''static {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}''' ) if cls_.constructor_ != None: constr_field_inits = [] for field in list( filter(lambda x: x.constructor_param != None, cls_.fields)): field_ref = refs.InstanceFieldReference( refs.ThisReference(cls_), field) mp_ref = refs.MethodParameterReference( field.constructor_param) # TODO: decide what to do with "after-TypeEngine" transformations mp_ref.set_actual_type(field.type, False, False) constr_field_inits.append( stats.ExpressionStatement( exprs.BinaryExpression(field_ref, "=", mp_ref))) # @java var stmts = Stream.concat(Stream.concat(constrFieldInits.stream(), complexFieldInits.stream()), ((Class)cls).constructor_.getBody().statements.stream()).toArray(Statement[]::new); # @java-import java.util.stream.Stream stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements res_list.append( "public " + self.pre_if("/* throws */ ", cls_.constructor_.throws) + self.name_(cls_.name) + f'''({", ".join(list(map(lambda p: self.var(p, p), cls_.constructor_.parameters)))})''' + (f''': base({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))})''' if cls_.constructor_.super_call_args != None else "") + f'''\n{{\n{self.pad(self.stmts(stmts))}\n}}''') elif len(complex_field_inits) > 0: res_list.append( f'''public {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}''' ) elif isinstance(cls_, types.Interface): res_list.append("\n".join( list( map( lambda field: f'''{self.var_wo_init(field, field)} {{ get; set; }}''', cls_.fields)))) methods = [] for method in cls_.methods: if isinstance(cls_, types.Class) and method.body == None: continue # declaration only methods.append( ("" if isinstance(method.parent_interface, types.Interface ) else self.vis(method.visibility) + " ") + self.pre_if("static ", method.is_static) + self.pre_if( "virtual ", method.overrides == None and len(method.overridden_by) > 0) + self.pre_if("override ", method.overrides != None) + self.pre_if("async ", method.async_) + self.pre_if("/* throws */ ", method.throws) + f'''{self.type(method.returns, False)} ''' + self.name_(method.name) + self.type_args(method.type_arguments) + f'''({", ".join(list(map(lambda p: self.var(p, None), method.parameters)))})''' + (f'''\n{{\n{self.pad(self.stmts(method.body.statements))}\n}}''' if method.body != None else ";")) res_list.append("\n\n".join(methods)) return self.pad("\n\n".join(list(filter(lambda x: x != "", res_list))))
def class_(self, cls_): self.current_class = cls_ res_list = [] static_constructor_stmts = [] complex_field_inits = [] field_reprs = [] prop_reprs = [] for field in cls_.fields: is_initializer_complex = field.initializer != None and not ( isinstance(field.initializer, exprs.StringLiteral)) and not ( isinstance(field.initializer, exprs.BooleanLiteral)) and not (isinstance( field.initializer, exprs.NumericLiteral)) prefix = f'''{self.vis(field.visibility)} {self.pre_if("static ", field.is_static)}''' if len(field.interface_declarations) > 0: var_type = self.var_type(field, field) name = self.name_(field.name) pname = self.uc_first(field.name) set_to_false = astTypes.TypeHelper.equals( field.type, self.current_class.parent_file.literal_types.boolean) prop_reprs.append( f'''{var_type} {name}{(" = false" if set_to_false else f' = {self.expr(field.initializer)}' if field.initializer != None else "")};\n''' + f'''{prefix}{var_type} get{pname}() {{ return this.{name}; }}\n''' + f'''{prefix}void set{pname}({var_type} value) {{ this.{name} = value; }}''' ) elif is_initializer_complex: if field.is_static: static_constructor_stmts.append( stats.ExpressionStatement( exprs.BinaryExpression( refs.StaticFieldReference(field), "=", field.initializer))) else: complex_field_inits.append( stats.ExpressionStatement( exprs.BinaryExpression( refs.InstanceFieldReference( refs.ThisReference(cls_), field), "=", field.initializer))) field_reprs.append( f'''{prefix}{self.var_wo_init(field, field)};''') else: field_reprs.append(f'''{prefix}{self.var(field, field)};''') res_list.append("\n".join(field_reprs)) res_list.append("\n\n".join(prop_reprs)) for prop in cls_.properties: prefix = f'''{self.vis(prop.visibility)} {self.pre_if("static ", prop.is_static)}''' if prop.getter != None: res_list.append( f'''{prefix}{self.type(prop.type)} get{self.uc_first(prop.name)}(){self.block(prop.getter, False)}''' ) if prop.setter != None: res_list.append( f'''{prefix}void set{self.uc_first(prop.name)}({self.type(prop.type)} value){self.block(prop.setter, False)}''' ) if len(static_constructor_stmts) > 0: res_list.append( f'''static {{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}''' ) if cls_.constructor_ != None: constr_field_inits = [] for field in list( filter(lambda x: x.constructor_param != None, cls_.fields)): field_ref = refs.InstanceFieldReference( refs.ThisReference(cls_), field) mp_ref = refs.MethodParameterReference(field.constructor_param) # TODO: decide what to do with "after-TypeEngine" transformations mp_ref.set_actual_type(field.type, False, False) constr_field_inits.append( stats.ExpressionStatement( exprs.BinaryExpression(field_ref, "=", mp_ref))) super_call = f'''super({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))});\n''' if cls_.constructor_.super_call_args != None else "" # @java var stmts = Stream.of(constrFieldInits, complexFieldInits, cls.constructor_.getBody().statements).flatMap(Collection::stream).toArray(Statement[]::new); # @java-import java.util.Collection # @java-import java.util.stream.Stream stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements # TODO: super calls res_list.append( self.method_gen( "public " + self.pre_if("/* throws */ ", cls_.constructor_.throws) + self.name_(cls_.name), cls_.constructor_.parameters, f'''\n{{\n{self.pad(super_call + self.stmts(stmts))}\n}}''' )) elif len(complex_field_inits) > 0: res_list.append( f'''public {self.name_(cls_.name)}()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}''' ) methods = [] for method in cls_.methods: if method.body == None: continue # declaration only methods.append(self.method(method, True)) res_list.append("\n\n".join(methods)) return self.pad("\n\n".join(list(filter(lambda x: x != "", res_list))))
def class_like(self, cls_): self.current_class = cls_ res_list = [] static_constructor_stmts = [] complex_field_inits = [] if isinstance(cls_, types.Class): field_reprs = [] for field in cls_.fields: is_initializer_complex = field.initializer != None and not (isinstance(field.initializer, exprs.StringLiteral)) and not (isinstance(field.initializer, exprs.BooleanLiteral)) and not (isinstance(field.initializer, exprs.NumericLiteral)) prefix = f'''{self.vis(field.visibility, True)}{self.pre_if("static ", field.is_static)}''' if is_initializer_complex: if field.is_static: static_constructor_stmts.append(stats.ExpressionStatement(exprs.BinaryExpression(refs.StaticFieldReference(field), "=", field.initializer))) else: complex_field_inits.append(stats.ExpressionStatement(exprs.BinaryExpression(refs.InstanceFieldReference(refs.ThisReference(cls_), field), "=", field.initializer))) field_reprs.append(f'''{prefix}{self.var_wo_init(field, field)};''') else: field_reprs.append(f'''{prefix}{self.var(field, field)};''') res_list.append("\n".join(field_reprs)) for prop in cls_.properties: if prop.getter != None: res_list.append(self.vis(prop.visibility, False) + self.pre_if("static ", prop.is_static) + f'''function get_{self.name_(prop.name)}(){self.block(prop.getter, False)}''') if prop.setter != None: res_list.append(self.vis(prop.visibility, False) + self.pre_if("static ", prop.is_static) + f'''function set_{self.name_(prop.name)}($value){self.block(prop.setter, False)}''') if len(static_constructor_stmts) > 0: res_list.append(f'''static function StaticInit()\n{{\n{self.pad(self.stmts(static_constructor_stmts))}\n}}''') if cls_.constructor_ != None: constr_field_inits = [] for field in list(filter(lambda x: x.constructor_param != None, cls_.fields)): field_ref = refs.InstanceFieldReference(refs.ThisReference(cls_), field) mp_ref = refs.MethodParameterReference(field.constructor_param) # TODO: decide what to do with "after-TypeEngine" transformations mp_ref.set_actual_type(field.type, False, False) constr_field_inits.append(stats.ExpressionStatement(exprs.BinaryExpression(field_ref, "=", mp_ref))) parent_call = f'''parent::__construct({", ".join(list(map(lambda x: self.expr(x), cls_.constructor_.super_call_args)))});\n''' if cls_.constructor_.super_call_args != None else "" # @java var stmts = Stream.of(constrFieldInits, complexFieldInits, ((Class)cls).constructor_.getBody().statements).flatMap(Collection::stream).toArray(Statement[]::new); # @java-import java.util.Collection # @java-import java.util.stream.Stream stmts = constr_field_inits + complex_field_inits + cls_.constructor_.body.statements res_list.append(self.pre_if("/* throws */ ", cls_.constructor_.throws) + "function __construct" + f'''({", ".join(list(map(lambda p: self.var(p, p), cls_.constructor_.parameters)))})''' + f''' {{\n{self.pad(parent_call + self.stmts(stmts))}\n}}''') elif len(complex_field_inits) > 0: res_list.append(f'''function __construct()\n{{\n{self.pad(self.stmts(complex_field_inits))}\n}}''') elif isinstance(cls_, types.Interface): pass methods = [] for method in cls_.methods: if isinstance(cls_, types.Class) and method.body == None: continue # declaration only methods.append(("" if isinstance(method.parent_interface, types.Interface) else self.vis(method.visibility, False)) + self.pre_if("static ", method.is_static) + self.pre_if("/* throws */ ", method.throws) + f'''function ''' + self.name_(method.name) + self.type_args(method.type_arguments) + f'''({", ".join(list(map(lambda p: self.var(p, None), method.parameters)))})''' + (f''' {{\n{self.pad(self.stmts(method.body.statements))}\n}}''' if method.body != None else ";")) res_list.append("\n\n".join(methods)) res_list_joined = self.pad("\n\n".join(list(filter(lambda x: x != "", res_list)))) return f''' {{\n{res_list_joined}\n}}''' + (f'''\n{self.name_(cls_.name)}::StaticInit();''' if len(static_constructor_stmts) > 0 else "")
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