caperが出力するパーサの特徴
modernなC++コードを出力する。
- パーサはテンプレートクラス。
- テンプレート引数はノードの値の型とセマンティックアクション定義クラス(see Tutorial)。
- セマンティックアクションのコードが分離されるので、ひとつの文法を複数の用途に利用可能。
- 入力文法ファイルで記号の型を明示するため、セマンティックアクションがタイプセーフ。
- パーサクラスは文法解析以外ほとんど何もしないシンプルなもの。
- parserのpublicメンバ関数は4つ(
reset
,post
,accept
,error
)だけ。 - テンプレート対応がまっとうなら、基本的にどんな環境でも使用可能なはず(gcc3.4、VS2005で確認)。
Lemonと同様のプッシュ型パーサ。
- パーサインスタンスにトークンを
post
するまで何もしない。 - 従ってスキャナ(との連携)という概念はない。
- 途中放棄可能。不要になった時点でデストラクトしても何ら悪影響はない。
- パーサインスタンスのメモリ割り当て場所はヒープでもスタックでもよい。
- サスペンド/レジュームも自由(ポストしなければ動かないだけだから)。
出力ファイルはhppファイル一つだけ。
- 他のファイルは一切不要。
- ライブラリのリンクは必要ない。
- caperが提供するヘッダのincludeも必要ない(caperはヘッダを提供しない)。
- caperの出力したパーサはライセンス的に「文法を書いた人が書いた」とみなしてOK
- 「手書きですよ?」としらばっくれて配布してもOK
- インクルードする標準ヘッダは
<cassert>, <cstdlib>, <vector>
だけ(<vector>
はSTLオンのときのみ)。
グローバル変数・スタティック変数を一切使わないクリーンな設計。
- パーサのインスタンス単位でスレッドセーフ。
- ひとつのインスタンスを複数スレッドから使いたい場合は自分で排他制御してください。
- 1スレッドで複数のパーサインスタンスを持って、別々の用途に使っても問題ない。
- 1スレッドで複数の文法の異なるパーサを持っても問題ない。
- 関連要素を一つの名前空間(ユーザ指定可能)にまとめるので、1実行ファイル中に複数の文法を持つことも気軽にできる。
- 基本的にメモリの動的確保を行わない。
- ただし内部スタックにSTLを用いる場合(デフォルトで使用、オプションで変更可能)は例外
例外に対して堅牢。SemanticAction内で例外を発生させてもOK。
- わざとハマりやすい文法を受理するようにして、その中で例外を発生させるようにすればエラー処理も簡単。
- 詳細は後述
- パーサ自体は例外を発生させない。
- 従って例外オフでも使用可能。
- スタックにSTLを使う場合、それが例外を発生させる可能性はある。
- パーサ内部では実行時型判定も行わない。
- 従ってRTTIオフでも使用可能。
性能はまあまあ(だと思う)
- アルゴリズム上可能で上記設計に反しない最適化は施してある。
- マシンアーキテクチャに依存する最適化や上記設計に反するような最適化は行っていない。
- テーブルはおおむね
switch
に展開するので、C++コンパイラの最適化性能次第。 - まあ、現代の状況ではパーサに超絶的パフォーマンスを求められることはないでしょう。
無責任・無保証
caperの特徴
シンプルな入力ファイル
- セマンティックアクションを外部に記述する設計のため、ターゲット文法ファイルはほぼ文法だけで構成される。
タイプセーフ
- トークンに型を与えることができる。
- 非終端記号(文法規則の左側に登場するシンボル)には型を設定しなければならない。
- 以上の決まりを用いて、文法規則の右側でセマンティックアクションに使うものを型チェックすることができる。
動的文法生成インターフェイス、動的解釈テーブル構築エンジン
- caper自身の入力ファイルの文法の解釈には、このエンジンが用いられている。
- ターゲット文法は、いったん内部で動的テーブル構築エンジンでテーブル化されたものを用いて生成される。
- 解釈テーブルはそれ自体独立したオブジェクトなので、容易に別の方法で出力可能。
- 現在はC++コードジェネレータしか存在しないが、他言語版を作るのも難しくないと思う(ターゲット言語に依存するコードは最後の最後だけ)
- elisp用とかJavaScript用とかPHP用なんて作ったら需要がありそうななさそうな(型情報完全無視になりますが)。
caperおよび動的解釈テーブル構築エンジン自体の速度的性能はイマイチ
- 動的パーサも未チューンなので、transition mapに
std::map
を使っていたりして遅いと思う。(とはいえ現代のマシンならcaperの入力ファイルごときは一瞬)
現在の注意点
開発中のバージョンです。一通りの機能は実装しましたが、安定性の検証はまだです。仕様が変更される可能性は大いにあります(特に要望によって)。おもちゃくらいの気持ちでいじってみてください。
STLオフ時の出力のStack<T>の実装がかなり不安です(特にTが複雑な型のとき)。%dont_use_stl;
で動かなかったら外してみてください。C++エキスパートの添削希望。