89 lines
3.2 KiB
C#
89 lines
3.2 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Linq.Expressions;
|
|
|
|
namespace Unosquare.Swan.Abstractions {
|
|
/// <summary>
|
|
/// Represents a generic expression parser.
|
|
/// </summary>
|
|
public abstract class ExpressionParser {
|
|
/// <summary>
|
|
/// Resolves the expression.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of expression result.</typeparam>
|
|
/// <param name="tokens">The tokens.</param>
|
|
/// <returns>The representation of the expression parsed.</returns>
|
|
public virtual T ResolveExpression<T>(IEnumerable<Token> tokens) {
|
|
UnaryExpression conversion = Expression.Convert(this.Parse(tokens), typeof(T));
|
|
return Expression.Lambda<Func<T>>(conversion).Compile()();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses the specified tokens.
|
|
/// </summary>
|
|
/// <param name="tokens">The tokens.</param>
|
|
/// <returns>The final expression.</returns>
|
|
public virtual Expression Parse(IEnumerable<Token> tokens) {
|
|
List<Stack<Expression>> expressionStack = new List<Stack<Expression>>();
|
|
|
|
foreach(Token token in tokens) {
|
|
if(expressionStack.Any() == false) {
|
|
expressionStack.Add(new Stack<Expression>());
|
|
}
|
|
|
|
switch(token.Type) {
|
|
case TokenType.Wall:
|
|
expressionStack.Add(new Stack<Expression>());
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolves the variable.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
/// <param name="expressionStack">The expression stack.</param>
|
|
public abstract void ResolveVariable(String value, Stack<Expression> expressionStack);
|
|
|
|
/// <summary>
|
|
/// Resolves the operator.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
/// <param name="expressionStack">The expression stack.</param>
|
|
public abstract void ResolveOperator(String value, Stack<Expression> expressionStack);
|
|
|
|
/// <summary>
|
|
/// Resolves the function.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
/// <param name="expressionStack">The expression stack.</param>
|
|
public abstract void ResolveFunction(String value, Stack<Expression> expressionStack);
|
|
}
|
|
}
|