Symbol SymbolicateValue(string formula, int begin, int end, Expression exp)
{
if (formula[begin] == '+')
{
begin++;
}
// Check for string value
if (formula[begin] == '\'' && formula[end - 1] == '\'')
{
var svalue = formula.Substring(begin + 1, end - begin - 2).Replace("\\'", "'");
return(new Symbol(svalue));
}
int depth = 0;
for (int k = begin; k < end; k++)
{
if (formula[k] == '(')
{
depth++;
}
else if (formula[k] == ')')
{
depth--;
}
else if (depth == 0 && formula[k] == '^')
{
// Check for small integer powers: they will be done using multiplication instead!
Symbol lhs = Symbolicate(formula, begin, k, exp);
Symbol rhs = Symbolicate(formula, k + 1, end, exp);
var newSubExpression = new SymbolList();
if (end - k - 1 == 1 && lhs.type == SymbolType.RealValue && formula.Substring(k + 1, end - k - 1) == "2")
{
// Second power found
newSubExpression.Append(lhs);
newSubExpression.Append(lhs);
}
else if (end - k - 1 == 1 && lhs.type == SymbolType.RealValue && formula.Substring(k + 1, end - k - 1) == "3")
{
// Second power found
newSubExpression.Append(lhs);
newSubExpression.Append(lhs);
newSubExpression.Append(lhs);
}
else
{
newSubExpression.Append(new Symbol(SymbolType.Pow));
newSubExpression.Append(lhs);
newSubExpression.Append(rhs);
}
Symbol newSymbol = new Symbol(SymbolType.SubExpression);
newSymbol.subExpression = newSubExpression;
return(newSymbol);
}
}
if (formula[begin] == '(' && formula[end - 1] == ')')
{
var s = Symbolicate(formula, begin + 1, end - 1, exp);
s.Simplify();
return(s);
}
double valueAsRealNumber;
if (double.TryParse(formula.Substring(begin, end - begin), out valueAsRealNumber))
{
return(new Symbol(valueAsRealNumber));
}
// Check if the value is transformed by a function
if (formula[end - 1] == ')')
{
int i = begin;
while (i < end - 1)
{
if (formula[i] == '(')
{
break;
}
i++;
}
string funcName = formula.Substring(begin, i - begin);
CustomFunction customFunc;
if (customFuncs.TryGetValue(funcName, out customFunc))
{
int requiredParameterCount = customFunc.paramCount;
int foundParameterCount = SolverTools.CountParameters(formula, begin, end);
if (requiredParameterCount == foundParameterCount)
{
if (requiredParameterCount == 1)
{
SymbolList newSubExpression = new SymbolList();
newSubExpression.Append(new Symbol(customFunc));
newSubExpression.Append(Symbolicate(formula, i + 1, end - 1, exp));
return(new Symbol(newSubExpression));
}
else
{
List <SolverTools.IntPair> parameters = SolverTools.ParseParameters(formula, i, end);
SymbolList newSubExpression = new SymbolList();
newSubExpression.Append(new Symbol(customFunc));
for (int k = 0; k < requiredParameterCount; k++)
{
Symbol p = Symbolicate(formula, parameters[k].first, parameters[k].second, exp);
newSubExpression.Append(p);
}
Symbol newSymbol = new Symbol(SymbolType.SubExpression);
newSymbol.subExpression = newSubExpression;
return(newSymbol);
}
}
else
{
throw new ESInvalidParametersException(customFunc.name + " expects " + requiredParameterCount + " parameters, " + foundParameterCount + " given.");
}
}
else
{
throw new ESInvalidFunctionNameException(funcName);
}
}
var valueName = formula.Substring(begin, end - begin);
// Then a local constant specific to our expression
Variable variable;
if (exp.constants.TryGetValue(valueName, out variable))
{
return(new Symbol(variable));
}
// Non immutable globals
if (globalConstants.TryGetValue(valueName, out variable))
{
return(new Symbol(variable));
}
// Immutable globals
double constDouble;
if (immutableGlobalConstants.TryGetValue(valueName, out constDouble))
{
return(new Symbol(constDouble));
}
// Found an unknown value name. Check policy to see what to do.
Variable v = null;
switch (undefinedVariablePolicy)
{
case UndefinedVariablePolicy.DefineExpressionLocalVariable:
v = new Variable(valueName, 0);
exp.constants.Add(valueName, v);
return(new Symbol(v));
case UndefinedVariablePolicy.DefineGlobalVariable:
v = new Variable(valueName, 0);
globalConstants.Add(valueName, v);
return(new Symbol(v));
default:
throw new ESUnknownExpressionException(valueName);
}
}