ExpressionTree.java
Go to the documentation of this file.00001 package com.graphbuilder.math;
00002
00003 import com.graphbuilder.struc.Stack;
00004
00059 public class ExpressionTree {
00060
00061 private ExpressionTree() {}
00062
00068 public static Expression parse(String s) {
00069 if (s == null)
00070 throw new ExpressionParseException("Expression string cannot be null.", -1);
00071
00072 return build(s, 0);
00073 }
00074
00075 private static Expression build(String s, int indexErrorOffset) {
00076
00077
00078 if (s.trim().length() == 0)
00079 return null;
00080
00081 Stack s1 = new Stack();
00082 Stack s2 = new Stack();
00083
00084 boolean term = true;
00085 boolean signed = false;
00086 boolean negate = false;
00087
00088 for (int i = 0; i < s.length(); i++) {
00089 char c = s.charAt(i);
00090
00091 if (c == ' ' || c == '\t' || c == '\n')
00092 continue;
00093
00094 if (term) {
00095 if (c == '(') {
00096 if (negate)
00097 throw new ExpressionParseException("Open bracket found after negate.", i);
00098
00099 s2.push("(");
00100 }
00101 else if (!signed && (c == '+' || c == '-')) {
00102 signed = true;
00103 if (c == '-') negate = true;
00104 }
00105 else if (c >= '0' && c <= '9' || c == '.') {
00106
00107 int j = i + 1;
00108 while (j < s.length()) {
00109 c = s.charAt(j);
00110 if (c >= '0' && c <= '9' || c == '.') j++;
00111
00112
00113 else if (c == 'e' || c == 'E') {
00114 j++;
00115
00116 if (j < s.length()) {
00117 c = s.charAt(j);
00118
00119 if (c != '+' && c != '-' && (c < '0' || c > '9'))
00120 throw new ExpressionParseException("Expected digit, plus sign or minus sign but found: " + String.valueOf(c), j + indexErrorOffset);
00121
00122 j++;
00123 }
00124
00125 while (j < s.length()) {
00126 c = s.charAt(j);
00127 if (c < '0' || c > '9')
00128 break;
00129 j++;
00130 }
00131 break;
00132 }
00133 else break;
00134 }
00135
00136 double d = 0;
00137 String _d = s.substring(i, j);
00138
00139 try {
00140 d = Double.parseDouble(_d);
00141 } catch (Throwable t) {
00142 throw new ExpressionParseException("Improperly formatted value: " + _d, i + indexErrorOffset);
00143 }
00144
00145 if (negate) d = -d;
00146 s1.push(new ValNode(d));
00147 i = j - 1;
00148
00149 negate = false;
00150 term = false;
00151 signed = false;
00152 }
00153 else if (c != ',' && c != ')' && c != '^' && c != '*' && c != '/' && c != '+' && c != '-' && c != '=') {
00154 int j = i + 1;
00155 while (j < s.length()) {
00156 c = s.charAt(j);
00157 if (c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '(' && c != ')' && c != '^' && c != '*' && c != '/' && c != '+' && c != '-' && c != '=')
00158 j++;
00159 else break;
00160 }
00161
00162 if (j < s.length()) {
00163 int k = j;
00164 while (c == ' ' || c == '\t' || c == '\n') {
00165 k++;
00166 if (k == s.length()) break;
00167 c = s.charAt(k);
00168 }
00169
00170 if (c == '(') {
00171 FuncNode fn = new FuncNode(s.substring(i, j), negate);
00172 int b = 1;
00173 int kOld = k + 1;
00174 while (b != 0) {
00175 k++;
00176
00177 if (k >= s.length()) {
00178 throw new ExpressionParseException("Missing function close bracket.", i + indexErrorOffset);
00179 }
00180
00181 c = s.charAt(k);
00182
00183 if (c == ')') {
00184 b--;
00185 }
00186 else if (c == '(') {
00187 b++;
00188 }
00189 else if (c == ',' && b == 1) {
00190 Expression o = build(s.substring(kOld, k), kOld);
00191 if (o == null) {
00192 throw new ExpressionParseException("Incomplete function.", kOld + indexErrorOffset);
00193 }
00194 fn.add(o);
00195 kOld = k + 1;
00196 }
00197 }
00198 Expression o = build(s.substring(kOld, k), kOld);
00199 if (o == null) {
00200 if (fn.numChildren() > 0) {
00201 throw new ExpressionParseException("Incomplete function.", kOld + indexErrorOffset);
00202 }
00203 }
00204 else {
00205 fn.add(o);
00206 }
00207 s1.push(fn);
00208 i = k;
00209 }
00210 else {
00211 s1.push(new VarNode(s.substring(i, j), negate));
00212 i = k - 1;
00213 }
00214 }
00215 else {
00216 s1.push(new VarNode(s.substring(i, j), negate));
00217 i = j - 1;
00218 }
00219
00220 negate = false;
00221 term = false;
00222 signed = false;
00223 }
00224 else {
00225 throw new ExpressionParseException("Unexpected character: " + String.valueOf(c), i + indexErrorOffset);
00226 }
00227 }
00228 else {
00229 if (c == ')') {
00230 Stack s3 = new Stack();
00231 Stack s4 = new Stack();
00232 while (true) {
00233 if (s2.isEmpty()) {
00234 throw new ExpressionParseException("Missing open bracket.", i + indexErrorOffset);
00235 }
00236 Object o = s2.pop();
00237 if (o.equals("(")) break;
00238 s3.addToTail(s1.pop());
00239 s4.addToTail(o);
00240 }
00241 s3.addToTail(s1.pop());
00242
00243 s1.push(build(s3, s4));
00244 }
00245 else if (c == '^' || c == '*' || c == '/' || c == '+' || c == '-') {
00246 term = true;
00247 s2.push(String.valueOf(c));
00248 }
00249
00250 else if (c == '=') {
00251 final char c_next = s.charAt(i+1);
00252
00253 if (c_next == '=') {
00254 i++;
00255 }
00256 term = true;
00257 s2.push(String.valueOf(c));
00258 }
00259 else {
00260 throw new ExpressionParseException("Expected operator or close bracket but found: " + String.valueOf(c), i + indexErrorOffset);
00261 }
00262 }
00263 }
00264
00265 if (s1.size() != s2.size() + 1) {
00266 throw new ExpressionParseException("Incomplete expression.", indexErrorOffset + s.length());
00267 }
00268
00269 return build(s1, s2);
00270 }
00271
00272 private static Expression build(Stack s1, Stack s2) {
00273 Stack s3 = new Stack();
00274 Stack s4 = new Stack();
00275
00276 while (!s2.isEmpty()) {
00277 Object o = s2.removeTail();
00278 Object o1 = s1.removeTail();
00279 Object o2 = s1.removeTail();
00280
00281 if (o.equals("^")) {
00282 s1.addToTail(new PowNode((Expression) o1, (Expression) o2));
00283 }
00284 else {
00285 s1.addToTail(o2);
00286 s4.push(o);
00287 s3.push(o1);
00288 }
00289 }
00290
00291 s3.push(s1.pop());
00292
00293 while (!s4.isEmpty()) {
00294 Object o = s4.removeTail();
00295 Object o1 = s3.removeTail();
00296 Object o2 = s3.removeTail();
00297
00298 if (o.equals("*")) {
00299 s3.addToTail(new MultNode((Expression) o1, (Expression) o2));
00300 }
00301 else if (o.equals("/")) {
00302 s3.addToTail(new DivNode((Expression) o1, (Expression) o2));
00303 }
00304 else {
00305 s3.addToTail(o2);
00306 s2.push(o);
00307 s1.push(o1);
00308 }
00309 }
00310
00311 s1.push(s3.pop());
00312
00313 while (!s2.isEmpty()) {
00314 Object o = s2.removeTail();
00315 Object o1 = s1.removeTail();
00316 Object o2 = s1.removeTail();
00317
00318 if (o.equals("+")) {
00319 s1.addToTail(new AddNode((Expression) o1, (Expression) o2));
00320 }
00321 else if (o.equals("-")) {
00322 s1.addToTail(new SubNode((Expression) o1, (Expression) o2));
00323 }
00324 else if (o.equals("=")) {
00325 s1.addToTail(new EqualNode((Expression) o1, (Expression) o2));
00326 }
00327 else {
00328
00329 throw new ExpressionParseException("Unknown operator: " + o, -1);
00330 }
00331 }
00332
00333 return (Expression) s1.pop();
00334 }
00335 }