package org.faabtech.brainfuck.impl;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
/**
* The {@link OokEngine} is an implementation for the
* <code>brainfuck<code> dialect
* <code>Ook!</code>.
*
* @author Fabian M.
*/
public class OokEngine extends TrollScriptEngine {
/**
* The default length of a token.
*/
protected int defaultTokenLength = 9;
/**
* The {@link Token} enum contains tokens of <code>Ook!</code>.
*
* @author Fabian M.
*/
protected static enum Token {
NEXT("Ook. Ook?"),
PREVIOUS("Ook? Ook."),
PLUS("Ook. Ook."),
MINUS("Ook! Ook!"),
OUTPUT("Ook! Ook."),
INPUT("Ook. Ook!"),
BRACKET_LEFT("Ook! Ook?"),
BRACKET_RIGHT("Ook? Ook!");
String value;
/**
* Constructs a new token.
*
* @param value The value of the token.
*/
Token(String value) {
this.value = value;
}
/**
* Get the value of the token.
*
* @return the value.
*/
public String getValue() {
return value;
}
}
/**
* Constructs a new {@link OokEngine} instance.
*
* @param cells
* The amount of memory cells.
*/
public OokEngine(int cells) {
this(cells, new PrintStream(System.out), System.in);
}
/**
* Constructs a new {@link OokEngine} instance.
*
* @param cells
* The amount of memory cells.
* @param out
* The outputstream of this program.
*/
public OokEngine(int cells, OutputStream out) {
this(cells, out, System.in);
}
/**
* Constructs a new {@link OokEngine} instance.
*
* @param cells
* The amount of memory cells.
* @param out
* The printstream of this program.
* @param in
* The outputstream of this program.
*/
public OokEngine(int cells, OutputStream out, InputStream in) {
super(cells, out, in);
}
/**
* Interprets the given string.
*
* @param str
* The string to interpret.
* @throws Exception
*/
@Override
public void interpret(String str) throws Exception {
// List with tokens.defaultTokenLenght
List<Token> tokens = new ArrayList<Token>();
// It fine that all Ook! tokens are 9 characters long :)
// So we aren't going to loop through all characters..
for (; charPointer < str.length(); ) {
String token = "";
if (charPointer + defaultTokenLength <= str.length())
// The string we found.
token = str.substring(charPointer, charPointer + defaultTokenLength);
else
token = str.substring(charPointer, charPointer
+ (str.length() - charPointer));
boolean b = false;
for (Token tokenCheck : Token.values()) {
if (tokenCheck.getValue().equals(token)) {
tokens.add(tokenCheck);
charPointer += defaultTokenLength;
b = true;
break;
}
}
// If the token was invalid, b is false.
if (!b)
if (charPointer + defaultTokenLength > str.length())
charPointer += (str.length() - charPointer);
else
charPointer++;
}
// Loop through all tokens.
for (int tokenPointer = 0; tokenPointer < tokens.size(); ) {
Token token = tokens.get(tokenPointer);
System.out.println(token);
switch(token) {
case NEXT:
// increment the data pointer (to point to the next cell
// to the
// right).
dataPointer = (dataPointer == data.length - 1 ? 0 : dataPointer + 1);
break;
case PREVIOUS:
// decrement the data pointer (to point to the next cell
// to the
// left).
dataPointer = (dataPointer == 0 ? data.length - 1 : dataPointer - 1);
break;
case PLUS:
// increment (increase by one) the byte at the data
// pointer.
data[dataPointer]++;
break;
case MINUS:
// decrement (decrease by one) the byte at the data
// pointer.
data[dataPointer]--;
break;
case OUTPUT:
// Output the byte at the current index in a character.
//outWriter.write((char) data[dataPointer]);
// Flush the outputstream.
//outWriter.flush();
break;
case INPUT:
// accept one byte of input, storing its value in the
// byte at the data pointer.
data[dataPointer] = (byte) consoleReader.read();
break;
case BRACKET_LEFT:
if (data[dataPointer] == 0) {
int level = 1;
while (level > 0) {
tokenPointer++;
if (tokens.get(tokenPointer).equals(Token.BRACKET_LEFT))
level++;
else if (tokens.get(tokenPointer).equals(Token.BRACKET_RIGHT))
level--;
}
}
break;
case BRACKET_RIGHT:
if (data[dataPointer] != 0) {
int level = 1;
while (level > 0) {
tokenPointer--;
if (tokens.get(tokenPointer).equals(Token.BRACKET_LEFT))
level--;
else if (tokens.get(tokenPointer).equals(Token.BRACKET_RIGHT))
level++;
}
}
break;
}
tokenPointer++;
}
// Clear all data.
initate(data.length);
}
}