|
import java.io.IOException; |
|
import java.util.LinkedList; |
|
|
|
public class BF { |
|
private interface Visitor { |
|
void visit (Loop loop); |
|
void visit (Left left); |
|
void visit (Right right); |
|
void visit (Increment increment); |
|
void visit (Decrement decrement); |
|
void visit (Input input); |
|
void visit (Output output); |
|
void visit (Program program); |
|
} |
|
private interface Node { |
|
void accept (Visitor v); |
|
} |
|
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 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); |
|
i++; |
|
if (c == '<') seq.add (new Left ()); |
|
if (c == '>') seq.add (new Right ()); |
|
if (c == '+') seq.add (new Increment ()); |
|
if (c == '-') seq.add (new Decrement ()); |
|
if (c == '.') seq.add (new Output ()); |
|
if (c == ',') seq.add (new Input ()); |
|
if (c == '[') seq.add (new Loop (doParse (str))); |
|
if (c == ']') return seq; |
|
} |
|
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.InterpreterVisitor()); |
|
Node hello = BF.parse("++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."); |
|
hello.accept(new BF.InterpreterVisitor()); |
|
Node beer = BF.parse(">+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>++++[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>+++++++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.-------.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]"); |
|
beer.accept(new BF.InterpreterVisitor()); |
|
Node fibonacci = BF.parse("+++++++++++>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]"); |
|
fibonacci.accept(new BF.InterpreterVisitor()); |
|
Node rot13 = BF.parse("+[,+[-[>+>+<<-]>[<+>-]+>>++++++++[<-------->-]<-[<[-]>>>+[<+<+>>-]<[>+<-]<[<++>>>+[<+<->>-]<[>+<-]]>[<]<]>>[-]<<<[[-]<[>>+>+<<<-]>>[<<+>>-]>>++++++++[<-------->-]<->>++++[<++++++++>-]<-<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<<<<+>>>>++++[<++++++++>-]>-]<<-<-]>[<<<<[-]>>>>[<<<<->>>>-]]<<++++[<<++++++++>>-]<<-[>>+>+<<<-]>>[<<+>>-]+>>+++++[<----->-]<-[<[-]>>>+[<+<->>-]<[>+<-]<[<++>>>+[<+<+>>-]<[>+<-]]>[<]<]>>[-]<<<[[-]<<[>>+>+<<<-]>>[<<+>>-]+>------------[<[-]>>>+[<+<->>-]<[>+<-]<[<++>>>+[<+<+>>-]<[>+<-]]>[<]<]>>[-]<<<<<------------->>[[-]+++++[<<+++++>>-]<<+>>]<[>++++[<<++++++++>>-]<-]>]<[-]++++++++[<++++++++>-]<+>]<.[-]+>>+<]>[[-]<]<]"); |
|
rot13.accept(new BF.InterpreterVisitor()); |
|
} |
|
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 static class InterpreterVisitor implements Visitor { |
|
private byte[] array; |
|
private int pointer; |
|
|
|
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; |
|
n.body.accept(this); |
|
} |
|
} |
|
} |