読者です 読者をやめる 読者になる 読者になる
ようこそ。睡眠不足なプログラマのチラ裏です。

さっそくC#でプログラム言語「てってってー」のインタプリタを書いたよ

プログラミング C#2.0 C#3.0 てってってー

何かを受信(^o^)ノ


プログラム言語「てってってー」
javascript - てってってー言語を移植してみた - 404 Blog Not Found
Wikipedia - Brainf*ck



というわけで、C#erな自分はC#で「てってってー言語」のインタプリタを書いてみました。
基本「Brainf*ck」のモシャスということで、決して難しい内容ではありません。
時間の都合上真面目にやるのは面倒くさいので、細かいところが本家の仕様と
若干異なっちゃっていたりしますが、ご了承ください(・ω・)


まずは、プログラミング言語「てってってー」仕様から


本家をご参照ください → プログラム言語「てってってー」


てってってーインタプリタC#による実装

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    /// <summary>
    /// てってってーインタプリタ
    /// </summary>
    public sealed class Tettettee
    {
        private const int memorySize = 65535; 
        private string _source;

        public Tettettee(string source) 
        {
            _source = source;
        }

        /// <summary>
        /// 分析
        /// </summary>
        /// <returns></returns>
        private string[] Analyze()
        {
            //フィルタリング
            _source = new Regex(@"[\s]*\{[^\}]+\}").Replace(_source, "");

            //分析用の正規表現
            var rx = new Regex(@"ー.*?てー|ててー|てっー|てってー|てっててー|てってっー|てってってー|てってっててー|てってってっー");

            var list = new List<string>();
            foreach (Match m in rx.Matches(_source)) 
                list.Add(m.ToString());
            return list.ToArray();
        }

        /// <summary>
        /// てってってー♪
        /// </summary>
        public unsafe void Run() 
        {
            var array = Analyze();

            char* point = stackalloc char[memorySize];

            for (int i = 0; i < array.Length; i++)
            {
                switch (array[i])
                {
                    case "ててー": //Brainf*ckで言うところの「+」
                        (*point)++;
                        break;
                    case "てっー": //Brainf*ckで言うところの「-」
                        (*point)--;
                        break;
                    case "てってー": //Brainf*ckで言うところの「>」 
                        point++;
                        break;
                    case "てっててー": //Brainf*ckで言うところの「<」
                        point--;
                        break;
                    case "てってっー": //Brainf*ckで言うところの「.」やったあと「>」 
                        Console.Write(*point);
                        point++;
                        break;
                    case "てってってー": //Brainf*ckで言うところの「,」やったあと「>」
                        *point = ((char)Console.Read());
                        point++;
                        break;
                    case "てってっててー": //Brainf*ckで言うところの「[」
                        if (*point == 0) i = Loop(array, i);
                        break;
                    case "てってってっー"://Brainf*ckで言うところの「]」
                        if (*point != 0) i = Loop(array, i);
                        break;
                    default: //「ー」に一致
                        //てってってー言語の独自仕様
                        char[] ar = array[i].ToString().Substring(1, array[i].Length - 3).ToCharArray();
                        fixed (char* cp = ar)
                        {
                            for (var j = 0; j < ar.Length; j++)
                            {
                                *point = cp[j];
                                point++;
                            }
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// てってってーなループを表現します。
        /// </summary>
        /// <param name="source"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private static int Loop(string[] source, int index)
        {
            int nest = default(int);
            bool flag = source[index] == "てってっててー";
            for (var i = index; flag ? i < source.Length : i >= 0; i = i + (flag ? 1 : -1))
            {
                if (source[i] == "てってっててー") nest++;
                else if (source[i] == "てってってっー") nest--;
                if (nest == 0) return i;
            }
            return -1;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string filename = args[0];

            var sb = new StringBuilder();
            foreach (var line in Lines(filename))
                sb.Append(line);

            new Tettettee(sb.ToString()).Run();
            Console.ReadLine();
        }

        private static IEnumerable<string> Lines(string path)
        {
            using (System.IO.StreamReader sr = new System.IO.StreamReader(path, Encoding.GetEncoding("Shift-Jis")))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                    yield return line;
            }
        }
    }
}


てってってーのコード

{「てってってーてってっててー」と出力するプログラム}

ーてってってー {「てってっ」をメモリに書き込む}
てっててーてっててーてっててーてっててー {ポインタを4つ戻す}
てってっーてってっーてってっーてってっー {標準出力へ4文字出力する}
ーててーてっててーてってっー {「て」をメモリに書き込み、ポインタを戻してから標準出力へ出力する}

ーーてってっててー {「ーてってって」をメモリに書き込む}
てっててーてっててーてっててーてっててーてっててーてっててー {ポインタを6つ戻す}
てってっーてってっーてってっーてってっーてってっーてってっー {標準出力へ6文字出力する}
ーててーてっててーてってっー {「て」をメモリに書き込み、ポインタを戻してから標準出力へ出力する}
ーーてーてっててーてってっー {「ー」をメモリに書き込み、ポインタを戻してから標準出力へ出力する}

本家より転載させていただきますた。

実行結果

てってってーてってっててー


D


てってってーてってっててー♪ m9(^Д^)プギャーーーッ
てってってーてってっててー♪ m9(^Д^)プギャーーーッ
てってってーてってっててー♪ m9(^Д^)プギャーーーッ


ネタに便乗するというのも、なかなか楽なもんじゃありません。
お疲れさまでした。