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);
}
}