private static void ToString(Expression x, StringBuilder sb) { if (x is OpNode) { OpNode o = (OpNode)x; sb.Append("("); ToString(o.leftChild, sb); sb.Append(o.GetSymbol()); ToString(o.rightChild, sb); sb.Append(")"); } else { if (x is TermNode) { TermNode t = (TermNode)x; if (t.GetNegate()) { sb.Append("("); sb.Append("-"); } sb.Append(t.GetName()); if (t is FuncNode) { FuncNode f = (FuncNode)t; sb.Append("("); if (f.NumChildren() > 0) { ToString(f.Child(0), sb); } for (int i = 1; i < f.NumChildren(); i++) { sb.Append(", "); ToString(f.Child(i), sb); } sb.Append(")"); } if (t.GetNegate()) { sb.Append(")"); } } else { if (x is ValNode) { sb.Append(((ValNode)x).val); } } } }
private static void GetTermNames(Expression x, Bag b, bool varNames) { if (x is OpNode) { OpNode o = (OpNode)x; GetTermNames(o.leftChild, b, varNames); GetTermNames(o.rightChild, b, varNames); } else { if (x is VarNode) { if (varNames) { VarNode v = (VarNode)x; if (!b.Contains(v.name)) { b.Add(v.name); } } } else { if (x is FuncNode) { FuncNode f = (FuncNode)x; if (!varNames) { if (!b.Contains(f.name)) { b.Add(f.name); } } for (int i = 0; i < f.NumChildren(); i++) { GetTermNames(f.Child(i), b, varNames); } } } } }
private static Expression Build(string s, int indexErrorOffset) { // do not remove (required condition for functions with no parameters, e.g. Pi()) if (s.Trim().Length == 0) { return(null); } Stack s1 = Stack.Allocate(); // contains expression nodes Stack s2 = Stack.Allocate(); try { // contains open brackets ( and operators ^,*,/,+,- bool term = true; // indicates a term should come next, not an operator bool signed = false; // indicates if the current term has been signed bool negate = false; // indicates if the sign of the current term is negated for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c == ' ' || c == '\t' || c == '\n') { continue; } if (term) { if (c == '(') { if (negate) { throw new ExpressionParseException("Open bracket found after negate.", i); } s2.Push("("); } else { if (!signed && (c == '+' || c == '-')) { signed = true; if (c == '-') { negate = true; } } else { // by default negate is false if (c >= '0' && c <= '9' || c == '.') { int j = i + 1; while (j < s.Length) { c = s[j]; if (c >= '0' && c <= '9' || c == '.') { j++; } else { // code to account for "computerized scientific notation" if (c == 'e' || c == 'E') { j++; if (j < s.Length) { c = s[j]; if (c != '+' && c != '-' && (c < '0' || c > '9')) { throw new ExpressionParseException( "Expected digit, plus sign or minus sign but found: " + c.ToString(), j + indexErrorOffset); } j++; } while (j < s.Length) { c = s[j]; if (c < '0' || c > '9') { break; } j++; } break; } else { break; } } } double d = 0; string _d = Sharpen.Runtime.Substring(s, i, j); try { d = double.Parse(_d); } catch { throw new ExpressionParseException("Improperly formatted value: " + _d, i + indexErrorOffset); } if (negate) { d = -d; } s1.Push(new ValNode(d)); i = j - 1; negate = false; term = false; signed = false; } else { if (c != ',' && c != ')' && c != '^' && c != '*' && c != '/' && c != '+' && c != '-') { int j = i + 1; while (j < s.Length) { c = s[j]; if (c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '(' && c != ')' && c != '^' && c != '*' && c != '/' && c != '+' && c != '-') { j++; } else { break; } } if (j < s.Length) { int k = j; while (c == ' ' || c == '\t' || c == '\n') { k++; if (k == s.Length) { break; } c = s[k]; } if (c == '(') { FuncNode fn = new FuncNode(Sharpen.Runtime.Substring(s, i, j), negate); int b = 1; int kOld = k + 1; while (b != 0) { k++; if (k >= s.Length) { throw new ExpressionParseException( "Missing function close bracket.", i + indexErrorOffset); } c = s[k]; if (c == ')') { b--; } else { if (c == '(') { b++; } else { if (c == ',' && b == 1) { Expression o = Build( Sharpen.Runtime.Substring(s, kOld, k), kOld); if (o == null) { throw new ExpressionParseException( "Incomplete function.", kOld + indexErrorOffset); } fn.Add(o); kOld = k + 1; } } } } Expression o_1 = Build(Sharpen.Runtime.Substring(s, kOld, k), kOld); if (o_1 == null) { if (fn.NumChildren() > 0) { throw new ExpressionParseException("Incomplete function.", kOld + indexErrorOffset); } } else { fn.Add(o_1); } s1.Push(fn); i = k; } else { s1.Push(new VarNode(Sharpen.Runtime.Substring(s, i, j), negate)); i = k - 1; } } else { s1.Push(new VarNode(Sharpen.Runtime.Substring(s, i, j), negate)); i = j - 1; } negate = false; term = false; signed = false; } else { throw new ExpressionParseException("Unexpected character: " + c.ToString(), i + indexErrorOffset); } } } } } else { if (c == ')') { Stack s3 = Stack.Allocate(); Stack s4 = Stack.Allocate(); try { while (true) { if (s2.IsEmpty()) { throw new ExpressionParseException("Missing open bracket.", i + indexErrorOffset); } object o = s2.Pop(); if (o.Equals("(")) { break; } s3.AddToTail(s1.Pop()); s4.AddToTail(o); } s3.AddToTail(s1.Pop()); s1.Push(Build(s3, s4)); } finally { s3.ReleaseReference(); s4.ReleaseReference(); } } else { if (c == '^' || c == '*' || c == '/' || c == '+' || c == '-') { term = true; s2.Push(c.ToString()); } else { throw new ExpressionParseException( "Expected operator or close bracket but found: " + c.ToString(), i + indexErrorOffset); } } } } if (s1.Size() != s2.Size() + 1) { throw new ExpressionParseException("Incomplete expression.", indexErrorOffset + s.Length); } return(Build(s1, s2)); } finally { s1.ReleaseReference(); s2.ReleaseReference(); } }