bjam_grammar

bjamのパーサーをBoost.Spiritで書いています。
これまでBoost.Spiritで大きなパーサーは書いたことなかったので四苦八苦しています。
↓とりあえず、これでかなり悩みました。
Boost.Spirit FAQ: The lexeme_d directive and rules
FAQに従うと、jamのリテラルのパースはこんな感じになりました。

#include <boost/spirit/core.hpp>
#include <boost/spirit/utility.hpp>

using namespace boost::spirit;

struct bjam_grammar : grammar<bjam_grammar>
{
    template<class ScannerT>
    struct definition
    {
        typedef rule<ScannerT> rule_t;
        typedef rule<typename lexeme_scanner<ScannerT>::type> lexeme_rule_t;

        // rule_tではダメ
        lexeme_rule_t literal_char, escape_char;

        rule_t literal;

        definition(const bjam_grammar& self)
        {
            // いい加減
            literal_char
                =   alnum_p | '.' | '-' | '_'
                ;

            escape_char
                =   '\\' >> ('"' | space_p)
                ;

            literal
                =   lexeme_d
                    [   +literal_char
                    |   '"' >> *( literal_char | escape_char ) >> '"'
                    ]
                ;

                // 以下略


Jamfileの文法は、「Perforce Jam」の
http://public.perforce.com/public/jam/src/Jam.html
を参照していますが、これは大雑把な説明なので手直しが必要です。
bjamはこれにかなり手を加えているので、どちらにしろ手直しはいるんでしょうけど。


進行度合いは10〜20%といったところです。
ifやforなどの制御文をパースできて、libやexeルールの呼び出しをリストアップできれば、後は適当でいいです。
ただ、forで動的にターゲットを追加されると、どうしようもないですね。