Java - разрывы оценки выражений при наличии множества скобок - PullRequest
0 голосов
/ 02 марта 2019

Это для оценки строковых выражений.Поэтому я использую этот сайт для создания сложного выражения со многими круглыми скобками, а когда их слишком много, он разрывается с исключением IndexOutOfBoundsException.https://dshepsis.github.io/ExpressionGenerator/ Я использую стеки и рекурсию для работы с круглыми скобками.Я указал строку, которую она прерывает в качестве комментария. Вот мой код:

private static float evaluate() { //No arguments to make recursion easier

Stack<Character> opStack = new Stack<Character>();
Stack<Character> currentOp = new Stack<Character>();

ArrayList<Float> numbers = new ArrayList<Float>();

//keep track of parenthesis
int indexOpen = 0, indexClose = 0, numOpen = 0, numClose = 0;   
String newExpr;
String temp;
float ans = 0;
int temp2 = 0;

char operation;
int first, second;  
//remove spaces
exp = exp.replaceAll(" ", "");
exp = exp.replaceAll("\t", "");
exp += " ";

//go thru expression to count array brackets
for (int i = 0; i < exp.length(); i++) {

    if ( exp.charAt(i) == '[') {
        indexOpen = i;
        i++;


        for (; i < exp.length(); i++){
            if ( exp.charAt(i) == ']'){
                numClose++;
            }

            if (exp.charAt(i) == '['){
                numOpen++;
            }

            if ( exp.charAt(i) == ']' && numOpen < numClose){
                indexClose = i;
                numOpen = 0;
                numClose = 0;
                break;
            }
        }

        newExpr = exp; //if theres parenthesis create subexpression
        exp = exp.substring(indexOpen+1, indexClose);
        temp = newExpr.substring(indexOpen, indexClose+1);


        temp2 = temp.length();
        temp = "" + (int)evaluate(); //recurse with the subexpression (arrays) hence cast to int


        exp = newExpr.substring(0, indexOpen+1) + temp
            + newExpr.substring(indexClose, newExpr.length());


        i-=temp2 - temp.length();
    }
}

//do it again for regular parenthesis
for (int i = 0; i < exp.length(); i++) {

    if ( exp.charAt(i) == '(') {
        indexOpen = i;
        i++;


        for (; i < exp.length(); i++){
            if ( exp.charAt(i) == ')'){
                numClose++;
            }

            if (exp.charAt(i) == '('){
                numOpen++;
            }

            if ( exp.charAt(i) == ')' && numOpen < numClose){
                indexClose = i;
                numOpen = 0;
                numClose = 0;
                break;
            }
        }
        newExpr = exp;
        exp = exp.substring(indexOpen+1, indexClose);
        temp = newExpr.substring(indexOpen, indexClose+1);
        temp2 = temp.length();
        temp = "" + evaluate(); //same as above
        exp = newExpr.substring(0, indexOpen) + temp
            + newExpr.substring(indexClose+1, newExpr.length());
        i -= temp2 - temp.length();
    }
}
opStack = getStackOps(exp);
numbers = getNumbers(exp);
if ( opStack.isEmpty() ){
    return numbers.get(0);
}

int test = opStack.size(); //do the operations
for (int x = 0; x < test; x++){

    operation = opStack.pop();
    currentOp.push(operation);

    if ( hasPriority(operation, opStack ) ) { //check PEMDAS
        first = currentOp.size()-1;
        second = currentOp.size();
        //breaks at this line in the output below
        ans = operate(numbers.get(first) , numbers.get(second), operation);

        numbers.set(first, ans);
        numbers.remove(second);

        currentOp.pop();
    }

    else {

        operation = opStack.pop();
        currentOp.push(operation);

        first = currentOp.size()-1;
        second = currentOp.size();

        //Do the ops
        //breaks here sometimes also
        ans = operate(numbers.get(first) , numbers.get(second), operation);


        numbers.set(first, ans);
        numbers.remove(second);
        currentOp.pop();
        opStack.push( currentOp.pop() );
    }}
return ans;
}

Вот пример вывода: output

Я могу предоставить вспомогательные методы operate and hasPriority, если это необходимобыть.Я сделал много отладки, но я не могу понять, почему он ломается, когда есть много скобок.Спасибо за любую помощь:)

...