public IOperand Parse <T>(string text) where T : IConvertible { IsTyped = typeof(T) != typeof(IConvertible); scanner = Scanner.Create(text); Clause = IsTyped ? new Sum <T>() : new Sum(); // it could have just one operand IOperand lastOperand = GetOperand <T>(); Clause.AddOperand(lastOperand); IOperation working = Clause; IOperand nextOperand = null; while (!ParseEnd) { IOperator op = GetOperation(); nextOperand = GetOperand <T>(); IOperation newOp; if (op.AssociationType == working.AssociationType) { // working can only be sum/product working.AddOperand(nextOperand, op.IsInverted); } else { switch (op.AssociationType) { case AssociationType.Addition: // always return to the root when adding if (!ReferenceEquals(working, Clause)) { working = Clause; } working.AddOperand(nextOperand, op.IsInverted); break; case AssociationType.Multiplicaton: //"steal" last operand from Clause, and change working to the new op newOp = op.GetFunction(); newOp.AddOperand(lastOperand); newOp.AddOperand(nextOperand, op.IsInverted); Clause.ReplaceLastOperand(newOp); working = newOp; break; case AssociationType.Power: // Similar to Multiplication, but does not change the active chain to the new operation. It can never be added to. newOp = op.GetFunction(); newOp.AddOperand(lastOperand); newOp.AddOperand(nextOperand, op.IsInverted); Clause.ReplaceLastOperand(newOp); break; case AssociationType.Function: // Similar to Multiplication, but does not change the active chain to the new operation. It can never be added to. newOp = op.GetFunction(); newOp.AddOperand(nextOperand, op.IsInverted); Clause.ReplaceLastOperand(newOp); break; default: throw new NotImplementedException("Unknown association type."); } } lastOperand = nextOperand; } Error = ""; return((IOperand)Clause); }