Skip to content

Instantly share code, notes, and snippets.

@painquin
Created November 19, 2009 03:18
Show Gist options
  • Save painquin/238522 to your computer and use it in GitHub Desktop.
Save painquin/238522 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.Linq.Expressions;
/*
* Disclaimer: No validation, only use on good input
* Also, Pants is the name of the game engine I'm working on.
*/
namespace Pants {
class psr
{
static bool IsNumber(char c)
{
return (c >= '0' && c <= '9');
}
class Operator
{
public int Precedence { get; set; }
public Func<Expression,Expression,Expression> Operation { get; set; }
}
static Dictionary<char,Operator> operators;
static psr()
{
operators = new Dictionary<char, Operator>() {
{ '+', new Operator {
Precedence = 1,
Operation = (a,b) => Expression.Add(a,b)
}},
{ '-', new Operator {
Precedence = 1,
Operation = (a,b) => Expression.Subtract(a,b)
}},
{ '*', new Operator {
Precedence = 2,
Operation = (a,b) => Expression.Multiply(a,b)
}},
{ '/', new Operator {
Precedence = 2,
Operation = (a,b) => Expression.Divide(a,b)
}},
{ '(', null }
};
}
public static LambdaExpression Parse(string expression)
{
Stack<Expression> outputStack = new Stack<Expression>();
Stack<Operator> operatorStack = new Stack<Operator>();
ParameterExpression Level = Expression.Parameter(typeof(int), "L");
CharEnumerator e = expression.GetEnumerator();
int cNumber = 0;
bool parsing_number = false;
while (e.MoveNext())
{
if (IsNumber(e.Current))
{
if (!parsing_number)
{
cNumber = 0;
parsing_number = true;
}
cNumber = cNumber * 10 + (e.Current - '0');
continue;
}
else if (parsing_number)
{
parsing_number = false;
outputStack.Push(Expression.Constant(cNumber));
}
if (e.Current == ' ') continue;
if (e.Current == '(')
{
operatorStack.Push(null);
continue;
}
Operator o;
if (operators.TryGetValue(e.Current, out o))
{
while (operatorStack.Count > 0 && operatorStack.Peek() != null && o.Precedence <= operatorStack.Peek().Precedence)
{
Expression a, b;
b = outputStack.Pop();
a = outputStack.Pop();
outputStack.Push(operatorStack.Pop().Operation(a, b));
}
operatorStack.Push(o);
continue;
}
if (e.Current == ')')
{
while (operatorStack.Count > 0 && operatorStack.Peek() != null)
{
Expression a, b;
b = outputStack.Pop();
a = outputStack.Pop();
outputStack.Push(operatorStack.Pop().Operation(a,b));
}
operatorStack.Pop();
}
if (e.Current == 'L')
{
outputStack.Push(Level);
continue;
}
}
if (parsing_number)
{
outputStack.Push(Expression.Constant(cNumber));
}
while (operatorStack.Count > 0)
{
Expression a, b;
b = outputStack.Pop();
a = outputStack.Pop();
outputStack.Push(operatorStack.Pop().Operation(a, b));
}
return Expression.Lambda<Func<int, int>>(outputStack.Pop(), Level);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment