Hi, I've been trying to create a fairly simple calculator that can parse a string and build up a simple tree that's easily evaluated. It has to support a custom order of operations and parenthesis support.
Sorry for the messy programming...
code:
private Expression parse (Expression handle, int state) throws SyntaxError { Expression hold = null; while (charPoint < text.length()) { if (readType() == type.RPARENTHESIS) { if (lastRead == type.LPARENTHESIS || lastRead == type.OPERATOR) { // error! empty parenthesis or BOP without second parameter throw new SyntaxError(); } else if (state == 4) { // finalize handle handle.setExpr(hold, 2); } charPoint++; parenCounter--; if (handle.getOper() == null) { return handle.getExpr(1); } return handle; } switch (state) { case 1: // parenthesis handling if (readType() == type.LPARENTHESIS) { lastRead = type.LPARENTHESIS; charPoint++; // set the first expression to what ever is inside the parenthesis parenCounter++; state = 1; handle.setExpr(parse(new Expression(), 1), 1); state = 2; break; } // look for a number if (readType() != type.NUMBER) { // not a number throw new SyntaxError(); } // read number in lastRead = type.NUMBER; handle.setExpr(new Number(Double.parseDouble(numMatcher.group())), 1); charPoint = numMatcher.end(); state = 2; break; case 2: // look for a binary operator if (readType() != type.OPERATOR) { throw new SyntaxError(); } lastRead = type.OPERATOR; handle.setOper(Operator.createBOP(operMatcher.group())); charPoint = operMatcher.end(); state = 3; case 3: // parenthesis handling if (readType() == type.LPARENTHESIS) { lastRead = type.LPARENTHESIS; parenCounter++; charPoint++; // set the second expression to what ever is inside the parenthesis handle.setExpr(parse(new Expression(), 1), 2); Expression temp = new Expression(); temp.setExpr(handle, 1); handle = temp; state = 2; break; } // look for a number if (readType() != type.NUMBER) { throw new SyntaxError(); } lastRead = type.NUMBER; // hold that number hold = new Number(Double.parseDouble(numMatcher.group())); charPoint = numMatcher.end(); state = 4; // break cause we want close parenthesis parsing break; case 4: // perform one look ahead if (readType() != type.OPERATOR) { // error, didn't find an operator throw new SyntaxError(); } lastRead = type.OPERATOR; Operator look = Operator.createBOP(operMatcher.group()); charPoint = operMatcher.end(); if (handle.getOper().hasHigherPrecedence(look)) { // previous operator has higher or equal precedence, finalize and move handle Expression temp = new Expression(); handle.setExpr(hold, 2); temp.setExpr(handle, 1); temp.setOper(look); handle = temp; break; } else { // previous operator has lower precedence Expression temp = new Expression(); temp.setExpr(hold, 1); temp.setOper(look); handle.setExpr(parse(temp, 3), 2); temp = new Expression(); temp.setExpr(handle, 1); state = 3; break; } } } if (state == 4) { handle.setExpr(hold, 2); } return handle; }
Currently, parse is building the expression tree wrong...
ex:
1+2*3+4
should be built:
However, I can't quite figure out how to get the "+4" bit of the tree into the correct position...+ / \ + 4 / \ 1 * / \ 2 3
It's coming out:
which is a problem, cause it's no longer a tree... And because of my class refering only to the top node, java's garbage collector turns it into this:+ + / \ / \ 1 * 4 / \ 2 3
+ / \ * 4 / \ 2 3
hmm.. well, that's what it was doing for a while. I've been fiddling with it, and now it doesn't work at all
If I happen to undo the changes I made, i'll update the code.
could someone tell me if there's a better way to accomplish this?