challenge BFコンパイラー

「どう書く?」でまだ出ていないのが不思議なお題。それがBF処理系。 ここでは、BFで書かれたソースを、同じ言語に変換するコンパイラーを募集します。

私自身、すでにPerlとJavaScriptに関しては http://blog.livedoor.jp/dankogai/archives/50545151.html でやっているのですが、他の言語バージョンも是非見たいので。

Dan the Brainf.ucker

以下のように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 - C#

お題を見て「BF→言語Aへのトランスレータを言語Aで製作する」のだと思ったんですけど、お手本見るとなんかちょっと違う感じがしたので全部やってみました (^-^;; BF ソースファイルから 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
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);
    }
}

Wikipedia と dankogai さんの実装を見つつ、C# で書いてみました。誰か添削してくださいw
  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
using System;
using System.Collections.Generic;

namespace Kinoko
{
    /*
        BrainF*ck
    */
    class Program
    {
        public static void Main(string[] args)
        {
            LinkedList<int> Tape = new LinkedList<int>();
            Tape.AddLast(0);
            LinkedListNode<int> Head = Tape.First;

            for(int i=0; i < args[0].Length; i++)
            {
                String op = args[0].Substring(i,1);
                switch(op)
                {
                    case "+":
                    {
                        Head.Value++;
                        break;
                    }
                    case "-":
                    {
                        Head.Value--;
                        break;
                    }
                    case "<":
                    {
                        if(Head == Tape.First)
                        {
                            Tape.AddFirst(0);
                        }
                        Head=Head.Previous;
                        break;
                    }
                    case ">":
                    {
                        if(Head == Tape.Last)
                        {
                            Tape.AddLast(0);
                        }
                        Head=Head.Next;
                        break;
                    }
                    case "[":
                    {
                        if(Head.Value == 0)
                        {
                            int nest = 1;
                            int step = 1;
                            while(nest > 0)
                            {
                                if(args[0].Substring(i+step, 1) == "[")
                                {
                                    nest++;
                                }
                                else if(args[0].Substring(i+step, 1) == "]")
                                {
                                    nest--;
                                }
                                step++;
                                if(i+step > args[0].Length)
                                {
                                    break;
                                }
                            }
                            i += step;
                        }
                        break;
                    }
                    case "]":
                    {
                        if(Head.Value != 0)
                        {
                            int nest = 1;
                            int step = 1;
                            while(nest > 0)
                            {
                                if(args[0].Substring(i-step, 1) == "]")
                                {
                                    nest++;
                                }
                                else if(args[0].Substring(i-step, 1) == "[")
                                {
                                    nest--;
                                }
                                step++;
                                if(i-step < 0)
                                {
                                    break;
                                }
                            }
                            i -= step;
                        }
                        break;
                    }
                    case ".":
                    {
                        Console.Write("{0}", ((Char)Head.Value));
                        break;
                    }
                    case ",":
                    {
                        int input = 0;
                        Console.Write("input:");
                        input = Console.Read();
                        Head.Value = input;
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }
        }
    }
}

unsafeを使って、 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
using System;
using System.IO;

namespace BrainFuck
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamWriter sw = new StreamWriter("C:\\txt.txt");

            sw.WriteLine("using System;");
            sw.WriteLine("namespace BrainFuck{");
            sw.WriteLine("class Program{");
            sw.WriteLine("unsafe static void Main(string[] args){");
            sw.WriteLine("fixed (byte* b = new byte[1024]){");
            sw.WriteLine("byte* ptr = b;");

            foreach (char s in args[0])
            {
                switch (s)
                {
                    case '>':
                        sw.WriteLine("ptr++;");
                        break;
                    case '<':
                        sw.WriteLine("ptr--;");
                        break;
                    case '+':
                        sw.WriteLine("(*ptr)++;");
                        break;
                    case '-':
                        sw.WriteLine("(*ptr)--;");
                        break;
                    case '.':
                        sw.WriteLine("Console.Write((char)*ptr);");
                        break;
                    case ',':
                        sw.WriteLine("*ptr = Console.Read();");
                        break;
                    case '[':
                        sw.WriteLine("while(*ptr != 0){");
                        break;
                    case ']':
                        sw.WriteLine("}");
                        break;
                }
            }

            sw.WriteLine("}}}}");
            sw.Close();
        }
    }
}

なんか弄ってたら得体の知れないものに……w
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--;") + "}}");
    }
}

Index

Feed

Other

Link

Pathtraq

loading...