Skip to content

コンパイル時パーサジェネレータ: ctpg

Hisayuki Mima edited this page Jan 19, 2014 · 11 revisions

ctpgは、D言語用の型付きパーサジェネレータライブラリです。生成されたパーサは再起下降構文解析を行います。

##目次

##特徴

  • PEGに似た、独自のDSLでパーサを定義する
  • コンパイル時にパーサを生成できる。裏を返すと、コンパイル時にしか生成できない
  • 生成されたパーサはコンパイル時にも実行時にも動作する
  • 実行時には解析結果をメモ化出来る
  • 生成されたパーサは、文字列だけでなく文字型を要素とするForwardRangeも入力として受け取れる
  • パーサの結果型がチェックされる

##導入方法 DUBを使うと簡単に導入できます。package.jsonに以下のdependenciesを追加します。

{
    "name": "your_project",
    "dependencies": {
        "ctpg": "~master"
    }
}

DUBについては、以下の記事が参考になります。

D言語でビルドツールDUBを用いて便利なライブラリをより簡単に利用する

##ドキュメント チュートリアル: 四則演算式

チュートリアル: JSON

DSLのリファレンス

既知のバグ

== 簡単な記法の紹介 = === 一つのパーサの定義 === 一つのパーサは、以下のように書くことによって定義することができます。

import ctpg;

mixin(generateParsers(q{
    string hoge = "hoge";
}));

このように、

型 名前 = パーサの定義 ;

という文法で定義し、この組み合わせでパーサを生成することができます。
この例では、"hoge"にマッチするパーサを定義したことになります。
定義されたパーサは、ctpg内で定義されたparse関数にテンプレート引数として渡すことによって、利用することができます。

import ctpg, std.algorithm, std.conv;

mixin(generateParsers(q{
    string hoge = "hoge";
}));

void main(){
    auto result = parse!hoge("hoge");
    // result.match には、hogeがマッチしたかどうかが代入される。
    assert(result.match);
    // result.value には、パーサが返した値が代入される。
    assert(result.value == "hoge");
}

入力として、stringだけでなく、wstringやdstring、文字型を要素とするForwardRangeを渡すこともできます。

import ctpg, std.algorithm, std.conv;

mixin(generateParsers(q{
    string hoge = "hoge";
}));

void main(){
    // wstring
    auto result1 = parse!hoge("hoge"w);
    assert(result1.match);
    // 入力の型が何であっても、hogeはstringの結果を返す。
    assert(result1.value == "hoge");

    // dstring
    auto result2 = parse!hoge("hoge"d);
    assert(result2.match);
    assert(result2.value == "hoge");

    // ForwardRange!char
    auto result3 = parse!hoge("hoge".map!(to!char));
    assert(result3.match);
    assert(result3.value == "hoge");
}

=== 複数のパーサの定義 === 以下のように、複数のパーサを定義することができます。

import ctpg;

mixin(generateParsers(q{
    string hoge = "hoge";
    string piyo = "piyo";
}));

void main(){
    assert(parse!hoge("hoge") == "hoge");
    assert(parse!piyo("piyo") == "piyo");
}

=== パーサを組み合わせる:連結 === 以下のように、パーサを並べて書くと、それらを連結させることができます。
連結したパーサの型は、それぞれのパーサの型のタプルとなります。

import ctpg;

mixin(generateParsers(q{
    Tuple!(string, string) hogepiyo = hoge piyo;
    string hoge = "hoge";
    string piyo = "piyo";
}));

void main(){
    assert(parse!hogepiyo("hogepiyo") == tuple("hoge", "piyo"));
}

=== パーサを組み合わせる:変換 === === その他 === == チュートリアル == == リファレンス == == 既知のバグ ==