はじめに

Spirit は、テンプレートメタプログラミング技術によって実装された、オブジェクト指向 再帰下降型パーサジェネレータフレームワークである。 式テンプレートを用いることで、 C++ で拡張バッカス記法( EBNF )の構文を完璧に模倣することが可能となった。

Spirit フレームワークでは、ターゲットとなる文法を C++ のみで書き起こすことができる。 インラインに記述された EBNF 文法仕様は、他の C++ コードと自由に混在させる事ができ、 また、 C++ テンプレートの生成的な力のおかげで、即座に実行する事ができる。 今にして思えば、従来のコンパイラ−コンパイラやパーサジェネレータは、 EBNF ソースコードから C や C++ コードへの余計な翻訳ステップを実行しなければならなかった。

次のような簡単な EBNF 文法の断片は:

    group       ::= '(' expression ')'
    factor      ::= integer | group
    term        ::= factor (('*' factor) | ('/' factor))*
    expression  ::= term (('+' term) | ('-' term))*

Spirit の機能を用いて次のコード断片のように模倣される:

    group       = '(' >> expression >> ')';
    factor      = integer | group;
    term        = factor >> *(('*' >> factor) | ('/' >> factor));
    expression  = term >> *(('+' >> term) | ('-' >> term));

式テンプレートの魔法によって、これは完璧に有効で実行可能な C++ コードである。 生成規則 expression は実はオブジェクトであり、メンバ関数 parse を持つ。 この関数は、ちょうど我々が宣言し終えた文法で書かれたソースコードに対して働く。 そう、これは電卓である。 話を単純にするために、factor によって呼び出される integer ルールの型宣言と定義は端折っている。 我々の文法仕様の生成ルール expression は伝統的に開始記号と呼ばれ、次のような入力を認識できる:

   12345
   -12345
   +12345
   1 + 2
   1 * 2
   1/2 + 3/4
   1 + 2 + 3 + 4
   1 * 2 * 3 * 4
   (1 + 2) * (3 + 4)
   (-1 + 2) * (3 + -4)
   1 + ((6 * 200) - 20) / 6
   (1 + (2 + (3 + (4 + 5))))

確かに我々は元の EBNF 構文に対していくつかの修正を施した。 これは C++ の構文規則を満たすためである。 最も顕著に分かることは、シフト >> 演算子の多用である。 C++ には '空の' 演算子が存在しないので、 例えば数学の構文で見られる乗算の意味や、この場合だと EBNF 構文での順序( a の後に続くb )の意味で 単に以下のように書く事はできないのだ:

   a b

フレームワークは、この目的の為にシフト >> 演算子を用いる。 "〜は−が後に続く" ことを意味するのに >> 演算子、つまり右を指す矢印を用いる。 だから次のように書く:

    a >> b

選択演算子 | および括弧 () はそのままの意味で残っている。 代入演算子 = は EBNF の ::= の代わりに用いられる。 最後になってしまったが重要なことは、 EBNF では後置演算子である Kleene star * が前置になっていることである。 つまり以下のように書く代わりに:

    a* //... EBNF の書き方

このように書く:

    *a //... Spirit の書き方

これは、 C++ には後置の星、"*" が存在しないためである。 最後に、各々のルールはあちこちに現れるセミコロン ";" で終わる。



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