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.GreaterThanExpression:
return EvaluateInt(((BinaryExpressionSyntax)expr).Left) > EvaluateInt(((BinaryExpressionSyntax)expr).Right);
case SyntaxKind.GreaterThanOrEqualExpression:
return EvaluateInt(((BinaryExpressionSyntax)expr).Left) >= EvaluateInt(((BinaryExpressionSyntax)expr).Right);
case SyntaxKind.LessThanExpression:
return EvaluateInt(((BinaryExpressionSyntax)expr).Left) < EvaluateInt(((BinaryExpressionSyntax)expr).Right);
case SyntaxKind.LessThanOrEqualExpression:
return EvaluateInt(((BinaryExpressionSyntax)expr).Left) <= EvaluateInt(((BinaryExpressionSyntax)expr).Right);
case SyntaxKind.IdentifierName:
var id = ((IdentifierNameSyntax)expr).Name.Text;
return IsDirectiveDefined(id);
case SyntaxKind.FunctionInvocationExpression:
// It must be a call to "defined" - that's the only one allowed by the parser.
var functionCall = (FunctionInvocationExpressionSyntax)expr;
var identifierName = ((IdentifierNameSyntax)functionCall.ArgumentList.Arguments[0]).Name;
return IsDirectiveDefined(identifierName.Text);
default:
return false;
}
}