Skip to content

Instantly share code, notes, and snippets.

@BenjaminUrquhart
Last active February 15, 2019 02:31
Show Gist options
  • Save BenjaminUrquhart/0aee5c1ea878d3b071e4170206a5b785 to your computer and use it in GitHub Desktop.
Save BenjaminUrquhart/0aee5c1ea878d3b071e4170206a5b785 to your computer and use it in GitHub Desktop.
BrainF interpreter in Java
package net.benjaminurquhart.bfj;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.script.ScriptException;
public class BFJ {
public static String stripComments(String code){
return code.chars().mapToObj((c) -> ((char)c)+"").filter((c)->",.+-<>[]".contains(c)).reduce("",(x,y)->x+y);
}
public static void execute(String code) throws ScriptException{
execute(code, 30000);
}
public static void execute(String code, int cellAmount) throws ScriptException{
int[] buff = new int[cellAmount < 30000 ? 30000 : cellAmount];
ArrayList<BracketPair> bracketsQueue = new ArrayList<>(), brackets = new ArrayList<>();
int instruction = 0, data = 0, codeLen = code.length();
for(int i = 0; i < codeLen; i++){
try{
if(code.charAt(i) == '[') bracketsQueue.add(0, new BracketPair(i, 0));
if(code.charAt(i) == ']') brackets.add(bracketsQueue.remove(0).setB(i));
}
catch(IndexOutOfBoundsException e){
throw new ScriptException("Unmatched jump instruction at character " + i);
}
}
if(!bracketsQueue.isEmpty()){
throw new ScriptException("Unmatched jump instruction at character " + bracketsQueue.get(0).getF());
}
HashMap<Integer, Integer> forward = new HashMap<>(), backward = new HashMap<>();
for(BracketPair pair : brackets){
if(pair.getB() == pair.getF()){
throw new ScriptException("Invalid jump instruction at character " + pair.getB());
}
backward.put(pair.getF(), pair.getB());
forward.put(pair.getB(), pair.getF());
}
try{
while(instruction < codeLen){
switch(code.charAt(instruction)){
case ',': buff[data] = System.in.read(); break;
case '.': System.out.print((char)buff[data]); break;
case '+': buff[data]++; break;
case '-': buff[data]--; break;
case '>' : data++; break;
case '<' : data--; break;
case '[': instruction = (buff[data] == 0 ? backward.get(instruction) : instruction); break;
case ']': instruction = (buff[data] != 0 ? forward.get(instruction) : instruction); break;
}
if(data >= buff.length || data < 0){
throw new ScriptException(String.format("Out-of-bounds buffer access at character %d. Index: %d, Size: %d", instruction, data, buff.length));
}
instruction++;
}
}
catch(IOException e){
throw new ScriptException("Failed to read from standard input: " + e.getMessage());
}
}
}
class BracketPair{
private int f,b;
protected BracketPair(int f, int b){
this.f = f;
this.b = b;
}
protected BracketPair setF(int f){
this.f = f;
return this;
}
protected BracketPair setB(int b){
this.b = b;
return this;
}
protected int getF(){
return f;
}
protected int getB(){
return b;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment