com.github.bloodshura.sparkium.brainfxck.action.impl.DefaultAction Maven / Gradle / Ivy
Show all versions of sparkium-brainfxck Show documentation
package com.github.bloodshura.sparkium.brainfxck.action.impl;
import com.github.bloodshura.ignitium.charset.sequence.CharSet;
import com.github.bloodshura.ignitium.collection.map.XMap;
import com.github.bloodshura.ignitium.collection.store.impl.XStack;
import com.github.bloodshura.sparkium.brainfxck.BrainfuckContext;
import com.github.bloodshura.sparkium.brainfxck.BrainfuckInterpreter;
import com.github.bloodshura.sparkium.brainfxck.BrainfuckMemory;
import com.github.bloodshura.sparkium.brainfxck.action.Action;
import javax.annotation.Nonnull;
import java.io.IOException;
/**
* The default Brainfuck action.
* It is responsible for handling the following Brainfuck input characters:
*
* - >, which increments the memory pointer
* - <, which decrements the memory pointer
* - +, which increments the value on the current memory pointer
* - -, which decrements the value on the current memory pointer
* - [, which starts a loop
* - ], which ends a loop if the value on the current memory pointer is zero, or returns to its beginning if otherwise
* - ,, which reads a character from {@link BrainfuckInterpreter#getScanner()} and stores it on the current memory pointer
* - ., which prints the value on the current memory pointer using {@link BrainfuckInterpreter#getLogger()}
*
*/
public class DefaultAction implements Action {
/**
* A {@link CharSet} instance containing all the characters which are manipulated by this action.
* See the documentation of this class for a detailed explanation of each character.
*/
public static final CharSet CHAR_SET = new CharSet('>', '<', '+', '-', '[', ']', ',', '.');
/**
* The flag name used for loop skipping.
*
* @see BrainfuckContext#getFlags()
*/
public static final String FLAG_SKIP = "skipping";
@Override
public boolean act(char ch, @Nonnull BrainfuckContext context) throws IOException {
BrainfuckInterpreter interpreter = context.getInterpreter();
XStack loopStack = context.getLoopStack();
BrainfuckMemory memory = interpreter.getMemory();
XMap flags = context.getFlags();
int skipLevel = (int) flags.get(FLAG_SKIP, 0);
if (skipLevel > 0 && ch != ']') {
return false;
}
if (ch == '>') {
memory.increasePointer();
} else if (ch == '<') {
memory.decreasePointer();
} else if (ch == '+') {
memory.increaseValue();
} else if (ch == '-') {
memory.decreaseValue();
} else if (ch == '[') {
if (memory.getValue() == 0) {
flags.set(FLAG_SKIP, skipLevel + 1);
} else {
loopStack.push(context.getCurrentIndex());
}
} else if (ch == ']') {
if (skipLevel > 0) {
flags.set(FLAG_SKIP, skipLevel - 1);
} else if (!loopStack.isEmpty()) {
int loopStart = loopStack.pop();
if (memory.getValue() != 0) {
loopStack.push(loopStart);
context.setCurrentIndex(loopStart + 1);
}
}
} else if (ch == ',') {
memory.setValue(interpreter.readChar());
} else if (ch == '.') {
interpreter.getLogger().print((char) memory.getValue());
} else {
return false;
}
return true;
}
}