Skip to content

Instantly share code, notes, and snippets.

@gvx
Forked from jdp/bf2c.py
Created May 25, 2012 07:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvx/2786437 to your computer and use it in GitHub Desktop.
Save gvx/2786437 to your computer and use it in GitHub Desktop.
Naive brainfuck-to-C transpiler
#!/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 depth:
raise SyntaxError("Unmatched opening bracket")
return ast
simple_stmts = {'+': "++*p", '-': "--*p", '<': "--p", '>': "++p", '.': "putchar(*p)", ',': "p = getchar()"}
def compile_to_c(tree, depth):
buf = ""
indent = " " * depth
for node in tree:
if isinstance(node, list):
buf += indent + "while (*p) {\n"
buf += compile_to_c(node, depth + 1)
buf += indent + "}\n"
else:
buf += indent + simple_stmts[node] + ";\n"
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, 1)
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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment