% A basic brainfuck interpreter :- use_module(library(main)). :- use_module(library(pure_input)). :- use_module(library(lists)). :- initialization(main, main). % parsing with a dcg instr(loop(Is)) --> [91], instrs(Is), [93]. instr(A) --> [C], {atom_codes(A, [C]), member(A, ['>', '<', '+', '-', '.', ','])}. instrs([]) --> []. instrs([X | Xs]) --> instr(X), instrs(Xs). instrs(Xs) --> [_], instrs(Xs). % ignore everything that is not an instruction % initialize the interpreter interpret(P) :- interpret(P, [], 0, []). % terminate on empty instruction list interpret([], _, _, _). interpret(['+' | Is], Ls, N, Rs) :- N1 is N + 1, interpret(Is, Ls, N1, Rs). interpret(['-' | Is], Ls, N, Rs) :- N1 is N - 1, interpret(Is, Ls, N1, Rs). interpret(['<' | Is], [], N, Rs) :- interpret(Is, [], 0, [N | Rs]). interpret(['<' | Is], [L | Ls], N, Rs) :- interpret(Is, Ls, L, [N | Rs]). interpret(['>' | Is], Ls, N, []) :- interpret(Is, [N | Ls], 0, []). interpret(['>' | Is], Ls, N, [R | Rs]) :- interpret(Is, [N | Ls], R, Rs). interpret(['.' | Is], Ls, N, Rs) :- format("~c", [N]), interpret(Is, Ls, N, Rs). interpret([',' | Is], Ls, _, Rs) :- get_char(C), char_code(C, N1), interpret(Is, Ls, N1, Rs). interpret([loop(_) | Is], Ls, 0, Rs) :- interpret(Is, Ls, 0, Rs). interpret([loop(Xs) | Is], Ls, N, Rs) :- append(Xs, [loop(Xs) | Is], Is1), interpret(Is1, Ls, N, Rs). main([File]) :- phrase_from_file(instrs(P), File), interpret(P).