Modification history:
- 2012-12-19 - First version.
- 2012-12-29 - Fixed loop nesting (loops can nest up to 10 levels deep) and incorrect brainf*ck code due to copy-and-paste mistake.
- 2013-01-04 - Added nested loop example.
Here is a C++ program which translates Brainf*ck into C. The code it produces is pretty ugly, but it works.
Translator source code:
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
|
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#define BF_BUFFER_MIN "0"
#define BF_BUFFER_MAX "32768"
static const char* BF_HEAD = "#include <stdint.h>\n"
"#include <stdio.h>\n"
"\n"
"#define BUFFER_MIN " BF_BUFFER_MIN "\n"
"#define BUFFER_MAX " BF_BUFFER_MAX "\n"
"\n"
"int main(void)\n"
"{\n"
" static uint8_t buffer[BUFFER_MAX];\n"
" static uint32_t index = 0;\n";
static const char* BF_IPTR = " if (index < BUFFER_MAX)\n"
" ++index;\n"
" else\n"
" index = 0;\n";
static const char* BF_DPTR = " if (index > BUFFER_MIN)\n"
" --index;\n"
" else\n"
" index = BUFFER_MAX - 1;\n";
static const char* BF_IVAL = " ++buffer[index];\n";
static const char* BF_DVAL = " --buffer[index];\n";
static const char* BF_PUTC = " putchar(buffer[index]);\n";
static const char* BF_GETC = " buffer[index] = getchar();\n";
static const char* BF_LOOP1 = "L$a:\n"
" if (buffer[index] == 0)\n"
" goto L$b;\n";
static const char* BF_LOOP2 = "L$b:\n"
" if (buffer[index] != 0)\n"
" goto L$a;\n";
static const char* BF_TAIL = " return 0;\n"
"}\n";
static std::string replace_all(const std::string& a, const std::string& b, std::string s)
{
size_t pos = 0;
while ((pos = s.find(a)) != std::string::npos)
s.replace(pos, a.size(), b);
return s;
}
static std::string chars2string(std::vector <char> chars)
{
std::stringstream sstream;
for (char c : chars)
sstream << c;
return sstream.str();
}
int main()
{
int c, label = 1, nest = 0;
std::cout << BF_HEAD;
while ((c = std::cin.get())) {
if (std::cin.eof())
break;
switch (c) {
case '>': std::cout << BF_IPTR; break;
case '<': std::cout << BF_DPTR; break;
case '+': std::cout << BF_IVAL; break;
case '-': std::cout << BF_DVAL; break;
case '.': std::cout << BF_PUTC; break;
case ',': std::cout << BF_GETC; break;
case '[':
std::cout << replace_all("$", chars2string({ char(label + '0'),
char(nest + '0') }), BF_LOOP1);
++nest;
break;
case ']':
--nest;
std::cout << replace_all("$", chars2string({ char(label + '0'),
char(nest + '0') }), BF_LOOP2);
if (!(nest))
++label;
break;
default:
break;
}
}
std::cout << BF_TAIL << std::endl;
return 0;
}
| |
Example input:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Output of translator:
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
#include <stdint.h>
#include <stdio.h>
#define BUFFER_MIN 0
#define BUFFER_MAX 32768
int main(void)
{
static uint8_t buffer[BUFFER_MAX];
static uint32_t index = 0;
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
L10a:
if (buffer[index] == 0)
goto L10b;
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
++buffer[index];
++buffer[index];
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
--buffer[index];
L10b:
if (buffer[index] != 0)
goto L10a;
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
++buffer[index];
putchar(buffer[index]);
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
putchar(buffer[index]);
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
putchar(buffer[index]);
putchar(buffer[index]);
++buffer[index];
++buffer[index];
++buffer[index];
putchar(buffer[index]);
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
++buffer[index];
putchar(buffer[index]);
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
if (index > BUFFER_MIN)
--index;
else
index = BUFFER_MAX - 1;
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
++buffer[index];
putchar(buffer[index]);
if (index < BUFFER_MAX)
++index;
else
index = 0;
putchar(buffer[index]);
++buffer[index];
++buffer[index];
++buffer[index];
putchar(buffer[index]);
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
putchar(buffer[index]);
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
--buffer[index];
putchar(buffer[index]);
if (index < BUFFER_MAX)
++index;
else
index = 0;
++buffer[index];
putchar(buffer[index]);
if (index < BUFFER_MAX)
++index;
else
index = 0;
putchar(buffer[index]);
return 0;
}
| |
Output of translated program:
Hello World!
Example with nested loops:
[[[[[[[[]]]]]]]]
Output of translator:
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
|
#include <stdint.h>
#include <stdio.h>
#define BUFFER_MIN 0
#define BUFFER_MAX 32768
int main(void)
{
static uint8_t buffer[BUFFER_MAX];
static uint32_t index = 0;
L10a:
if (buffer[index] == 0)
goto L10b;
L11a:
if (buffer[index] == 0)
goto L11b;
L12a:
if (buffer[index] == 0)
goto L12b;
L13a:
if (buffer[index] == 0)
goto L13b;
L14a:
if (buffer[index] == 0)
goto L14b;
L15a:
if (buffer[index] == 0)
goto L15b;
L16a:
if (buffer[index] == 0)
goto L16b;
L17a:
if (buffer[index] == 0)
goto L17b;
L18a:
if (buffer[index] == 0)
goto L18b;
L19a:
if (buffer[index] == 0)
goto L19b;
L19b:
if (buffer[index] != 0)
goto L19a;
L18b:
if (buffer[index] != 0)
goto L18a;
L17b:
if (buffer[index] != 0)
goto L17a;
L16b:
if (buffer[index] != 0)
goto L16a;
L15b:
if (buffer[index] != 0)
goto L15a;
L14b:
if (buffer[index] != 0)
goto L14a;
L13b:
if (buffer[index] != 0)
goto L13a;
L12b:
if (buffer[index] != 0)
goto L12a;
L11b:
if (buffer[index] != 0)
goto L11a;
L10b:
if (buffer[index] != 0)
goto L10a;
return 0;
}
| |