private static string parse(Dictionary<string, double> terms, Expression expr, ref double value)
{
if (expr == null)
return null;
BinaryExpression eb = expr as BinaryExpression;
MemberExpression em = expr as MemberExpression;
UnaryExpression eu = expr as UnaryExpression;
if (em != null) // member expression
{
string term = em.Member.Name;
terms[term] = 1;
return term;
}
else if (eb != null) // binary expression
{
if (expr.NodeType == ExpressionType.Multiply)
{
// This could be either a constant times and expression or a quadratic member
ConstantExpression a = eb.Left as ConstantExpression ?? eb.Right as ConstantExpression;
MemberExpression m = eb.Left as MemberExpression ?? eb.Right as MemberExpression;
UnaryExpression u = eb.Left as UnaryExpression ?? eb.Right as UnaryExpression;
if (a != null)
{
// This is a constant times an expression
double scalar = (double)a.Value;
string term = parse(terms, (Expression)m ?? (Expression)u, ref value);
terms[term] = scalar;
return term;
}
else throw new FormatException("Unexpected expression.");
}
else if (expr.NodeType == ExpressionType.Add)
{
// This could be an expression + term, a term + expression or an expression + expression
BinaryExpression lb = eb.Left as BinaryExpression;
MemberExpression lm = eb.Left as MemberExpression;
UnaryExpression lu = eb.Left as UnaryExpression;
ConstantExpression lc = eb.Left as ConstantExpression;
BinaryExpression rb = eb.Right as BinaryExpression;
MemberExpression rm = eb.Right as MemberExpression;
ConstantExpression rc = eb.Right as ConstantExpression;
if (lb != null)
{
parse(terms, lb, ref value);
}
else if (lm != null)
{
terms[lm.Member.Name] = 1;
}
else if (lu != null)
{
parse(terms, lu, ref value);
}
else if (lc != null)
{
value += (double)lc.Value;
}
else throw new FormatException("Unexpected expression.");
if (rb != null)
{
parse(terms, rb, ref value);
}
else if (rm != null)
{
terms[rm.Member.Name] = 1;
}
else if (rc != null)
{
value += (double)rc.Value;
}
else throw new FormatException("Unexpected expression.");
}
else if (expr.NodeType == ExpressionType.Subtract)
{
// This could be an expression - term, a term - expression or an expression - expression
BinaryExpression lb = eb.Left as BinaryExpression;
MemberExpression lm = eb.Left as MemberExpression;
UnaryExpression lu = eb.Left as UnaryExpression;
BinaryExpression rb = eb.Right as BinaryExpression;
MemberExpression rm = eb.Right as MemberExpression;
ConstantExpression rc = eb.Right as ConstantExpression;
if (lb != null)
parse(terms, lb, ref value);
else if (lm != null)
terms[lm.Member.Name] = 1;
else if (lu != null)
parse(terms, lu, ref value);
else throw new FormatException("Unexpected expression.");
if (rb != null)
{
var term = parse(terms, rb, ref value);
terms[term] = -terms[term];
}
else if (rm != null)
{
terms[rm.Member.Name] = -1;
}
else if (rc != null)
{
value -= (double)rc.Value;
}
else throw new FormatException("Unexpected expression.");
}
}
else if (eu != null) // unary expression
{
if (expr.NodeType == ExpressionType.UnaryPlus)
{
BinaryExpression lb = eu.Operand as BinaryExpression;
MemberExpression lm = eu.Operand as MemberExpression;
ConstantExpression lc = eu.Operand as ConstantExpression;
if (lm != null)
{
terms[lm.Member.Name] = 1;
}
else if (lb != null)
{
parse(terms, lb, ref value);
}
else if (lc != null)
{
value += (double)lc.Value;
}
else throw new FormatException("Unexpected expression.");
}
else if (expr.NodeType == ExpressionType.Negate)
{
BinaryExpression lb = eu.Operand as BinaryExpression;
MemberExpression lm = eu.Operand as MemberExpression;
ConstantExpression lc = eu.Operand as ConstantExpression;
if (lm != null)
{
terms[lm.Member.Name] = -1;
}
else if (lb != null)
{
var term = parse(terms, lb, ref value);
terms[term] = -terms[term];
}
else if (lc != null)
{
value -= (double)lc.Value;
}
else throw new FormatException("Unexpected expression.");
}
else throw new FormatException("Unexpected expression.");
}
else throw new FormatException("Unexpected expression.");
return null;
}