Skip to content

Instantly share code, notes, and snippets.

@mueschm
Created August 5, 2012 02:37
Show Gist options
  • Save mueschm/3261206 to your computer and use it in GitHub Desktop.
Save mueschm/3261206 to your computer and use it in GitHub Desktop.
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BF {
private interface Visitor
{
void visit (Character character);
void visit (Function function);
void visit (CallFunction functionCall);
void visit (Loop loop);
void visit (Left left);
void visit (Right right);
void visit (Increment increment);
void visit (Decrement decrement);
void visit (Number number);
void visit (Input input);
void visit (Output output);
void visit (Program program);
}
private interface Node
{
void accept (Visitor v);
}
private class Character implements Node
{
public String character;
public Character(String character)
{
this.character = character;
}
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Function implements Node
{
public Node body;
public Function(Node body)
{
this.body = body;
}
public void accept(Visitor v)
{
v.visit(this);
}
}
private class CallFunction implements Node
{
public void accept(Visitor v)
{
v.visit(this);
}
}
private class Left implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Right implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Increment implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Decrement implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Input implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Output implements Node
{
public void accept (Visitor v)
{
v.visit(this);
}
}
private class Number implements Node
{
public int iterations;
public Node command;
public Number(int number, Node command)
{
iterations = number;
this.command = command;
}
public void accept(Visitor v)
{
v.visit(this);
}
}
private class Sequence implements Node
{
private LinkedList<Node> children;
public Sequence()
{
children = new LinkedList<Node>();
}
public void accept (Visitor v)
{
for (Node child : children)
{
child.accept(v);
}
}
public void add (Node instruction)
{
children.add(instruction);
}
}
private class Loop implements Node
{
public Node body;
public Loop (Node body)
{
this.body = body;
}
public void accept (Visitor v)
{
v.visit (this);
}
}
public static class Program implements Node
{
public Node body;
public Program (Node body)
{
this.body = body;
}
public void accept(Visitor v)
{
v.visit (this);
}
}
private int i = 0;
private Sequence doParse (String str)
{
Sequence seq = new Sequence();
char c;
while (i < str.length ())
{
c = str.charAt (i);
if (c == '<') seq.add (new Left ());
else if (c == '>') seq.add (new Right ());
else if (c == '+') seq.add (new Increment ());
else if (c == '-') seq.add (new Decrement ());
else if (c == '.') seq.add (new Output ());
else if (c == ',') seq.add (new Input ());
else if (c == ':') seq.add (new CallFunction());
else if (c == '[')
{
i++;
seq.add (new Loop (doParse (str)));
}
else if(c == '(')
{
i++;
seq.add (new Function(doParse(str)));
}
else if(str.charAt(i) >= 48 && str.charAt(i) <= 57)
{
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(str.substring(i));
m.find();
String numString = m.group();
i += numString.length();
int num = Integer.parseInt(numString);
int temp = i;
i = 0;
Node node = doParse(""+str.charAt(temp));
i = temp;
seq.add(new Number(num,node));
}
else if (c == ']') return seq;
else if (c == ')') return seq;
else if (c == '"')
{
i++;
String characters = "";
while(str.charAt(i) != '"')
characters += str.charAt(i++);
seq.add(new Character(characters));
}
i++;
}
return seq;
}
public static Program parse (String str)
{
return new Program (new BF().doParse(str));
}
public static void main(String[] args)
{
Node ascii = BF.parse("(++++++++++<[>+>+<<-]>>[<<+>>-])>::::::::::::::<<<<<<<--------.>>>---------.+++++++..>---------.<<<<<<<------.<--------.>>>>>---.>>>.+++.<.--------.<<<<<<<+.");
ascii.accept(new BF.CompilerVisitor());
System.out.println();
Node name = BF.parse("77+.>105+.>107+.>101+.>32+.>77+.>117+.>101+.>115+.>99+.>104+.>");
name.accept(new BF.InterpreterVisitor());
System.out.println();
}
public static class PrintVisitor implements Visitor
{
public void visit (Left n) { System.out.print('<'); }
public void visit (Right n) { System.out.print('>'); }
public void visit (Increment n) { System.out.print('+'); }
public void visit (Decrement n) { System.out.print('-'); }
public void visit (Input n) { System.out.print(','); }
public void visit (Output n) { System.out.print('.'); }
public void visit (Loop n) { System.out.print('['); n.body.accept(this); System.out.print(']'); }
public void visit (Program n) { n.body.accept(this); }
public void visit(Character n) {System.out.print("\""+n.character+"\"");}
public void visit(Number n) {System.out.print(""+n.iterations);n.command.accept(this);}
public void visit(Function function) {System.out.print("("); function.body.accept(this); System.out.print(")");}
public void visit(CallFunction functionCall) {System.out.print(":");}
}
public static void displayByteArray(byte[] array, int pointer)
{
for(int i = 0;i < 100;i++)
{
for(int j = 0;j < 300;j++)
{
if(pointer == (i*300)+j)
System.out.print(">");
else
System.out.print(" ");
System.out.print(""+array[(i*300)+j]);
}
System.out.println();
}
System.out.println("===================================");
}
public static class CompilerVisitor implements Visitor
{
int loopNumber;
private Map<Byte,Function> functions;
private byte[] array;
private int pointer;
public void visit(Character character)
{
System.out.println("string=\""+character.character+"\";");
System.out.println("for(int i = 0;i < string.length();i++){");
System.out.println("char c = string.charAt(i);");
System.out.println("array[pointer] = (byte)c;");
System.out.println("pointer++;");
System.out.println("array[pointer] = 0;");
System.out.println("}");
}
public void visit(Function function)
{
System.out.println("procedures[array[pointer]] = new Procedure() {public void execute() {");
function.body.accept(this);
System.out.println("}};");
}
public void visit(CallFunction functionCall)
{
System.out.println("procedures[array[pointer]].execute();");
}
public void visit(Loop loop)
{
System.out.println("while(array[pointer] != 0){");
loop.body.accept(this);
System.out.println("}");
}
public void visit(Left left)
{
System.out.println("pointer--;");
}
public void visit(Right right)
{
System.out.println("pointer++;");
}
public void visit(Increment increment)
{
System.out.println("array[pointer]++;");
}
public void visit(Decrement decrement)
{
System.out.println("array[pointer]--;");
}
public void visit(Input input)
{
System.out.println("array[pointer] = (byte) System.in.read();");
}
public void visit(Output output)
{
System.out.println("System.out.print(\"\"+(char)array[pointer]);");
}
public void visit(Program program)
{
loopNumber = 0;
array = new byte[30000];
pointer = 0;
functions = new HashMap<Byte,Function>();
System.out.println("class Prog {");
System.out.println("public interface Procedure {");
System.out.println(" void execute();");
System.out.println("}");
System.out.println("private static Procedure[] procedures;");
System.out.println("private static byte[] array;");
System.out.println("private static int pointer;");
System.out.println("private static String string;");
System.out.println("public static void main(String[] args){");
System.out.println("array = new byte[30000];");
System.out.println("pointer = 0;");
System.out.println("procedures = new Procedure[256];");
program.body.accept(this);
System.out.println("}}");
}
public void visit(Number number)
{
for(int i = 0;i < number.iterations;i++)
number.command.accept(this);
}
}
public static class InterpreterVisitor implements Visitor
{
private byte[] array;
private int pointer;
private Map<Byte,Function> functions;
public void visit (Left n) { pointer--; }
public void visit (Right n) { pointer++; }
public void visit (Increment n) { array[pointer]++; }
public void visit (Decrement n) { array[pointer]--; }
public void visit (Input n)
{
try
{
array[pointer] = (byte) System.in.read();
}
catch (IOException e)
{
}
}
public void visit (Output n)
{
System.out.print((char)array[pointer]);
}
public void visit (Loop n)
{
while (array[pointer] != 0)
{
n.body.accept(this);
}
}
public void visit (Program n)
{
array = new byte[30000];
pointer = 0;
functions = new HashMap<Byte,Function>();
n.body.accept(this);
}
public void visit(Character n)
{
for(int i = 0;i < n.character.length();i++)
{
array[pointer] = (byte)n.character.charAt(i);
pointer++;
array[pointer] = 0;
}
}
public void visit(Function n)
{
functions.put(Byte.parseByte(""+(array[pointer])), n);
}
public void visit(CallFunction n)
{
Function function = functions.get(Byte.parseByte(""+array[pointer]));
if(function != null)
function.body.accept(this);
}
public void visit(Number number)
{
for(int i = 0;i < number.iterations;i++)
number.command.accept(this);
}
}
public static class AnimationVisitor implements Visitor
{
private byte[] array;
private int pointer;
private Map<Byte,Function> functions;
public void visit (Left n) { pointer--; BF.displayByteArray(array,pointer); }
public void visit (Right n) { pointer++; BF.displayByteArray(array,pointer); }
public void visit (Increment n) { array[pointer]++; BF.displayByteArray(array,pointer); }
public void visit (Decrement n) { array[pointer]--; BF.displayByteArray(array,pointer); }
public void visit (Input n)
{
try
{
array[pointer] = (byte) System.in.read();
}
catch (IOException e)
{
}
BF.displayByteArray(array,pointer);
}
public void visit (Output n)
{
System.out.print((char)array[pointer]);
BF.displayByteArray(array,pointer);
}
public void visit (Loop n)
{
while (array[pointer] != 0)
{
n.body.accept(this);
}
}
public void visit (Program n)
{
array = new byte[30000];
pointer = 0;
functions = new HashMap<Byte,Function>();
n.body.accept(this);
}
public void visit(Character n)
{
for(int i = 0;i < n.character.length();i++)
{
array[pointer] = (byte)n.character.charAt(i);
pointer++;
array[pointer] = 0;
BF.displayByteArray(array,pointer);
}
}
public void visit(Function n)
{
functions.put(Byte.parseByte(""+(array[pointer])), n);
}
public void visit(CallFunction n)
{
Function function = functions.get(Byte.parseByte(""+array[pointer]));
if(function != null)
function.body.accept(this);
}
public void visit(Number number)
{
for(int i = 0;i < number.iterations;i++)
number.command.accept(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment