Paolo Mazzon Paolo Mazzon - 4 months ago 10
Brainfuck Question

Java substr not working as expected

So I'm making a brainfuck interpreter in Java and I don't have any problems with it except for the [ and ]. (Inevitably) The problem is with parsing the string. So what I do to deal with the loop is locate the code in between the two brackets and recall the function (Recursion) to redo the code inside the brackets. This sounds nice on paper but

substring
is not cooperating with me. Here is where I deal with the [

void openBracket(short i, String brainfuck)
{
/*LOGIC EXPLAINED: First set balance = 1, then loop through all characters after this,
if another opening bracket is found increment balance, if a close bracket is found,
decrement balance. Also, when another close bracket is found test if balance is 1, if
so then this is the proper bracket*/
String codeSection = brainfuck.substring(i);
short balance = 1;
String codeToRedo;
short endPoint = -1;

for (short j = i; j < codeSection.length(); j++)
{
//Check the character
if (codeSection.charAt(j) == '[')
{
balance++;
} else if (codeSection.charAt(j) == ']')
{
balance--;

}
//Check if it's the right bracket
if (balance == 1) {
endPoint = j;
}
}

//Only do such a thing if the cell is not equal to 0
if (cell[pointer] > 0 && endPoint != -1)
{
codeToRedo = brainfuck.substring(i, endPoint);
output += brainfuckExecute(codeToRedo);
}
else if (endPoint == -1) //If endpoint is equal to -1, that means that there was no closing bracket
{
errorList += "ERROR: No closing bracket (" + i + ")";
}
}


I apologize about the indenting, it didn't copy very well form Netbeans. But anyways, as you can see at the top of the code, I make a variable called 'codeSection,' and it should contain the proper text. Here is what I give for the argument 'brainfuck':
+++[>+++++ +++++<-]>+++.
Here is what I get when I print the variable:

[>+++++ +++++<-]>+++.
[>+++++ +++


Yes, I print the variable with System.out.println and I get two different things printed. The first time, it is the correct string. The second time I get what is processed, and that has no closing bracket. I have an error checking system rigged up in the code for brainfuck, so I can check. And I get the error I should. (ERROR: No closing bracket (0))
I am really dazed and confused with this one, so any help provided is greatly appreciated.

P.S. Extra code, like where it's called and such:
Where it's called:

String brainfuckExecute(String brainfuck)
{
//Reset the output
output = "";

//Loop through all instructions
for(short i = 0; i < brainfuck.length(); i++)
{
//Execute a switch to do the instructions
switch(brainfuck.charAt(i))
{
//Increment current cell
case '+':
incrementCell();
break;
//Decrement current cell
case '-':
decrementCell(i);
break;
//Move pointer up
case '>':
incrementPointer(i);
break;
//Move pointer down
case '<':
decrementPointer(i);
break;
//Get user input and store it in the current cell
case ',':
getInput();
break;
//Add the cell to the output string
case '.':
addOutput();
break;
//Start the while loop -- Recurssive
case '[':
openBracket(i, brainfuck);
break;
}
}

//Return said output
return output;
}


(It's within a class that has all those variables)
Where main is:

Brainfuck codeTranslator = new Brainfuck();
System.out.println(codeTranslator.brainfuckExecute("+++[>+++++ +++++<-]>+++."));
System.out.println(codeTranslator.getErrors());


Again, thanks

Answer

When you call openBracket() for the first time, you have i == 3 and brainfuck == "+++[>+++++ +++++<-]>+++.". So, in the first substring() call you get:

String codeSection = brainfuck.substring(3);

Which results in:

String codeSection = "+++[>+++++ +++++<-]>+++.".substring(3);
String codeSection = "[>+++++ +++++<-]>+++."

Then you loop through codeSection to see if it is balanced. The problem is that you already cut out the part before the [, but you begin your loop at j = 3. I will mark the current index positions with ( ), so it is easier to follow:

You start the loop at j = 3:

[>+(+)+++ +++++<-]>+++.

And go until j = 14, which is the index of - just before ]:

[>+++++ +++++<(-)]>+++.

Since you didn't find the first [, the value of balance was 1 all this time. So, in the end, you did endPoint = 14.

if (balance == 1) {
    endPoint = j;
}

In the next iteration you find the ], and balance gets decremented to 0, so the loop keeps going but endPoint is not updated again.

After this, you do:

codeToRedo = brainfuck.substring(i, endPoint);

Which results in:

codeToRedo = brainfuck.substring(3, 14);
codeToRedo = "+++[>+++++ +++++<-]>+++.".substring(3, 14);
codeToRedo = "[>+++++ +++";

I guess your loop should really be:

for (short j = 0; j < codeSection.length(); j++) { ... }

And finally, to get only the part of brainfuck that's between the brackets you should notice that, while balance is 1, you keep updating the value of endPoint. I think you want to stop when you find the balancing bracket, so you can add a break inside your if:

for (short j = 0; j < codeSection.length(); j++) {
    //Check the character
    if (codeSection.charAt(j) == '[') {
        balance++;
    } else if (codeSection.charAt(j) == ']') {
        balance--;
    }
    //Check if it's the right bracket
    if (balance == 1) {
        endPoint = j;
        break; // Stop when you find the ] position
    }
}

Then do:

codeToRedo = brainfuck.substring(i + 1, i + endPoint);

Or:

codeToRedo = codeSection.substring(1, endPoint);

Also, you concatenate the results of brainfuckExecute() when you do output += brainfuckExecute(codeToRedo). That's probably why it looks like it is printing twice.