protected override Expression visitExpression(Expression expr) { var origExpr = expr; expr = base.visitExpression(expr); if (expr is BinaryExpression binExpr && binExpr.operator_ == "in") { expr = new UnresolvedCallExpression(new PropertyAccessExpression(binExpr.right, "hasKey"), new IType[0], new Expression[] { binExpr.left }); } expr.parentNode = origExpr.parentNode; return(expr); }
public Expression parse(int precedence = 0, bool required = true) { this.reader.skipWhitespace(); var leftStart = this.reader.offset; var left = this.parseLeft(required); if (left == null) { return(null); } this.addNode(left, leftStart); while (true) { if (this.hooks != null) { var parsed = this.hooks.infixPrehook(left); if (parsed != null) { left = parsed; this.addNode(left, leftStart); continue; } } var op = this.parseOperator(); if (op == null || op.precedence <= precedence) { break; } this.reader.expectToken(op.text); var opText = this.config.aliases.hasKey(op.text) ? this.config.aliases.get(op.text) : op.text; if (op.isBinary) { var right = this.parse(op.isRightAssoc ? op.precedence - 1 : op.precedence); left = new BinaryExpression(left, opText, right); } else if (op.isPostfix) { left = new UnaryExpression(UnaryType.Postfix, opText, left); } else if (op.text == "?") { var whenTrue = this.parse(); this.reader.expectToken(":"); var whenFalse = this.parse(op.precedence - 1); left = new ConditionalExpression(left, whenTrue, whenFalse); } else if (op.text == "(") { var args = this.parseCallArguments(); left = new UnresolvedCallExpression(left, new IType[0], args); } else if (op.text == "[") { var elementExpr = this.parse(); this.reader.expectToken("]"); left = new ElementAccessExpression(left, elementExpr); } else if (this.config.propertyAccessOps.includes(op.text)) { var prop = this.reader.expectIdentifier("expected identifier as property name"); left = new PropertyAccessExpression(left, prop); } else { this.reader.fail($"parsing '{op.text}' is not yet implemented"); } this.addNode(left, leftStart); } if (left is ParenthesizedExpression parExpr && parExpr.expression is Identifier ident) { var expr = this.parse(0, false); if (expr != null) { return(new CastExpression(new UnresolvedType(ident.text, new IType[0]), expr)); } } return(left); }