Created
March 3, 2017 03:17
-
-
Save Pyeroh/7c170cbd52eb6a43201a444d2b577b04 to your computer and use it in GitHub Desktop.
Brainfuck interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BrainLuck { | |
private static Map<String, Consumer<Data>> operations = new HashMap<>(); | |
static { | |
operations.put(">", Data::incrementPointer); | |
operations.put("<", Data::decrementPointer); | |
operations.put("+", Data::increment); | |
operations.put("-", Data::decrement); | |
operations.put(".", Data::output); | |
} | |
private static class Data { | |
private final List<Byte> data = new ArrayList<>(); | |
private int currentPointer = 0; | |
private final List<Byte> output = new ArrayList<>(); | |
public Data() { | |
data.add((byte) 0); | |
} | |
public void incrementPointer() { | |
currentPointer++; | |
if (data.size() <= currentPointer) { | |
data.add((byte) 0); | |
} | |
} | |
public void decrementPointer() { | |
currentPointer--; | |
} | |
public void increment() { | |
int valueAtPointer = data.get(currentPointer); | |
if (valueAtPointer == 255) { | |
valueAtPointer = -1; | |
} | |
data.set(currentPointer, (byte) ++valueAtPointer); | |
} | |
public void decrement() { | |
int valueAtPointer = data.get(currentPointer); | |
if (valueAtPointer == 0) { | |
valueAtPointer = 256; | |
} | |
data.set(currentPointer, (byte) --valueAtPointer); | |
} | |
public byte get() { | |
return data.get(currentPointer); | |
} | |
public void output() { | |
output.add(get()); | |
} | |
public void input(byte b) { | |
data.set(currentPointer, b); | |
} | |
} | |
private List functions = new ArrayList<>(); | |
private int currentInstruction; | |
private List<int[]> bracketPairs = new ArrayList<>(); | |
public BrainLuck(String code) { | |
int i = 0; | |
for (String instruction : code.split("")) { | |
int currentI = i; | |
if (operations.containsKey(instruction)) { | |
functions.add(operations.get(instruction)); | |
} else { | |
switch (instruction) { | |
case ",": | |
functions.add((BiConsumer<Data, Byte>) Data::input); | |
break; | |
case "[": | |
bracketPairs.add(new int[] { i, findMatchingBracket(code, i) }); | |
Consumer<Data> o = d -> currentInstruction = (d.get() == 0 ? bracketPairs.stream().filter(arr -> arr[0] == currentI).findFirst().get()[1] : currentInstruction); | |
functions.add(o); | |
break; | |
case "]": | |
o = d -> currentInstruction = (d.get() != 0 ? bracketPairs.stream().filter(arr -> arr[1] == currentI).findFirst().get()[0] : currentInstruction); | |
functions.add(o); | |
break; | |
} | |
} | |
i++; | |
} | |
} | |
private int findMatchingBracket(String code, int openingBracket) { | |
int openedBrackets = 0; | |
int openedBracketsBeforeToFind = -1; | |
int index = 0; | |
for (String s : code.split("")) { | |
if (index == openingBracket) { | |
openedBracketsBeforeToFind = openedBrackets; | |
} | |
if (s.equals("[")) { | |
openedBrackets++; | |
} | |
if (s.equals("]")) { | |
openedBrackets--; | |
} | |
if (openedBrackets == openedBracketsBeforeToFind) { | |
return index; | |
} | |
index++; | |
} | |
return -1; | |
} | |
public String process(String input) { | |
currentInstruction = 0; | |
Data data = new Data(); | |
String processedInput = input; | |
while (currentInstruction < functions.size()) { | |
Object instruction = functions.get(currentInstruction); | |
if (instruction instanceof Consumer) { | |
((Consumer<Data>) instruction).accept(data); | |
} | |
if (instruction instanceof BiConsumer) { | |
char first = processedInput.charAt(0); | |
processedInput = processedInput.substring(1, processedInput.length()); | |
((BiConsumer<Data, Byte>) instruction).accept(data, (byte) first); | |
} | |
currentInstruction++; | |
} | |
return data.output.stream().map(b -> new String(new byte[] { b })).collect(Collectors.joining()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment