A Brainf**k Interpreter in JavaScript

Brainf**k (I bet you can guess what the asterisks are covering…) is a tiny, esoteric programming language. It is classified as Turing-complete, but its practical use is very limited (if not nonexistent). BF is an interesting challenge because it is so simple. Many devoted developers spend lots of time creating the smallest, fastest BF interpreters and compilers they can. One user on Codegolf created a BF implementation that was only 106 bytes long. That’s pretty impressive.

BF has eight commands (which will be discussed in a moment). Every program has access to a series of memory blocks that can have any range of values. When a BF program loads, all the “cells” in the memory (really just an array) are initialized in value to zero. BF programs can switch between different blocks of memory (change the array index that they are accessing), increment the values of specific blocks, decrement the values of specific blocks, print a character representation of a block to the screen, or put a character’s value into a block. Programs can also loop. They are executed command-by-command from left to right.

There is no official language specification for BF, so many details are left up to the individual implementation. However, the following standards are pretty common (and were implemented in my BF interpreter):

  • Using bytes for memory. My BF interpreter limits values in cells to [0, 255].
  • Allowing overflows. Blocks overflow when their value goes outside the permissible range of [0, 255]. That is, when a program tries to make a block’s value -1, its value becomes 255, and when a program tries to make a block’s value 256, its value becomes zero.
  • 30,000 blocks (29.3kb) of available memory.
  • Non-command characters are ignored.

The eight commands:

  •  + increases the value of the current block by one.
  • - decreases the value of the current block by one.
  • > increases the block index by one.
  • < decreases the block index by one.
  • . prints the block to the screen as an ASCII character.
  • , gets an ASCII character and puts it in the current block.
  • [ opens a loop. It will jump to the end of the loop if the current block’s value is zero.
  • ] closes a loop. It will jump to the beginning of the loop if the current block’s value is not zero. If it is zero, the program will continue.

I’m not going to teach you how to write BF programs in this post; I’m hardly a maestro of it myself. If you want to learn more about BF, Google is an awesome resource.

My interpreter is pretty simple. The first task was to create a crash-reporting function, since I figured that would probably happen a lot. For future reference, “output” is the ID of the part of the page where BF script output goes.

function crash(reason, at){ // When the program dies
	$("#output").text("CRASHED: " + reason + " ( at char index " + at + ")");

The actual interpreter starts out with the declaration of a run function and all sorts of BF-related variables.

function run(data){ // Runs the BF program. Data: program to run.
	var mem = []; // Program memory
	// Initialize all the memory
	for(var i = 0; i < 30000; i++){
		mem[i] = 0;
	var pointer = 0; // Pointer to memory
	$("#output").text(""); // Clear output field

Next, it loops through each character in the program (specified to the function as data) and if it is BF-legal, the required action is performed. The simple ones (that aren’t loops) are self-explanatory.

for(var i = 0; i < data.length; i++){ 	
        if(data[i] === ">"){ // Right one cell
		if(pointer < 30000) pointer++;
			crash("There are only 30,000 usable cells of memory. Sorry.", i); // Trying to use too many cells.
	else if(data[i] === "<"){ // Left one cell 		
                if (pointer > 0) pointer--;
		else {
			crash("Cannot decrement pointer when pointer is at first cell.", i); // Trying to go below cell zero.
	else if(data[i] === "+"){ // Increment cell value
		if(mem[pointer] > 255) mem[pointer] = 0; // Overflow
	else if(data[i] === "-"){ // Decrement cell value
		if (mem[pointer] > 0) mem[pointer]--;
		else {
			mem[pointer] = 255; // Overflow back to 255
	else if(data[i] == "."){ // Put character to screen
		var memChar = String.fromCharCode(mem[pointer]);
		if (memChar == "\n") memChar = ""; // Turn newlines into breaks
		$("#output").append(String.fromCharCode(mem[pointer])); // Log the correct character from its code
	else if(data[i] == ","){
		mem[pointer] = window.prompt("Please enter one character.").charCodeAt(0); // Set memory to char code

Next come loops. There are loads of elegant ways of going about loops; a stack storing the start indices of loops could be used to avoid all the searching my implementation does. However, simplicity was on my mind when I wrote this program: it suffices to say I took the slow, not-so-elegant way out. When the interpreter encounters the start of a loop (a [), it checks to see if the value of the current cell is zero. If it is not, it just continues along. If it is, things get more interesting. The interpreter loops through the program until it finds the corresponding end of the loop so that the program can continue executing properly.

The task is not as simple as incrementing i (the “instruction pointer,” so to speak) until data[i] is a ]. Other loops could be in the way. The solution is shockingly simple: keep track of the number of newly open loops as the program searches for the end of the original loop. I used a counter to keep track of the loop openings. Every [ increments it; every ] decrements it. When the counter gets to zero and the program finds a ], the index has been found. All that is left is to change the “instruction pointer” to the new location in the program.

The ] routine works in the exact opposite way. It keeps track of ]s instead of [s but is otherwise very similar. Here’s what it looks like:

else if(data[i] == "["){
	if(mem[pointer] != 0) continue;
	else{ // Search for corresponding ]
		var openCount = 0; // # of open loops
		for(var j = i; j < data.length;j++){ // Loop through more characters
			if(data[j] === "[") openCount++; // Another open loop
			else if(data[j] === "]"){ // A closing of a loop
				openCount--; // Decrement open count
				if(openCount === 0){ // If we're at zero, we're done.
					i = j; // Move the program forward
					break; // Stop looping
		if(openCount != 0){
			crash("Open loop.", i);
else if(data[i] === "]"){
	// Same deal as [ except going backwards
	if(mem[pointer] != 0){
		var closeCount = 0; // We use close count on this one because it makes more sense (since we're doing the opposite from before!)
		for(var j = i; j >= 0; j--){
			if(data[j] === "]") closeCount++;
			else if(data[j] === "["){
				if(closeCount === 0){
					i = j;
		if(closeCount != 0) {
			crash("Too many loop closings.", i);

That’s all there is to it. The rest of the page that contains the interpreter, which you can find here, is instructions and a textbox to let you put a program in.

Here’s what the finished product looks like:

It's not as pretty as TextRacer but it gets the job done.

The interpreter running a ROT13 cipher example I found on Wikipedia.

Overall, I was surprised with how quickly I managed to get my interpreter working. I was also glad I went with the architecture I did; though it would have been possible to convert the BF to JavaScript and then eval() it, the program would have lost most of its charm. This program could certainly use some refining but overall, it gets the job done! Happy BFing!

Leave a Reply

Your email address will not be published. Required fields are marked *

× 2 = two

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>