Upsilon/Upsilon/Evaluator/Evaluator.cs

79 lines
2.8 KiB
C#

using System;
using Upsilon.Parser;
namespace Upsilon.Evaluator
{
public static class Evaluator
{
public static object Evaluate(this ScriptSyntax e)
{
return EvaluateExpression(e.Statement);
}
public static object Evaluate(this ExpressionSyntax e)
{
return EvaluateExpression(e);
}
private static object EvaluateExpression(ExpressionSyntax e)
{
switch (e.Kind)
{
case SyntaxKind.UnaryExpression:
return EvaluateUnaryExpression((UnaryExpressionSyntax) e);
case SyntaxKind.BinaryExpression:
return EvaluateBinaryExpression((BinaryExpressionSyntax) e);
case SyntaxKind.LiteralExpression:
return ((LiteralExpressionSyntax) e).Value;
case SyntaxKind.ParenthesizedExpression:
return ((ParenthesizedExpressionSyntax) e).Expression.Evaluate();
default:
throw new Exception("Invalid expression: " + e.Kind);
}
}
private static object EvaluateUnaryExpression(UnaryExpressionSyntax e)
{
var operand = EvaluateExpression(e.Expression);
switch (e.Operator.Kind)
{
case SyntaxKind.Plus:
return operand;
case SyntaxKind.Minus:
return -(double) operand;
case SyntaxKind.NotKeyword:
return !(bool)operand;
default:
throw new Exception("Invalid Unary Operator: " + e.Operator.Kind);
}
}
private static object EvaluateBinaryExpression(BinaryExpressionSyntax e)
{
var left = EvaluateExpression(e.Left);
var right = EvaluateExpression(e.Right);
switch (e.Operator.Kind)
{
case SyntaxKind.Plus:
return (double)left + (double)right;
case SyntaxKind.Minus:
return (double)left - (double)right;
case SyntaxKind.Star:
return (double)left * (double)right;
case SyntaxKind.Slash:
return (double)left / (double)right;
case SyntaxKind.AndKeyword:
return (bool)left && (bool)right;
case SyntaxKind.OrKeyword:
return (bool)left || (bool)right;
case SyntaxKind.EqualsEquals:
return Equals(left, right);
case SyntaxKind.TildeEquals:
return !Equals(left, right);
default:
throw new Exception("Invalid Binary Operator: " + e.Operator.Kind);
}
}
}
}