Edited at

例のキヨシチェックを Sprache で書いてみる

More than 3 years have passed since last update.


はじめに

http://qiita.com/beinteractive/items/a2264048a601ee998aca

例の(?)が何だか解らないんですが、こういうのが上がってきたので、パーサの練習がてら書いてみました。


使ったもの

https://github.com/sprache/Sprache

C# の Monadic Parser だそうです。Monadic って Haskell で出てきたモナド的なヤツでしょうか。


できたもの


main.cs

using System;

using System.Collections.Generic;
using System.Text;
using Sprache;
using System.IO;

public class ZundokoGenerator {
Random _random = new Random();
public IEnumerator<string> RandomZunDoko() {
for (;;) {
yield return _random.Next(0, 2) == 0 ? "ズン" : "ドコ";
}
}
}

public static class KiyoshiParser {
public static readonly Parser<string> zun =
from txt in Parse.String("ズン").Text()
select txt;
public static readonly Parser<string> doko =
from txt in Parse.String("ドコ").Text()
select txt;
public static readonly Parser<string> zzzd =
from z0 in zun
from z1 in zun
from z2 in zun
from z3 in zun
from dk in doko
select "キヨシ";
}

class Program {
static void Main() {
var zdg = new ZundokoGenerator().RandomZunDoko();
var sb = new StringBuilder();
int count = 0;
for (;;) {
sb.Clear();
for (int i = 0; i < 5; ++i) {
zdg.MoveNext();
sb.Append(zdg.Current);
}
++count;
try {
var kys = KiyoshiParser.zzzd.Parse(sb.ToString());
Console.WriteLine(sb.ToString() + kys);
Console.WriteLine(count + "回ズンドコしました");
break;
}
catch (Sprache.ParseException) {
Console.WriteLine(sb.ToString());
}
}
}
}



解説


ZundokoGenerator

クラス ZundokoGenerator は元になった記事からパクってきましたが、実は UnityEngine.Random が使われていたので、 System.Random を使うように変更しました。

IEnumerator で、ズン or ドコを延々と返すだけですね。


KiyoshiParser

パーサ本体です。

文法についてはなんとなく見てもらえば解ると思いますが、 LINQ のクエリ構文で繋いでいく感じです。

詳しいところは Sprache のドキュメントをあたってもらった方がいいと思いますが、 bisonyacc でいうパターンを from の羅列で記述し、 select でアクションといった感じです。

注意する点は、 Parse.String() は返値が IEnumerator<char> (だっけ?)になっているので、 string に変換してやる必要があるところです。


Program

メインの処理です。

正しくないズンドコ(?)の際は例外で処理しています。


コンパイル&結果

% mcs main.cs -r:Sprache.dll ; mono main.exe

ドコズンズンズンズン
ズンズンズンズンズン
ドコドコズンドコズン
ドコズンドコズンズン
ドコズンズンドコズン
ドコドコズンドコズン
ズンドコドコズンズン
ドコズンドコドコズン
ズンドコズンズンドコ
ズンドコズンドコドコ
ズンドコドコズンズン
ドコドコズンドコズン
ズンドコドコズンドコ
ドコドコズンズンズン
ドコズンドコズンドコ
ドコズンズンズンズン
ズンドコドコドコズン
ズンズンズンズンドコキヨシ
18回ズンドコしました

簡単ですね('ω`)