using System; using System.Linq; using System.Collections.Generic; using System.Linq.Expressions; namespace Unosquare.Swan.Abstractions { /// /// Represents a generic expression parser. /// public abstract class ExpressionParser { /// /// Resolves the expression. /// /// The type of expression result. /// The tokens. /// The representation of the expression parsed. public virtual T ResolveExpression(IEnumerable tokens) { UnaryExpression conversion = Expression.Convert(this.Parse(tokens), typeof(T)); return Expression.Lambda>(conversion).Compile()(); } /// /// Parses the specified tokens. /// /// The tokens. /// The final expression. public virtual Expression Parse(IEnumerable tokens) { List> expressionStack = new List>(); foreach(Token token in tokens) { if(expressionStack.Any() == false) { expressionStack.Add(new Stack()); } switch(token.Type) { case TokenType.Wall: expressionStack.Add(new Stack()); break; case TokenType.Number: expressionStack.Last().Push(Expression.Constant(Convert.ToDecimal(token.Value))); break; case TokenType.Variable: this.ResolveVariable(token.Value, expressionStack.Last()); break; case TokenType.String: expressionStack.Last().Push(Expression.Constant(token.Value)); break; case TokenType.Operator: this.ResolveOperator(token.Value, expressionStack.Last()); break; case TokenType.Function: this.ResolveFunction(token.Value, expressionStack.Last()); if(expressionStack.Count > 1 && expressionStack.Last().Count == 1) { Expression lastValue = expressionStack.Last().Pop(); _ = expressionStack.Remove(expressionStack.Last()); expressionStack.Last().Push(lastValue); } break; } } return expressionStack.Last().Pop(); } /// /// Resolves the variable. /// /// The value. /// The expression stack. public abstract void ResolveVariable(String value, Stack expressionStack); /// /// Resolves the operator. /// /// The value. /// The expression stack. public abstract void ResolveOperator(String value, Stack expressionStack); /// /// Resolves the function. /// /// The value. /// The expression stack. public abstract void ResolveFunction(String value, Stack expressionStack); } }