Skip to content

Instantly share code, notes, and snippets.

@jdp
Created March 29, 2012 14:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jdp/2237916 to your computer and use it in GitHub Desktop.
Save jdp/2237916 to your computer and use it in GitHub Desktop.
Naive brainfuck-to-C compiler
#!/usr/bin/env python
import argparse
import sys
def tokenize(source):
return list(source)
def parse(tokens):
depth = 0
ast = []
stack = [ast]
node = ast
for token in tokens:
if token == '[':
node.append([])
stack.append(node)
node = node[-1]
depth += 1
elif token == ']':
node = stack.pop()
depth -= 1
elif token in "+-<>,.":
node.append(token)
if not depth == 0:
raise SyntaxError("Unmatched opening bracket")
return ast
def compile_to_c(tree):
buf = ""
for node in tree:
if isinstance(node, list):
buf += "while (*p) { "
buf += compile_to_c(node)
buf += "} "
elif node == '+':
buf += "++*p; "
elif node == '-':
buf += "--*p; "
elif node == '>':
buf += "++p; "
elif node == '<':
buf += "--p; "
elif node == ",":
buf += "*p = getchar(); "
elif node == ".":
buf += "putchar(*p); "
return buf
if __name__ == '__main__':
ap = argparse.ArgumentParser(description="Transpile a Brainfuck program to a different host language")
ap.add_argument('infile', nargs='?', type=argparse.FileType('r'), \
default='-', help="File to read source from, defaults to stdin")
ap.add_argument('-t', '--target', action='store', type=str, \
choices=set(['c']), default='c', help="Output language to target")
args = ap.parse_args()
code = args.infile.read()
tokens = tokenize(code)
ast = parse(tokens)
if args.target == 'c':
print "#include <stdio.h>"
print "#include <stdlib.h>"
print "int main(int argc, char **argv) {"
print " int *p = (int *)malloc(30000 * sizeof(int));"
print " ", compile_to_c(ast)
print " return 0;"
print "}"
>+++++++++
[<++++++++>-]
<.>+++++++
[<++++>-]
<+.+++++++..+++.>>>++++++++
[<++++>-]
<.>>>++++++++++
[<+++++++++>-]
<---.<<<<.+++.------.--------.>>+.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int *p = (int *)malloc(30000 * sizeof(int));
++p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
while (*p) {
--p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++p;
--*p;
}
--p;
putchar(*p);
++p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
while (*p) {
--p;
++*p;
++*p;
++*p;
++*p;
++p;
--*p;
}
--p;
++*p;
putchar(*p);
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
putchar(*p);
putchar(*p);
++*p;
++*p;
++*p;
putchar(*p);
++p;
++p;
++p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
while (*p) {
--p;
++*p;
++*p;
++*p;
++*p;
++p;
--*p;
}
--p;
putchar(*p);
++p;
++p;
++p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
while (*p) {
--p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++*p;
++p;
--*p;
}
--p;
--*p;
--*p;
--*p;
putchar(*p);
--p;
--p;
--p;
--p;
putchar(*p);
++*p;
++*p;
++*p;
putchar(*p);
--*p;
--*p;
--*p;
--*p;
--*p;
--*p;
putchar(*p);
--*p;
--*p;
--*p;
--*p;
--*p;
--*p;
--*p;
--*p;
putchar(*p);
++p;
++p;
++*p;
putchar(*p);
return 0;
}
@augustohp
Copy link

@keyle
Copy link

keyle commented Jul 23, 2014

Thanks for your article Justin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment