Skip to content

Instantly share code, notes, and snippets.

@augustohp
Forked from jdp/bf2c.py
Created March 30, 2012 05:11
Show Gist options
  • Save augustohp/2246690 to your computer and use it in GitHub Desktop.
Save augustohp/2246690 to your computer and use it in GitHub Desktop.
Naive brainfuck-to-C transpiler
#!/usr/bin/env python3
import argparse
import sys
def tokenize(source):
return list(source)
def parse(tokens):
ast = []
stack = [ast]
node = ast
for token in tokens:
if token == '[':
node.append([])
stack.append(node)
node = node[-1]
elif token == ']':
node = stack.pop()
elif token in "+-<>,.":
node.append(token)
return ast
def compile_to_c(tree, depth=1):
buf = ""
def emit(code):
nonlocal buf
buf += (" " * depth) + code + "\n"
for node in tree:
if isinstance(node, list):
emit("while (*p) {")
emit(compile_to_c(node, depth=depth+1).rstrip()[2:])
emit("}")
elif node == '+': emit("++*p;")
elif node == '-': emit("--*p;")
elif node == '>': emit("++p;")
elif node == '<': emit("--p;")
elif node == ",": emit("*p = getchar();")
elif node == ".": emit("putchar(*p);")
return buf
if __name__ == '__main__':
argparser = argparse.ArgumentParser(description="Transpile a Brainfuck program to a different host language")
argparser.add_argument('infile', nargs='?', type=argparse.FileType('r'), \
default='-', help="File to read source from, defaults to stdin")
argparser.add_argument('-t', '--target', action='store', type=str, \
choices=set(['c']), default='c', help="Output language to target")
args = argparser.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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment