Sprache を利用してキー名と値を抽出するパーサーを作成する - C#

Sprache を利用してキー名と値を抽出するパーサーのコードを紹介します。

プログラム1 (2つの値の抽出)

UI

下図のUIを作成します。Windows Formに複数行のTextBoxを2つ、Buttonを1つ配置します。

コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sprache;

namespace SimpleSprache
{
  public partial class FormKeyValueParse : Form
  {
    public class MyItem
    {
      public string key;
      public string value;

      public MyItem(string mkey, string mvalue)
      {
        key = mkey;
        value = mvalue;
      }
    }

    public static readonly Parser<MyItem> parse =  from lk in Parse.Letter.AtLeastOnce().Text().Token()
                                                   from lv in Parse.Letter.AtLeastOnce().Text().Token()
                                                   select new MyItem(lk, lv);

    public FormKeyValueParse()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string input = textBox1.Text;
      MyItem item = parse.Parse(input);
      textBox2.Text = string.Format("{0} : {1}", item.key, item.value);
    }
  }
}

解説

下記のコードにより、空白またはタブで区切られた2語を抽出します。抽出した語はMyItemオブジェクトのインスタンスとして返します。
  public static readonly Parser<MyItem> parse =  from lk in Parse.Letter.AtLeastOnce().Text().Token()
                                                 from lv in Parse.Letter.AtLeastOnce().Text().Token()
                                                 select new MyItem(lk, lv);

パーサーにより入力された文字列をパージングします。Parseメソッドは、MyItemオブジェクトを返します。戻り値の値をテキストボックスに表示します。
    private void button1_Click(object sender, EventArgs e)
    {
      string input = textBox1.Text;
      MyItem item = parse.Parse(input);
      textBox2.Text = string.Format("{0} : {1}", item.key, item.value);
    }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


上部のテキストボックスにパージングする文字列を入力します。今回は"Penguin Jump"の文字列を入力します。


[button1]をクリックします。下部のテキストボックスに、"Penguin"と"Jump"の値がコロンで区切られて表示されます。keyとvalueがそれぞれ抽出できていることが確認できます。

補足

ちなみに、valueの部分を数値にした場合、語句とみなされないため、例外が発生します。


Sprache.ParseException が発生します。

プログラム2 (値が「"」で囲まれている2つの値の抽出)

続いて、値が「"」で囲まれている場合の抽出コードを紹介します。

UI

下図のUIを作成します。Windows Formに複数行のTextBoxを2つ、Buttonを2つ配置します。Buttonは2つ配置されていますが、[button2]のみを利用します。

コード

下記のコードを記述します。(button2のクリックイベントを実装します。)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sprache;

namespace SimpleSprache
{
  public partial class FormKeyValueParse : Form
  {
    public class MyItem
    {
      public string key;
      public string value;

      public MyItem(string mkey, string mvalue)
      {
        key = mkey;
        value = mvalue;
      }
    }

    public static readonly Parser<string> p_key = Parse.Letter.AtLeastOnce().Text().Token();
    public static readonly Parser<string> p_value = (from open in Parse.Char('"')
                                                        from content in Parse.CharExcept('"').Many().Text()
                                                        from close in Parse.Char('"')
                                                        select content).Token();

    public static readonly Parser<MyItem> parse2 = from lk in p_key
                                                   from lv in p_value
                                                   select new MyItem(lk, lv);


    public FormKeyValueParse()
    {
      InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      string input = textBox1.Text;
      MyItem item = parse2.Parse(input);
      textBox2.Text = string.Format("{0} : {1}", item.key, item.value);

    }
  }
}

解説

下記のコードは、先の例の空白またはタブで区切られた2語を抽出するパーサーと似た形式の式です。ただし、"Parse.Letter.AtLeastOnce().Text().Token()"の部分が、p_keyとp_valueとなっています。取得した2つの値はMyItemオブジェクトのインスタンスとして返ります。
    public static readonly Parser<MyItem> parse2 = from lk in p_key
                                                   from lv in p_value
                                                   select new MyItem(lk, lv);

p_keyは下記の記述となっており、前後の空白を除去した1語を抽出するパーサーとなっています。
    public static readonly Parser<string> p_key = Parse.Letter.AtLeastOnce().Text().Token();

p_valueは下記の記述となっており、「"」で囲まれた内部の値を抽出するパーサーとなっています。
    public static readonly Parser<string> p_value = (from open in Parse.Char('"')
                                                        from content in Parse.CharExcept('"').Many().Text()
                                                        from close in Parse.Char('"')
                                                        select content).Token();

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


上部のテキストボックスにパージングするテキストを入力します。今回は "Penguin "Jump"" を入力します。


[button2]をクリックします。下部のテキストボックスに "Penguin" と "Jump" がコロンで区切られて表示されました。Jumpを囲んでいた「"」も取り除かれて抽出できています。


同様に「Duck "8650"」でも動作確認します。


"Duck"と"8650"がコロンで区切られ表示されており、keyとvalueにパージングできていることが確認できました。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2018-01-09
iPentec all rights reserverd.