-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompiler.py
97 lines (75 loc) · 2.25 KB
/
compiler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import sys
BF_ALLOWED_SYMBOLS = '><+-.,[]'
C_FILE_TEMPLATE = """#include<stdio.h>
int main(void) {
\tchar array[30000] = {0};
\tchar *ptr = array + 15000;
%s
\treturn 0;
}
"""
def load_bf_code(filename):
with open(filename) as f:
return [
command
for command in f.read()
if command in BF_ALLOWED_SYMBOLS
]
def preprocess_bf_code(raw_bf_code):
bf_code = []
indent = 1
last_op = None
for op in raw_bf_code:
if op == ']':
indent -= 1
if op in '><+-' and op == last_op:
bf_code[-1]['count'] += 1
else:
bf_code.append({'op': op, 'indent': indent, 'count': 1})
if op == '[':
indent += 1
last_op = op
return bf_code
def transpile_to_c(bf_code):
c_code = []
for record in bf_code:
op = record['op']
indent = record['indent']
count = record['count']
instr = ''
if op == '>':
instr = 'ptr += {};'.format(count) if count > 1 else 'ptr++;'
elif op == '<':
instr = 'ptr -= {};'.format(count) if count > 1 else 'ptr--;'
elif op == '+':
instr = '(*ptr) += {};'.format(count) if count > 1 else '(*ptr)++;'
elif op == '-':
instr = '(*ptr) -= {};'.format(count) if count > 1 else '(*ptr)--;'
elif op == '.':
instr = 'putchar(*ptr);'
elif op == ',':
instr = '(*ptr) = getchar();'
elif op == '[':
instr = 'while (*ptr) {'
elif op == ']':
instr = '}'
c_code.append('\t' * indent + instr)
return c_code
def save_c_code(filename, c_code):
code = C_FILE_TEMPLATE % '\n'.join(c_code)
with open(filename, 'w') as f:
f.write(code)
print(code)
def compile_c_code(filename):
subprocess.call('gcc -x c {0} -o {0}'.format(filename), shell=True)
def main(input_filename, output_filename='a.out'):
bf_code = load_bf_code(input_filename)
bf_code = preprocess_bf_code(bf_code)
c_code = transpile_to_c(bf_code)
save_c_code(output_filename, c_code)
compile_c_code(output_filename)
if __name__ == '__main__':
main(*sys.argv[1:])