public BoundExpression BindExpression(ExpressionSyntax node) { switch (node.Kind) { case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: case SyntaxKind.NumericLiteralExpression: case SyntaxKind.StringLiteralExpression: return ProcessLiteral((LiteralExpressionSyntax) node); case SyntaxKind.IdentifierName: return ProcessIdentifierName((IdentifierNameSyntax) node); case SyntaxKind.PreDecrementExpression: case SyntaxKind.PreIncrementExpression: return ProcessPrefixUnary((PrefixUnaryExpressionSyntax) node); case SyntaxKind.UnaryMinusExpression: case SyntaxKind.UnaryPlusExpression: case SyntaxKind.LogicalNotExpression: case SyntaxKind.BitwiseNotExpression: case SyntaxKind.PostDecrementExpression: case SyntaxKind.PostIncrementExpression: return ProcessPostfixUnary((PostfixUnaryExpressionSyntax)node); case SyntaxKind.MemberAccessExpression: return ProcessMemberAccess((MemberAccessExpressionSyntax) node); default: throw new ArgumentOutOfRangeException(); } }
private object Evaluate(ExpressionSyntax expr) { if (expr == null) return null; switch (expr.Kind) { case SyntaxKind.ParenthesizedExpression: return Evaluate(((ParenthesizedExpressionSyntax)expr).Expression); case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: case SyntaxKind.NumericLiteralExpression: return ((LiteralExpressionSyntax)expr).Token.Value; case SyntaxKind.LogicalAndExpression: case SyntaxKind.BitwiseAndExpression: return EvaluateBool(((BinaryExpressionSyntax)expr).Left) && EvaluateBool(((BinaryExpressionSyntax)expr).Right); case SyntaxKind.LogicalOrExpression: case SyntaxKind.BitwiseOrExpression: return EvaluateBool(((BinaryExpressionSyntax)expr).Left) || EvaluateBool(((BinaryExpressionSyntax)expr).Right); case SyntaxKind.EqualsExpression: return Equals(Evaluate(((BinaryExpressionSyntax)expr).Left), Evaluate(((BinaryExpressionSyntax)expr).Right)); case SyntaxKind.NotEqualsExpression: return !Equals(Evaluate(((BinaryExpressionSyntax)expr).Left), Evaluate(((BinaryExpressionSyntax)expr).Right)); case SyntaxKind.LogicalNotExpression: return !EvaluateBool(((PrefixUnaryExpressionSyntax)expr).Operand); case SyntaxKind.AddExpression: return EvaluateInt(((BinaryExpressionSyntax)expr).Left) + EvaluateInt(((BinaryExpressionSyntax)expr).Right); case SyntaxKind.SubtractExpression: return EvaluateInt(((BinaryExpressionSyntax)expr).Left) - EvaluateInt(((BinaryExpressionSyntax)expr).Right); case SyntaxKind.MultiplyExpression: return EvaluateInt(((BinaryExpressionSyntax)expr).Left) * EvaluateInt(((BinaryExpressionSyntax)expr).Right); case SyntaxKind.DivideExpression: var divisor = EvaluateInt(((BinaryExpressionSyntax) expr).Right); return (divisor != 0) ? EvaluateInt(((BinaryExpressionSyntax) expr).Left) / divisor : int.MaxValue; case SyntaxKind.IdentifierName: var id = ((IdentifierNameSyntax)expr).Name.Text; return IsDirectiveDefined(id); case SyntaxKind.InvocationExpression: // It must be a call to "defined" - that's the only one allowed by the parser. var functionCall = (InvocationExpressionSyntax)expr; var identifierName = ((IdentifierNameSyntax)functionCall.ArgumentList.Arguments[0]).Name; return IsDirectiveDefined(identifierName.Text); default: return false; } }
private int EvaluateInt(ExpressionSyntax expr) { var result = Evaluate(expr); if (result is int) return (int)result; return 0; }
private bool EvaluateBool(ExpressionSyntax expr) { var result = Evaluate(expr); if (result is bool) return (bool)result; if (result is int) return (int)result != 0; return false; }
private ExpressionSyntax ParsePostFixExpression(ExpressionSyntax expr) { Debug.Assert(expr != null); while (true) { var tk = Current.Kind; switch (tk) { case SyntaxKind.OpenParenToken: expr = new InvocationExpressionSyntax(expr, ParseParenthesizedArgumentList(false)); break; case SyntaxKind.OpenBracketToken: expr = new ElementAccessExpressionSyntax(expr, Match(SyntaxKind.OpenBracketToken), ParseExpression(), Match(SyntaxKind.CloseBracketToken)); break; case SyntaxKind.PlusPlusToken: case SyntaxKind.MinusMinusToken: expr = new PostfixUnaryExpressionSyntax(SyntaxFacts.GetPostfixUnaryExpression(tk), expr, NextToken()); break; case SyntaxKind.DotToken: expr = new MemberAccessExpressionSyntax(expr, NextToken(), ParseIdentifier()); break; default: return expr; } } }
private BoundExpression GetBoundExpression(ExpressionSyntax expression) { return _bindingResult.GetBoundNode(expression) as BoundExpression; }
public Symbol GetSymbol(ExpressionSyntax expression) { var boundExpression = GetBoundExpression(expression); return boundExpression == null ? null : GetSymbol(boundExpression); }
public TypeSymbol GetExpressionType(ExpressionSyntax expression) { var boundExpression = GetBoundExpression(expression); return boundExpression?.Type; }