BFコンパイラー
以下のようにonelinerで可能です。
ただしLanguage::BF 0.03が必要です。
CodeRepos経由
で、
- svn co svn.coderepos.org/share/lang/perl/Language-BF
- cd Language-BF/trunk
- perl Makefile.PL
- make install
するか、CPANにVersion 0.03が現れるのをお待ち下さい。
Dan the Brainf.cker
1 2 3 4 | perl -MLanguage::BF \
-e 'print Language::BF->new_from_file(shift)->as_perl' t/hello.bf \
| perl
Hello World!
|
Posted feedbacks - awk
久しぶりに投稿します。
-v optimize=1 とするとオプティマイズされます(笑
helloworld.bf:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
% awk -f bf2awk.awk helloworld.bf > helloworld.awk
% awk -f helloworld.awk
Hello World!
helloworld.awk:
BEGIN {
ix = 0
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
while (st[ix]) {
ix++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
ix--
ix--
ix--
ix--
st[ix]--
}
ix++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
st[ix]++
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix--
ix--
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
printf("%c", st[ix])
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
printf("%c", st[ix])
ix++
st[ix]++
printf("%c", st[ix])
ix++
printf("%c", st[ix])
}
% awk -v optimize=1 -f bf2awk.awk helloworld.bf > helloworld-optimized.awk
% awk -f helloworld-optimized.awk
Hello World!
helloworld-optimized.awk:
BEGIN {
ix = 0
st[ix] += 10
while (st[ix]) {
st[++ix]++
st[ix] += 6
st[++ix]++
st[ix] += 9
st[++ix]++
st[ix] += 2
st[++ix]++
ix -= 4
st[ix]--
}
st[++ix]++
st[ix]++
printf("%c", st[ix])
st[++ix]++
printf("%c", st[ix])
st[ix] += 7
printf("%c", st[ix])
printf("%c", st[ix])
st[ix] += 3
printf("%c", st[ix])
st[++ix]++
st[ix]++
printf("%c", st[ix])
ix -= 2
st[ix] += 15
printf("%c", st[ix])
printf("%c", st[++ix])
st[ix] += 3
printf("%c", st[ix])
st[ix] -= 6
printf("%c", st[ix])
st[ix] -= 8
printf("%c", st[ix])
st[++ix]++
printf("%c", st[ix])
printf("%c", st[++ix])
}
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 | BEGIN {
read_buf = ""
if (optimize) reset_last()
indent = ""
indent_print("BEGIN {")
indent_incr()
indent_print("ix = 0")
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
N = split($0, op, "")
for (i=1; i<=N; i++) {
if (op[i] == ">") {
if (optimize) {
if (last_inst == "ix") {
last_arg++
} else {
out_last()
set_last("ix", 1)
}
} else {
indent_print("ix++")
}
} else if (op[i] == "<") {
if (optimize) {
if (last_inst == "ix") {
last_arg--
} else {
out_last()
set_last("ix", -1)
}
} else {
indent_print("ix--")
}
} else if (op[i] == "+") {
if (optimize) {
if (last_inst == "st[ix]") {
last_arg++
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, 1)
}
} else {
indent_print("st[ix]++")
}
} else if (op[i] == "-") {
if (optimize) {
if (last_inst == "st[ix]") {
last_arg--
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, -1)
}
} else {
indent_print("st[ix]--")
}
} else if (op[i] == ".") {
if (optimize) {
s = set_incr_decr("printf(\"%c\", st[ix])")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("printf(\"%c\", st[ix])")
}
} else if (op[i] == ",") {
if (optimize) {
s = set_incr_decr("st[ix] = getchar()")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
if (optimize) {
s = set_incr_decr("while (st[ix]) {")
if (last_inst) out_last()
indent_print(s)
indent_incr()
} else {
indent_print("while (st[ix]) {")
indent_incr()
}
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
indent_print("}")
} else {
;
}
}
}
END {
if (optimize) out_last()
indent_decr()
indent_print("}")
}
function getchar( ch)
{
if (read_buf ~ /^$/) getline read_buf
ch = substr(read_buf,1,1)
read_buf = substr(read_buf,2)
return ch
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
}
return s
}
|
optimize=1 の時に while(st[ix]) の直前に ix++ や ix-- が来ると while(st[++ix]) のように誤ったオプティマイズが行われるバグを修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | --- bf2awk.awk.orig 2007-11-14 00:43:07.000000000 +0900
+++ bf2awk.awk 2007-11-14 01:46:46.000000000 +0900
@@ -77,15 +77,9 @@
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
- if (optimize) {
- s = set_incr_decr("while (st[ix]) {")
- if (last_inst) out_last()
- indent_print(s)
- indent_incr()
- } else {
- indent_print("while (st[ix]) {")
- indent_incr()
- }
+ if (optimize) out_last()
+ indent_print("while (st[ix]) {")
+ indent_incr()
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
|
オプティマイズ時に ++ix st[ix]++ st[ix]++ st[ix]++ が st[++ix]++ st[ix] += 2 となっていたのを st[++ix] += 3 のようにちゃんとまとめるように修正するパッチ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | --- bf2awk.awk.orig 2007-11-14 00:43:07.000000000 +0900
+++ bf2awk.awk 2007-11-14 01:55:50.000000000 +0900
@@ -38,7 +38,7 @@
}
} else if (op[i] == "+") {
if (optimize) {
- if (last_inst == "st[ix]") {
+ if (last_inst ~ /^st\[/) {
last_arg++
} else {
s = set_incr_decr("st[ix]")
@@ -50,7 +50,7 @@
}
} else if (op[i] == "-") {
if (optimize) {
- if (last_inst == "st[ix]") {
+ if (last_inst ~ /^st\[/) {
last_arg--
} else {
s = set_incr_decr("st[ix]")
|
うう駄目だ、getchar() の定義が出力されないので、#3976の ,+[-.,+] をコンパイルしても動かない。 しかも getchar() が文字コードを返すようになってない。ord() を実装。 全面書き換え。 a2pをかましても動くように getline, index 回りを微調整。
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 | BEGIN {
if (optimize) reset_last()
indent = ""
print "BEGIN {"
indent_incr()
indent_print("read_buf = \"\"")
indent_print("ix = 0")
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
N = split($0, op, "")
for (i=1; i<=N; i++) {
if (op[i] == ">") {
if (optimize) {
if (last_inst == "ix") {
last_arg++
} else {
out_last()
set_last("ix", 1)
}
} else {
indent_print("ix++")
}
} else if (op[i] == "<") {
if (optimize) {
if (last_inst == "ix") {
last_arg--
} else {
out_last()
set_last("ix", -1)
}
} else {
indent_print("ix--")
}
} else if (op[i] == "+") {
if (optimize) {
if (last_inst ~ /^st\[/) {
last_arg++
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, 1)
}
} else {
indent_print("st[ix]++")
}
} else if (op[i] == "-") {
if (optimize) {
if (last_inst ~ /^st\[/) {
last_arg--
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, -1)
}
} else {
indent_print("st[ix]--")
}
} else if (op[i] == ".") {
if (optimize) {
s = set_incr_decr("printf(\"%c\", st[ix])")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("printf(\"%c\", st[ix])")
}
} else if (op[i] == ",") {
if (optimize) {
s = set_incr_decr("st[ix] = getchar()")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
if (optimize) {
s = set_incr_decr("while (st[ix]) {")
if (last_inst) out_last()
indent_print(s)
indent_incr()
} else {
indent_print("while (st[ix]) {")
indent_incr()
}
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
indent_print("}")
} else {
;
}
}
}
END {
if (optimize) out_last()
indent_decr()
indent_print("}")
print "function getchar( ch)"
print "{"
print " if (read_buf ~ /^$/) {"
print " if (eof) return -1"
# print " if ((getline read_buf) < 1) { eof = 1; return -1 }"
print " if (getline != 1) { eof = 1; return -1 }" # a2p
print " read_buf = $0" # a2p
print " }"
print " ch = ord(substr(read_buf,1,1))"
print " read_buf = substr(read_buf,2)"
print " return ch"
print "}"
print "function ord(ch, ofs)"
print "{"
print " if (ch == \"\\t\") return 9"
print " if (ch == \"\\n\") return 13"
# print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)"
print " if (ch == \"@\") return 64" # a2p
print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?.ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)" # a2p
print " return ofs ? 31 + ofs : 0"
print "}"
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
}
return s
}
|
#3964-#3978を、optimize=2 を指定すると身も蓋もなく最適化を行うように改良(?)したもの。
- http://namazu.org/~takesako/ppencode/bpencode.html
- http://pc11.2ch.net/test/read.cgi/tech/1177988460/135
あたりのソースを通してみると面白いです。
% cat helloworld.bf
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
% awk -v optimize=1 -f bf2awk.awk < helloworld.bf
BEGIN {
ix = 0
st[ix] += 10
while (st[ix]) {
st[++ix] += 7
st[++ix] += 10
st[++ix] += 3
st[++ix]++
ix -= 4
st[ix]--
}
st[++ix] += 2
printf("%c", st[ix])
printf("%c", ++st[++ix])
st[ix] += 7
printf("%c", st[ix])
printf("%c", st[ix])
st[ix] += 3
printf("%c", st[ix])
st[++ix] += 2
printf("%c", st[ix])
ix -= 2
st[ix] += 15
printf("%c", st[ix])
printf("%c", st[++ix])
st[ix] += 3
printf("%c", st[ix])
st[ix] -= 6
printf("%c", st[ix])
st[ix] -= 8
printf("%c", st[ix])
printf("%c", ++st[++ix])
printf("%c", st[++ix])
}
% awk -v optimize=2 -f bf2awk.awk < helloworld.bf
BEGIN {
print "Hello World!"
}
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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | #
# Brainf*ck to AWK compiler, written in AWK by naoya_t/
#
BEGIN {
inst_buf = ""
ix = 0
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
inst_buf = inst_buf $0
}
END {
if (inst_buf ~ /,/) getchar_used = 1
# compile
if (optimize >= 1) reset_last()
output_buf = ""
indent = ""
print "BEGIN {"
indent_incr()
if (getchar_used) indent_print("read_buf = \"\"")
if (getchar_used || optimize < 2) indent_print("ix = 0")
diff_value[">"] = diff_value["+"] = 1
diff_value["<"] = diff_value["-"] = -1
incr_decr[">"] = incr_decr["+"] = "++"
incr_decr["<"] = incr_decr["-"] = "--"
N = split(inst_buf, ops, "")
eval(ops,1,N)
if (optimize >= 1) out_last()
flush_buf(0)
indent_decr()
indent_print("}")
if (getchar_used) output_getchar_funcs()
}
function eval(ops,begin,end, i,j,op,s,till)
{
for (i=begin; i<=end; i++) {
op = ops[i]
if (op ~ /[><]/) {
ix += diff_value[op] # emulation
if (optimize >= 1) {
if (last_inst == "ix") {
last_arg += diff_value[op]
} else {
out_last()
set_last("ix", diff_value[op])
}
} else {
if (getchar_used || optimize < 2) indent_print("ix" incr_decr[op])
}
} else if (op ~ /[+-]/) {
st[ix] += diff_value[op] # emulation
if (optimize >= 1) {
if (last_inst ~ /^st\[/) {
last_arg += diff_value[op]
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, diff_value[op])
}
} else {
if (getchar_used || optimize < 2) indent_print("st[ix]" incr_decr[op])
}
} else if (op == ".") {
s = "printf(\"%c\", st[ix])"
if (optimize >= 1) {
s = set_incr_decr(s)
if (last_inst) out_last()
}
if (getchar_used || optimize < 2)
indent_print(s)
else
putchar(st[ix])
} else if (op == ",") {
s = "st[ix] = getchar()"
if (optimize >= 1) {
s = set_incr_decr(s)
if (last_inst) out_last()
}
indent_print(s)
} else if (op == "[") {
nest = 1
for (j=i+1; j<=N; j++) {
if (ops[j] == "[") nest++
if (ops[j] == "]") nest--
if (nest == 0) { till = j ; break }
}
while_loop(ops, i+1, till-1)
i = till
} else {
;
}
}
}
function while_loop(ops,begin,end, i,j,putchar_used)
{
putchar_used = 0
for (j=begin; j<=end; j++) if (ops[j] == ".") { putchar_used = 1; break }
if (getchar_used || optimize < 2) {
out_last()
indent_print("while (st[ix]) {")
indent_incr()
eval(ops,begin,end)
if (optimize >= 1) out_last()
indent_decr()
indent_print("}")
} else {
while (st[ix]) eval(ops,begin,end)
}
}
function putchar(ch)
{
if (ch == 10 || ch == 13) {
flush_buf(1)
} else {
output_buf = output_buf sprintf("%c", st[ix])
}
}
function flush_buf(cr)
{
if (output_buf) {
gsub(/\\/, "\\\\", output_buf)
if (cr)
indent_print("print \"" output_buf "\"")
else
indent_print("printf(\"%s\", \"" output_buf "\")")
output_buf = ""
}
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff && (getchar_used || optimize < 2)) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
} else if (last_inst ~ /^st\[/ && s ~ /printf/) {
if (last_arg == 1) { gsub(/st\[ix\]/, "++" last_inst, s); last_inst = "" }
else if (last_arg == -1) { gsub(/st\[ix\]/, "--" last_inst, s); last_inst = "" }
}
return s
}
function output_getchar_funcs()
{
print "function getchar( ch)"
print "{"
print " if (read_buf ~ /^$/) {"
print " if (eof) return -1"
# print " if ((getline read_buf) < 1) { eof = 1; return -1 }"
print " if (getline != 1) { eof = 1; return -1 } ; read_buf = $0" # a2p
print " }"
print " ch = ord(substr(read_buf,1,1))"
print " read_buf = substr(read_buf,2)"
print " return ch"
print "}"
print "function ord(ch, ofs)"
print "{"
print " if (ch == \"\\t\") return 9"
print " if (ch == \"\\n\") return 13"
# print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)"
print " if (ch == \"@\") return 64" # a2p
print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?.ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)" # a2p
print " return ofs ? 31 + ofs : 0"
print "}"
}
|




dankogai
#3886()
Rating0/2=0.00
「どう書く?」でまだ出ていないのが不思議なお題。それがBF処理系。 ここでは、BFで書かれたソースを、同じ言語に変換するコンパイラーを募集します。
私自身、すでにPerlとJavaScriptに関しては http://blog.livedoor.jp/dankogai/archives/50545151.html でやっているのですが、他の言語バージョンも是非見たいので。
Dan the Brainf.ucker
see: Brainfuck - Wikipedia
1 reply [ reply ]