-
Notifications
You must be signed in to change notification settings - Fork 2
コンパイル時パーサジェネレータ: 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を用いて便利なライブラリをより簡単に利用する
##ドキュメント チュートリアル: 四則演算式
== 簡単な記法の紹介 = === 一つのパーサの定義 === 一つのパーサは、以下のように書くことによって定義することができます。
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"));
}
=== パーサを組み合わせる:変換 === === その他 === == チュートリアル == == リファレンス == == 既知のバグ ==