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 - 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--;") + "}}");
}
}
|





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 ]