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 - Nested
Flatten Hiddenひさびさの一番かな? 入力を文字列にしたい場合なんかは Console.withInを使うとできます。
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 | import scala.io.Source.fromFile
object BF{
def main(args:Array[String]) = {
if(args.size == 0) print("scala BF [sourcecode filename]")
else
args.foreach{f=> (new Machine).interpret(fromFile(f).mkString("")) }
}
}
object Machine {
final val MEM = 0xffffff
final val VAL = 0xff
}
class Machine{
var _p = 0
val _mem = new Array[int](Machine.MEM)
def p_=(v:int) = _p = v&Machine.MEM
def p = _p
def mem_=(v:int) = _mem(p)=v&Machine.VAL
def mem = _mem(p)
def abort = error("Missing corresponding parenthesis.")
def interpret(code:String):unit = interpret(code.toArray)
def interpret(code:Array[char]):unit = {
val (s,m) = ((List[int](), List[(int,int)]()) /: code.zipWithIndex){
(r,c) => c._1 match {
case '[' => (c._2::r._1, r._2)
case ']' => r._1 match {
case x::xs => (xs, (x,c._2)::(c._2,x)::r._2)
case _ => abort
}
case _ => r
}}
if(s.size > 0) abort
val parenMap = Map(m:_*)
var i = -1;while({i=i+1;i<code.size}) code(i) match {
case '>' => p = p+1
case '<' => p = p-1
case '+' => mem = mem+1
case '-' => mem = mem-1
case '.' => print(mem.asInstanceOf[char])
case ',' => mem = readChar.asInstanceOf[int]
case '[' if mem == 0 => i = parenMap(i)
case ']' if mem != 0 => i = parenMap(i)
case _ => ()
}
}
}
|
題意を読み間違えてたので。 こっちのほうがかなり楽です。
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 | import scala.io.Source.fromFile
object BFC{
def main(args:Array[String]) = {
if(args.size == 0){
println("Usage:scala BFC [sourcecode filename]")
}else{
println("""
object Machine {
final val MEM = 0xffffff
final val VAL = 0xff
}
class Machine{
var _p = 0
val _mem = new Array[int](Machine.MEM)
def p_=(v:int) = _p = v&Machine.MEM
def p = _p
def mem_=(v:int) = _mem(p)=v&Machine.VAL
def mem = _mem(p)
def eval = {
""")
val code = fromFile(args(0)).mkString("").toList
if(code.count('['==_) != code.count(']'==_)) {
error("Missing corresponding parenthesis.")
}
code.foreach(c=>println(c match {
case '>' => "p = p+1"
case '<' => "p = p-1"
case '+' => "mem = mem+1"
case '-' => "mem = mem-1"
case '.' => "print(mem.asInstanceOf[char])"
case ',' => "mem = readChar.asInstanceOf[int]"
case '[' => "while(mem != 0){"
case ']' => "}"
case _ => ""
}))
println("}};(new Machine).eval;")
}
}
}
|
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 | using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.CSharp;
static class BFCompiler {
public static void Main(String[] args) {
if (0 < args.Length && File.Exists(args[0])) {
using(StringWriter sw = new StringWriter())
using(StreamReader sr = new StreamReader(args[0])) {
Stack<string> labels = new Stack<string>();
int label_num = 0;
sw.WriteLine("using System; static class BF {");
sw.WriteLine("public static void Main() {");
sw.WriteLine("byte[] m = new byte[256]; int p = 0;");
foreach(char c in sr.ReadToEnd()) {
switch(c) {
case '+': sw.WriteLine("m[p]++;"); break;
case '-': sw.WriteLine("m[p]--;"); break;
case '>': sw.WriteLine("p++;"); break;
case '<': sw.WriteLine("p--;"); break;
case '.': sw.WriteLine("Console.Write((char)m[p]);"); break;
case ',': sw.WriteLine("m[p] = (byte)Console.Read();"); break;
case '[': {
string ll = "L" + (label_num++);
labels.Push(ll);
sw.WriteLine("if (m[p] == 0) goto {0}_END;", ll);
sw.WriteLine("{0}_START:;", ll);
break;
}
case ']': {
string ll = labels.Pop();
sw.WriteLine("if (m[p] != 0) goto {0}_START;", ll);
sw.WriteLine("{0}_END:;", ll);
break;
}
}
}
sw.WriteLine("}}");
Generate(Path.GetFileNameWithoutExtension(args[0]), sw.ToString());
}
}
else {
Console.WriteLine("usage: bfc [sourcefile]");
}
}
private static void Generate(string filename, string cs_code) {
// ソースファイル生成
using (StreamWriter sw = new StreamWriter(filename + ".cs")) {
sw.Write(cs_code);
}
// 実行ファイル生成
CompilerParameters param = new CompilerParameters();
param.OutputAssembly = filename + ".exe";
param.GenerateExecutable = true;
CompilerResults rs = new CSharpCodeProvider().CompileAssemblyFromSource(param, cs_code);
// 実行
rs.CompiledAssembly.GetType("BF").GetMethod("Main").Invoke(null, null);
}
}
|
>お題を見て「BF→言語Aへのトランスレータを言語Aで製作する」のだと思ったんですけど
それであっていると思いますよ。お手本は 「Language::BF->new_from_file(shift)->as_perl」というコードで「t/hello.bf」というBrainf*ckで書かれたコードを読んでPerlに変換し、その出力をさいごの「| perl」でもう一度Perlに食わせて実行させているわけです。
perl -MLanguage::BF \ -e 'print Language::BF->new_from_file(shift)->as_perl' t/hello.bf \ | perl Hello World!
SiroKuroさんがおっしゃっているお手本は http://blog.livedoor.jp/dankogai/archives/50545151.html のほうだと思います。投稿時間を見てみるとわかります。 僕もURLの方だけみて勘違いしてました・・・ 今から書き直します(^^;
はっきりしなくてごめんなさい。にしおさんが言う通り。
コンパイラー(トランスレーター)
BF ====> 言語A
言語A
というのが本来の趣旨で、そしてBFの場合こちらの方が
インタープリター(ランタイム)
BF => 言語Aで書かれた実行環境
よりもずっと実装が簡単なので。
ちなみにLanguage::BFはどちらの機能も持っています。
Dan the Brainf.cker
1 2 3 4 5 6 7 | using System;
using System.IO;
static class BFCompiler {
public static void Main(String[] args) {
Console.WriteLine(0 == args.Length || !File.Exists(args[0]) ? "usage: bfc [sourcefile]" : "using System;static class BF{static void Main(){byte[]m=new byte[256];int p=0;" + new StreamReader(args[0]).ReadToEnd().Replace("]","}").Replace("[","while(m[p]!=0){").Replace(".","Console.Write((char)m[p]);").Replace(",","m[p]=(byte)Console.Read();").Replace("+","m[p]++;").Replace("-","m[p]--;").Replace(">","p++;").Replace("<","p--;") + "}}");
}
}
|
ひねり無し。 python bf.py -o hello.py hello.bf みたいな感じで使います。
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 | import sys
from getopt import getopt
def encode(bfcode):
depth = code = 0
pycode = []
stack = []
f = file(default['-o'], 'w')
pycode.append('import sys')
pycode.append('tape, ptr, code = {}, 0, 0')
while code != len(bfcode):
c = bfcode[code]
if c == '>':
pycode.append('\t' * depth + 'ptr += 1')
elif c == '<':
pycode.append('\t' * depth + 'ptr -= 1')
elif c == '+':
pycode.append('\t' * depth + 'tape[ptr] = tape.get(ptr, 0) + 1')
elif c == '-':
pycode.append('\t' * depth + 'tape[ptr] = tape.get(ptr, 0) - 1')
elif c == ',':
pycode.append('\t' * depth + 'tape[ptr] = sys.stdin.read(1)')
elif c == '.':
pycode.append('\t' * depth + 'sys.stdout.write(chr(tape.get(ptr, 0)))')
elif c == '[':
pycode.append('\t' * depth + 'while tape.get(ptr, 0):')
stack.append(depth)
depth += 1
elif c == ']':
depth = stack.pop()
code += 1
file(default['-o'], 'w').write('\n'.join(pycode))
if __name__ == '__main__':
default = {'-o': 'a.py'}
optlist, args = getopt(sys.argv[1:], 'o:', [])
if args:
default.update(optlist)
encode(''.join(file(args[0]).readlines()))
|
自己ツッコミ。 このままだと"~[]~" のようなBFコードがあった際にwhile文のところで文法エラーを起こすので、 ']'が出た時にはpassをダミーで放り込んだ方がよさそうです。 あと、最初間違えてインタプリタを書いてしまった名残で変なやり方になっていました。
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 | def encode(bfcode):
- depth = code = 0
+ depth = 0
pycode = []
stack = []
f = file(default['-o'], 'w')
pycode.append('import sys')
- pycode.append('tape, ptr, code = {}, 0, 0')
+ pycode.append('tape, ptr = {}, 0')
- while code != len(bfcode):
- c = bfcode[code]
+ for c in bfcode:
if c == '>':
pycode.append('\t' * depth + 'ptr += 1')
elif c == '<':
pycode.append('\t' * depth + 'ptr -= 1')
elif c == '+':
pycode.append('\t' * depth + 'tape[ptr] = tape.get(ptr, 0) + 1')
elif c == '-':
pycode.append('\t' * depth + 'tape[ptr] = tape.get(ptr, 0) - 1')
elif c == ',':
pycode.append('\t' * depth + 'tape[ptr] = sys.stdin.read(1)')
elif c == '.':
pycode.append('\t' * depth + 'sys.stdout.write(chr(tape.get(ptr, 0)))')
elif c == '[':
pycode.append('\t' * depth + 'while tape.get(ptr, 0):')
stack.append(depth)
depth += 1
elif c == ']':
+ pycode.append('\t' * depth + 'pass')
depth = stack.pop()
- code += 1
|
これまたifの羅列をHashに置き換え。ただし、pythonの場合、[]は少し特別扱いが必要。こちらはindent不要とは行かないので。
あと、関数名やインターフェースも好みにあわせて変えました。
Dan the Novice Snake Tamer
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 | #!/usr/bin/env python
import sys
from getopt import getopt
def bf2py(bfcode):
depth = 0
opcode = {
'>':'ptr += 1',
'<':'ptr -= 1',
'+':'tape[ptr] = tape.get(ptr, 0) + 1',
'-':'tape[ptr] = tape.get(ptr, 0) - 1',
',':'tape[ptr] = sys.stdin.read(1)',
'.':'sys.stdout.write(chr(tape.get(ptr, 0)))',
'[':'while tape.get(ptr, 0):',
']':'pass'
}
pycode = []
stack = []
pycode.append('import sys')
pycode.append('tape, ptr = {}, 0')
for c in bfcode:
if opcode.has_key(c):
pycode.append( '\t' * depth + opcode[c])
if c == '[':
stack.append(depth)
depth += 1
elif c == ']':
depth = stack.pop()
return '\n'.join(pycode)
if __name__ == '__main__':
defout = 'a.py'
optlist, args = getopt(sys.argv[1:], 'o:', [])
if args:
pysrc = bf2py(''.join(file(args[0]).readlines()));
file(defout or ops['-o'], 'w').write(pysrc)
|
せっかくなので++++がbf.inc(4)に置き換わるような設計にしてみました。
この程度の規模なら正規表現でも十分いけるんじゃないかと思いつつ勉強がてらにlexとyaccを使いました。
PLY (Python Lex-Yacc)
あとインデントうんぬんを考慮しないといけないのはそもそも直接while文を使うからなので式で表現しました。
,+[-.,+]を入力するとbf.get()or bf.inc(1)or bf.loop(lambda: bf.inc(-1)or bf.put()or bf.get()or bf.inc (1))と出力されます。
下のFizzBuzzコードを食わせると2638バイトの出力で、処理時間はあっという間でした。 http://d.hatena.ne.jp/n_shuyo/20070516/fizzbuzz
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 | from ply import lex, yacc
import sys
# lex
tokens = "PLUS MINUS LEFT RIGHT WHILE WEND PUT GET COMMENT".split()
t_WHILE = "\["
t_WEND = "]"
t_PUT = "\."
t_GET = ","
def t_PLUS(t):
"\++"
t.value = len(t.value)
return t
def t_MINUS(t):
"-+"
t.value = len(t.value)
return t
def t_LEFT(t):
"<+"
t.value = len(t.value)
return t
def t_RIGHT(t):
">+"
t.value = len(t.value)
return t
def t_COMMENT(t):
'[^[\]><+-,.]' # return nothing
def t_error(t): pass
# yacc
"""*** grammar definition
sequence : sequence command
| command
command : PLUS
| MINUS
| LEFT
| RIGHT
| PUT
| GET
| loop
loop : WHILE sequence WEND
"""
def p_sequence(p):
"sequence : sequence command"
p[0] = p[1] + "or " + p[2]
def p_sequence_command(p):
"sequence : command"
p[0] = p[1]
def p_command_PLUS(p):
"command : PLUS"
p[0] = "bf.inc(%s)" % p[1]
def p_command_MINUS(p):
"command : MINUS"
p[0] = "bf.inc(%s)" % -p[1]
def p_command_LEFT(p):
"command : LEFT"
p[0] = "bf.mov(%s)" % -p[1]
def p_command_RIGHT(p):
"command : RIGHT"
p[0] = "bf.mov(%s)" % p[1]
def p_command_PUT(p):
"command : PUT"
p[0] = "bf.put()"
def p_command_GET(p):
"command : GET"
p[0] = "bf.get()"
def p_command_loop(p):
"command : loop"
p[0] = p[1]
def p_loop(p):
"loop : WHILE sequence WEND"
p[0] = "bf.loop(lambda: %s)" % p[2]
def p_error(p): pass
# input and parse
data = sys.stdin.read()
lex.lex()
yacc.yacc()
result = yacc.parse(data)
# output
print """
from collections import defaultdict
import sys
class BF(object):
mem = defaultdict(int)
cur = 0
def inc(self, n):
self.mem[self.cur] += n
self.mem[self.cur] %= 256
def mov(self, n):
self.cur += n
def put(self):
c = chr(self.mem[self.cur])
sys.stdout.write(c)
def get(self):
c = sys.stdin.read(1)
self.mem[self.cur] = ord(c)
def loop(self, seq):
while self.mem[self.cur]:
seq()
bf = BF()
"""
print result
|
素数探索のコード:
http://labs.cybozu.co.jp/blog/kazuho/archives/2006/06/bf_prime.php
さすがに結構時間がかかるなー。Core2Duo @2.4GHzで1分くらい。
real 1m2.317s user 0m0.015s sys 0m0.031s
8行修正して[-]を単体で「リセット命令」にしたらreal 0m54.380sになった。
うーん、これ以上高速化するとなるとコピーの処理を置き換えるとかになりそうだけど、それは正規表現では無理な気がするなぁ。パースしながら出力文字列を作るのをやめて、sequenceを文字列に変換する際にmovとincだけで構成されているかどうかをチェックして…となるのかな。面倒だな。
Pythonだとこれだけ時間がかかるんですね。 参考になります。 Scalaでもやってみたところ、#3960のコードで 出力したものを、コンパイルせずインタプリタで 実行しても1秒以内に結果が出ました。 Scalaは実はできる子です(笑
うーん、それはちょっと違いますね。 #3960のコードはコードを一つの関数の中にローカルに展開しているのに対して、上のコードは一つ一つの命令がメソッド呼び出しですから。PythonとScalaの性能の違いと言うより、生成されたコードの質の違い思います。
# 要するに僕のコードが生成したのは質が悪いと!orz
毎回bf.fooとメソッド名の解決をしているのをやめるとreal:0m32.481sになり、きちんとインデントするようにしたら(毎回関数呼び出しをするのをやめたら)real:0m15.548sになりました。
それでもScalaには全然追いつかないのか…orz
コードを張り忘れたので。
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 | def p_sequence(p):
"sequence : sequence command"
p[0] = p[1] + p[2]
def p_sequence_command(p):
"sequence : command"
p[0] = p[1]
def p_command_PLUS(p):
"command : PLUS"
p[0] = "\nmem[cur] = (mem[cur] + %s) %% 256" % p[1]
def p_command_MINUS(p):
"command : MINUS"
p[0] = "\nmem[cur] = (mem[cur] - %s) %% 256" % p[1]
def p_command_LEFT(p):
"command : LEFT"
p[0] = "\ncur -= %s" % p[1]
def p_command_RIGHT(p):
"command : RIGHT"
p[0] = "\ncur += %s" % p[1]
def p_command_PUT(p):
"command : PUT"
p[0] = "\nsys.stdout.write(chr(mem[cur]))"
def p_command_GET(p):
"command : GET"
p[0] = "\nmem[cur] = ord(sys.stdin.read(1))"
def p_command_RESET(p):
"command : RESET"
p[0] = "\nmem[cur] = 0"
def p_command_loop(p):
"command : loop"
p[0] = p[1]
def p_loop(p):
"loop : WHILE sequence WEND"
p[0] = "\nwhile mem[cur]:%s" % p[2].replace("\n", "\n ")
def p_error(p): pass
# input and parse
data = sys.stdin.read()
lex.lex()
yacc.yacc()
result = yacc.parse(data)
# output
print """
from collections import defaultdict
import sys
mem = defaultdict(int)
cur = 0
"""
print result
|
あ、確かにそうですね。見落としてました。 せっかくなので#3952の素朴なタイプでも手元で時間とって見ましたが、 dppさんの#3952:55秒程度 にしおさんの#3988:2分10秒程度 でした。 あと、メモリとしてdictを使っているけど、 [0]*0xffffみたいにリストで長さ決めうちにすると だいぶマシですね。55 -> 31秒程度まで短縮できました。
これ
tape[ptr] = sys.stdin.read(1)
の部分でordしていないのでテープに文字列が書き込まる気が。
簡単の為、標準出力を使用。
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 | #include <stdio.h>
#include <stdlib.h>
int main(int arg_c, char **arg_v) {
FILE *fp;
int c;
if (*++arg_v == NULL) {
fprintf(stderr, "usage: bfc [source file]\n");
exit(EXIT_FAILURE);
}
if ((fp = fopen(*arg_v, "r")) == NULL) {
fprintf(stderr, "file open error.\n");
exit(EXIT_FAILURE);
}
puts("#include <stdio.h>");
puts("#include <stdlib.h>");
puts("int main(void) {");
puts(" char *s, *p;");
puts(" p = s = (char *)calloc(1024, 1);");
while ((c = getc(fp)) != EOF) {
switch (c) {
case '>': puts(" ++p;"); break;
case '<': puts(" --p;"); break;
case '+': puts(" ++*p;"); break;
case '-': puts(" --*p;"); break;
case '.': puts(" putchar(*p);"); break;
case ',': puts(" *p = getchar();"); break;
case '[': puts(" while (*p) {"); break;
case ']': puts(" }"); break;
default: break;
}
}
puts(" free(s);");
puts("}");
fclose(fp);
}
|
./bf2c hello.bf > hello.c
または
./bf2c hello.bf 128 > hello.c
のように使います。
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 | #include <stdio.h>
#include <stdlib.h>
char *code[] = { "sp++;", "sp--;", "(*sp)++;", "(*sp)--;", "putchar(*sp);",
"*sp = getchar();", "while(*sp){", "}" };
int main( int argc, char *argv[] ){
int c,i,j,n=0;
int indent = 1;
int length;
FILE *fp;
if( argc < 2 ){
fprintf(stderr,"Usage: %s sourcefile\n", argv[0] );
return EXIT_FAILURE;
}
if( (fp = fopen( argv[1], "r" )) == NULL ){
fprintf(stderr,"Error: %s cannot opened\n", argv[1] );
return EXIT_FAILURE;
}
if( !argv[2] || (length = atoi( argv[2] )) <= 0 ){
length = 256;
}
puts("#include <stdio.h>");
puts("#include <stdlib.h>");
printf("#define DATA_LEN %d\n", length);
puts("char code[DATA_LEN];");
puts("int main (void){");
puts(" char *sp = code;");
while( (c=fgetc( fp )) != EOF ){
switch(c){
case '>': i = 0; break;
case '<': i = 1; break;
case '+': i = 2; break;
case '-': i = 3; break;
case '.': i = 4; break;
case ',': i = 5; break;
case '[': i = 6; indent++; break;
case ']': i = 7; indent--; break;
default:
/* skip other characters */
continue;
}
for( j = 0; j < (indent+(i==6?-1:0)); j++ ){
printf(" ");
}
printf("%s\n", code[i] );
}
puts(" return EXIT_SUCCESS;");
puts("}");
fclose(fp);
return EXIT_SUCCESS;
}
|
ケースが嫌いな私は、以下のように書き換えてしまいました。機能的には#3955と互換ですが、出力されたCコードのコンパイルには差し支えないのでインデントは省略しました。
Dan the Brainf.cker
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 | #include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ){
int c;
char *code[256];
int length;
FILE *fp;
if( argc < 2 ){
fprintf(stderr,"Usage: %s sourcefile\n", argv[0] );
return EXIT_FAILURE;
}
if( (fp = fopen( argv[1], "r" )) == NULL ){
fprintf(stderr,"Error: %s cannot opened\n", argv[1] );
return EXIT_FAILURE;
}
if( ! |




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 ]