ちょっと数式パーサー

なんかバグある気がするけど、整数の数式処理してみた。

import java.util.Stack;

public class Interpreter {
    public static void main(String[] a){
        System.out.println(eval("4-3"));
        System.out.println(eval("4--3"));
        System.out.println(eval("((-12 + 3) * 2)"));
        System.out.println(eval("(-12 + 3) * 2"));
        System.out.println(eval("-12 + 3 * 2"));
        System.out.println(eval("3 * 2 + 4 * -5"));
        System.out.println(eval("3 * 2 + -4 * 5"));
        System.out.println(eval("3 * (2 + -4) * 5"));
        System.out.println(eval("3 * (-2 + 4) * 5"));
    }
    
    public static int eval(String str){
        int value = 0;
        int numphase = 0;//0:数字がくる 1:数字の途中 2:演算子が来る
        boolean minus = false;
        Stack<State> statestack = new Stack<State>();
        State state = new State();
        statestack.push(state);
        for(int i = 0; i < str.length(); ++i){
            char ch = str.charAt(i);
            if(ch == ' '){
                continue;
            }else if(ch >= '0' && ch <= '9'){
                if(numphase == 2){
                    System.out.println("数字がきちゃだめなところに" + ch);
                    return 0;
                }
                value = value * 10 + (ch - '0');
                numphase = 1;
            }else{
                if(numphase == 0){
                    if(ch == '-'){
                        minus = !minus;
                        continue;
                    }else if(ch == '('){
                        state = new State();
                        state.minus = minus;
                        statestack.push(state);
                        minus = false;
                        continue;
                    }else{
                        System.out.println(ch + "が来たのでパースエラーです");
                        return 0;
                    }
                }
                state.numstack.push(value * (minus ? -1 : 1));
                value = 0;
                minus = false;
                
                state.mul();
                
                if("*/+-".indexOf(ch) >= 0){
                    state.opstack.push(ch);
                    numphase = 0;
                }else if(ch == ')'){
                    value = state.calc();
                    
                    statestack.pop();
                    if(statestack.size() == 0){
                        //対応する括弧がない
                        System.out.println("対応するカッコがない");
                        return 0;
                    }
                    state = statestack.peek();
                    numphase = 2;
                }else{
                    //エラー
                    System.out.println(ch + "はわかんない");
                    return 0;
                }
            }
        }

        state.numstack.push(value * (minus ? -1 : 1));
        state.mul();
        
        return state.calc();
    }

    static class State{
        boolean minus;
        Stack<Character> opstack = new Stack<Character>();
        Stack<Integer> numstack = new Stack<Integer>();
        
        void mul(){
            if(!opstack.empty()){
                char op = opstack.peek();
                if(op == '*'){
                    int r = numstack.pop();
                    int l = numstack.pop();
                    numstack.push(l * r);
                    opstack.pop();
                }else if(op == '/'){
                    int r = numstack.pop();
                    int l = numstack.pop();
                    numstack.push(l / r);
                    opstack.pop();
                }
            }
        }
        
        int calc(){
            int value = numstack.get(0);
            for(int j = 1; j < numstack.size(); ++j){
                int r = numstack.get(j);
                char op = opstack.get(j - 1);
                if(op == '+'){
                    value = value + r;
                }else if(op == '-'){
                    value = value - r;
                }else{
                    //なんかおかしい
                    System.out.println("なんかおかしいね");
                }
            }
            if(minus) value = -value;
            return value;
        }
    }
}