構成

このフレームワークは高度にモジュール化されており、またいくつかのレイヤーから構成されている。

attribute
debug
dynamic
error_handling
iterator
symbols
tree
utility
closure.hpp
closure_context.hpp
grouping.hpp
parametric.hpp
debug_node.hpp
minimal.hpp
parser_names.hpp
for.hpp
if.hpp
while.hpp
exceptions.hpp file_iterator.hpp
fixed_size_queue.hpp
multi_pass.hpp
position_iterator.hpp
symbols.hpp ast.hpp
common.hpp
parse_tree.hpp
parse_tree_utils.hpp
parsetree.dtd
tree_iterator.hpp
tree_to_xml.hpp
chset.hpp
chset_operators.hpp
confix.hpp
escape_char.hpp
flush_multi_pass.hpp
functor_parser.hpp
lists.hpp
loops.hpp
refactoring.hpp
regex.hpp
scoped_lock.hpp
Core
scanner
primitives
composite
non_terminal
meta
scanner.hpp
skipper.hpp
primitives.hpp
numerics.hpp
composite.hpp
operators.hpp
actions.hpp
directives.hpp
epsilon.hpp
parser_context.hpp
parser_id.hpp
rule.hpp
subrule.hpp
grammar.hpp
fundamental.hpp
parser_traits.hpp
traverse.hpp

現在の Spirit は、基本的に二つのレイヤー、コアとコア上にあるすべてのモジュールから成っている。 コア以外のモジュールとはデバッグ、属性、シンボル、ツリー、ユーティリティ、動的パーサおよびエラー処理である。 将来的には新しいレイヤーが既存のレイヤーの上に組み立てられるだろう。 このフレームワークのアーキテクチャは完全に直交している。 レイヤー間の関係は完全に非環式である[訳注:AがBを、BがCを、CがAを必要とするようなことはない]。 コアは他のレイヤーの存在に依存しないし、関知もしない。 あるレイヤーに属すモジュールが、同一レイヤーの他のモジュールに依存することもない。

クライアントは、コンパイル時や実行時のペナルティーのない、望みのモジュールのみ使うだろう。 最小主義的なアプローチは、現状のように、コアにのみ用いられている。 非常に合理化されたコアは、単独で利用可能である。 コアはごく小さなパージングなどのタスクに非常に適している。

属性モジュールは、より進んだセマンティックアクション機構を導入する。 これは、 属性を継承したり合成することで、 パーサ階層の至る所で、データの抽出や受け渡しを強調する。 実際には、属性は構文解析を制御するのに用いられる。 パラメトリックパーサは動的パーサの一形態であり、属性やデータを元にして、実行時にその振る舞いを変化させる。

デバッグモジュールはライブラリ中にデバッグ機能群を提供する。 このモジュールは基本的にコアを侵害しないように、また必要なときにのみ、それ自身を透過的にコアに接続する。

動的パーサモジュールは実行時に振る舞いを変更できる構文解析器にフォーカスしている。

エラー処理。このフレームワークはエラー処理なしでは完全とは言えない。 Spirit が高度な再帰関数であるという性質ゆえに、 C++ の例外処理メカニズムは Spirit うってつけだ。 C++ 例外はこのモジュールによってエラー処理の為に広く利用されている。

イテレータモジュールは Spirit から独立しており、他の文脈でも同じように活用できる。 このモジュールはスタンドアローンのイテレータと Spirit と互換性のあるイテレータラッパーを集めたものである。 時間が経つうちに、これらのイテレータは Spirit での構文解析で最も便利であるということが分かった。

シンボルモジュールはシンボルテーブルの管理にフォーカスしている。 このモジュールは現時点では非常に必要最小限のものである。 そのゴールは、 C++ スタイルの多重スコープ機構に対応できるようなサブフレームワークを組み立てることである。 C++ のスコープ処理は、おそらく他に比肩し得る言語のない複雑さをもった、素晴らしいモデルである。 クラスと継承、 private / protected / public アクセス制限、 friend 関数と friend クラス、名前空間、 using 宣言、 using 指令、 Koenig ルックアップ…等々がある。 現在我々が持っているシンボルテーブルの機能は、これをモデルとした完全な機能の基盤となるだろう。

ツリーのように愛しい構造を見ることができれば...

構文解析木および抽象構文木(AST)の生成はツリーモジュールによって処理される。 構文解析木と抽象構文木には、セマンティックアクションを越える利点がある。 例えば、入力を再解析することなく、データに多重パスを施すことができる。 あるいは、ツリー上で変換を掛けることができる。 属性という仕組みでは、始まりから終わりまでという流れで処理しなければならなかったが、 ツリーなら、物事を望みの順番で評価することができる。 バックトラッキングや、曖昧な文法で起こりがちなアクションの副作用について気にする必要もない。

ユーティリティモジュールは、一般的に便利なパーサの集合である。 この構文解析器ライブラリは開発時間を著しく削減する。 リスト処理、コメント、 confix expression などの一般的なタスクを処理するパーサが用意されている。

ヘッダファイル

Spirit はヘッダファイルのみで済むように設計されている。 通常はライブラリをビルドしてリンクする必要はない。 しかし一部の機能については追加のライブラリが必要である; 具体的には、正規表現パーサBoost.Regex を必要とし、 マルチスレッド支援機能Boost.Threads を必要とする。

Spirit を使うことは簡単である。メインヘッダファイルをインクルードするだけで良い:

    #include <boost/spirit.hpp>

すると、すべてのヘッダファイルがインクルードされる。 この動作は望みのものでない場合もあるだろう。 低コレステロールな代替策は、必要なモジュールだけをインクルードすることである。 各モジュールは固有のヘッダファイルを持っている。 実際のところ、 spirit のマスターヘッダファイルは、そのモジュールファイルをすべてインクルードしている:

    #include <boost/spirit/attribute.hpp>
    #include <boost/spirit/debug.hpp>
    #include <boost/spirit/dynamic.hpp>
    #include <boost/spirit/error_handling.hpp>
    #include <boost/spirit/iterator.hpp>
    #include <boost/spirit/symbols.hpp>
    #include <boost/spirit/tree.hpp>
    #include <boost/spirit/utility.hpp>

あなたが必要としない機能の不要なインクルードを回避するためには、必要なモジュールのみをインクルードする方が良い。 より細かくインクルードを制御するために、必要な特定のファイルのみをインクルードすることができる。 各モジュールは固有のサブディレクトリに納められている。 例えば、もしコアにクロージャのみ追加する必要があるなら、以下のようにする:

    #include <boost/spirit/core.hpp>
    #include <boost/spirit/attribute/closure.hpp>


このドキュメントの対象: Boost Version 1.30.0
最新版ドキュメント(英語)