Skip to content

Instantly share code, notes, and snippets.

@steveash
Created December 12, 2014 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steveash/10de12a2c085215b66d8 to your computer and use it in GitHub Desktop.
Save steveash/10de12a2c085215b66d8 to your computer and use it in GitHub Desktop.
Simple Brainfuck interpreter for a friend
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Brainfuck {
public static void main(String[] args) throws IOException {
int maxTapeSize = 10000;
Scanner s = new Scanner(System.in);
char[] program = s.nextLine().toCharArray();
short[] tape = new short[maxTapeSize];
Map<Integer, Integer> jumpTable = new HashMap<>();
int p = 0; // pointer to the current program instruction
int t = 0; // pointer to the current tape location
int allowedCommands = 10000;
int doneCommands = 0;
while (p < program.length && doneCommands < allowedCommands) {
char cmd = program[p];
if (cmd == '>') {
if (t == tape.length - 1) {
t = 0; // go to first location in the buffer (i.e wrap around)
} else {
t += 1;
}
p += 1; // program goes to next instruction
} else if (cmd == '<') {
if (t == 0) {
t = tape.length - 1; // go to the last location in the buffer (i.e. wrap around)
} else {
t -= 1; // tape moves one location to the left
}
p += 1; // program moves to the next character
} else if (cmd == '+') {
short cell = tape[t];
if (cell == 255) {
tape[t] = 0;
} else {
tape[t] += 1;
}
p += 1; // program moves to the next character
} else if (cmd == '-') {
short cell = tape[t];
if (cell == 0) {
tape[t] = 255;
} else {
tape[t] -= 1;
}
p += 1; // program moves to the next character
} else if (cmd == '.') {
short cell = tape[t];
System.out.println(cell);
p += 1; // program moves to the next character
} else if (cmd == ',') {
short valueToWrite = 0; // if there's no more then write zero
if (s.hasNextShort()) {
valueToWrite = s.nextShort();
}
tape[t] = valueToWrite;
p += 1;
} else if (cmd == '[') {
short cell = tape[t];
if (cell != 0) {
p += 1; // if its != zero then just move to the next program position
} else {
// we need to _find_ the next program position
Integer jump = jumpTable.get(p);
if (jump == null) {
// we've never hit this bracket and needed to jump before so find the pair
jump = findClosingBracket(program, p + 1);
// save it so next time we dont have to look it up
jumpTable.put(p, jump);
jumpTable.put(jump, p);
}
p = 1 + jump;
}
} else if (cmd == ']') {
short cell = tape[t];
if (cell == 0) {
p += 1; // if its zero then move to the next, otherwise go back to the opening bracket
} else {
Integer jump = jumpTable.get(p);
if (jump == null) {
// we've never hit this bracket and needed to jump before so find the pair
jump = findOpeningBracket(program, p - 1);
// save it so next time we dont have to look it up
jumpTable.put(p, jump);
jumpTable.put(jump, p);
}
p = 1 + jump;
}
}
// we already dealt with p above (because sometimes it increments by one sometimes it jumps around)
doneCommands += 1;
}
}
// finds the next closing bracket starting at p; returns -1 if it can't find anything because the brainfuck
// program was not specified correctly (i.e. a starting bracket with no closing)
private static int findClosingBracket(char[] program, int i) {
int nestedCount = 0;
while (true) {
if (i >= program.length) {
// we ran out of program and couldnt find a closing bracket so the program mustve been entered incorrectly
throw new IllegalStateException("Bad program input cant find closing bracket from " + i);
}
if (program[i] == '[') {
// uh oh we were looking for a closing bracket but we found a nested opening bracket that means we need
// to find this nested brackets closing bracket before we can get ours; let's keep track of how many
// nested brackets we're looking for
nestedCount += 1;
}
if (program[i] == ']') {
// we found _a_ closing bracket but we're not sure if its _ours_ or one of the nested ones we're looking for
if (nestedCount == 0) {
// we found _our_ bracket!
return i;
} else {
// this is someone else's so just _decrement_ the nestedCount, when we finally hit the closing bracket
// with nestedCount = 0 then we know we've found ours
nestedCount -= 1;
}
}
// didn't find it this time, try the next spot
i += 1;
}
}
private static int findOpeningBracket(char[] program, int i) {
int nestedCount = 0;
while (true) {
if (i < 0) {
throw new IllegalStateException("Bad program input cant find opening bracket from " + i);
}
if (program[i] == ']') {
nestedCount += 1;
}
if (program[i] == '[') {
if (nestedCount == 0) {
return i;
} else {
nestedCount -= 1;
}
}
i -= 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment