DEV Community 👩‍💻👨‍💻

FreakCdev
FreakCdev

Posted on • Updated on

Creating Brainfuck

Brainfuck is one of the most iconic programming languages out there, and probably the king of esolangs. So today, I will share how to create Brainfuck.

Understanding Brainfuck

So as we all might have known, Brainfuck has 8 commands:

  • ">" increment the data pointer (to point to the next cell to the right).
  • "<" decrement the data pointer (to point to the next cell to the left).
  • "+" increment (increase by one) the byte at the data pointer.
  • "-" decrement (decrease by one) the byte at the data pointer.
  • "." output the byte at the data pointer.
  • "," accept one byte of input, storing its value in the byte at the data pointer.
  • "[" if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.
  • "]" if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command.

Choosing a way to run our code

Normally, you would have these programs to execute a programming language's codes:

  • Compiler (compiles to machine code)
  • Interpreter
  • Transpiler (compiles to source code)

Compilers are quite complex and they require you to have machine code's understanding which is not our choice when just creating a simple esolang. Interpreters and transpilers are good ones since they are easy to create, especially for esolangs. In this article, I will create a transpiler as it's the easiest.

Creating a transpiler

Language to use

I will use Javascript to create the transpiler, and the compilation target will be Javascript as well. Now, let's get our hand dirty.

Create a transpile function

We just simply create a function which takes all the codes as input, and return the compiled codes to output.

const transpile = input => {
    let output = 'let cells = Array(30000).fill(0), ptr=0;';
    return output;
}
Enter fullscreen mode Exit fullscreen mode

The output variable already has 1 line to declare an array cells which has 30000 elements all start at 0 and a ptr variable which is the pointer of the cell.

Parsing commands

We can create a simple lexer like this:

const transpile = input => {
    let output = 'let cells = Array(30000).fill(0), ptr=0;';
    input.split('').forEach(token => {

    })
    return output;
}
Enter fullscreen mode Exit fullscreen mode

Now, we want to do stuffs which each token (command), we just need to add a switch statement:

const transpile = input => {
    let output = 'let cells = Array(30000).fill(0), ptr=0;';
    input.split('').forEach(token => {
        switch (token) {
            case '+':
                break;
            case '-':
                break;
            case '>':
                break;
            case '<':
                break;
            case '.':
                break;
            case ',':
                break;
            case '[':
                break;
            case ']':
                break;
        }
    })
    return output;
}
Enter fullscreen mode Exit fullscreen mode

Then, we just implement each token's functionality in JS:

const transpile = input => {
    let output = 'let cells = Array(30000).fill(0), ptr=0;';
    input.split('').forEach(token => {
        switch (token) {
            case '+':
                output+='++cells[ptr];';
                break;
            case '-':
                output+='--cells[ptr];';
                break;
            case '>':
                output+='++ptr;';
                break;
            case '<':
                output+='--ptr;';
                break;
            case '.':
                output+='document.write(String.fromCharCode(cells[ptr]));';
                break;
            case ',':
                output+='cells[ptr]=prompt();';
                break;
            case '[':
                output+='while (cells[ptr] > 0) {';
                break;
            case ']':
                output+='}';
                break;
        }
    })
    return output;
}
Enter fullscreen mode Exit fullscreen mode

There you go, that's how you can create a Brainfuck transpiler, you just need to take the output codes and run them in a browser, then it should work fine.

Running it immediately

If you're tired of copying the output codes and run it in a different place, you can create a version that runs the code immediately like this:

const transpile = input => {
    let output = 'let cells = Array(30000).fill(0), ptr=0;';
    input.split('').forEach(token => {
        switch (token) {
            case '+':
                output+='++cells[ptr];';
                break;
            case '-':
                output+='--cells[ptr];';
                break;
            case '>':
                output+='++ptr;';
                break;
            case '<':
                output+='--ptr;';
                break;
            case '.':
                output+='document.write(String.fromCharCode(cells[ptr]));';
                break;
            case ',':
                output+='cells[ptr]=prompt();';
                break;
            case '[':
                output+='while (cells[ptr] > 0) {';
                break;
            case ']':
                output+='}';
                break;
        }
    })
    new Function(output)();
}
Enter fullscreen mode Exit fullscreen mode

Basically, we just create a new function and execute the codes.

Thanks for your time, if you're interested in programming languages, please consider checking out my language "FreakC".

Top comments (0)

Create an Account!
Now it's your turn!
 
🗒 Share a tutorial
🤔 Reflect on your coding journey
❓ Ask a question

Create an account to join hundreds of thousands of DEV members on their journey.