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:
       +
      /   \
    +    4
  /   \
1     *
      /  \
     2   3
However, I can't quite figure out how to get the "+4" bit of the tree into the correct position...

It's coming out:
    +    +
  /   \ /   \
1     *    4
      /  \
     2   3
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:
    +
   /  \
  *   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?