using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Swan.Parsers {
///
/// 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) => this.ResolveExpression(tokens, System.Globalization.CultureInfo.InvariantCulture);
///
/// Resolves the expression.
///
/// The type of expression result.
/// The tokens.
/// The format provider.
/// The representation of the expression parsed.
public virtual T ResolveExpression(IEnumerable tokens, IFormatProvider formatProvider) {
UnaryExpression conversion = Expression.Convert(this.Parse(tokens, formatProvider), typeof(T));
return Expression.Lambda>(conversion).Compile()();
}
///
/// Parses the specified tokens.
///
/// The tokens.
///
/// The final expression.
///
public virtual Expression Parse(IEnumerable tokens) => this.Parse(tokens, System.Globalization.CultureInfo.InvariantCulture);
///
/// Parses the specified tokens.
///
/// The tokens.
/// The format provider.
///
/// The final expression.
///
public virtual Expression Parse(IEnumerable tokens, IFormatProvider formatProvider) {
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, formatProvider)));
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);
}
}