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で動的にターゲットを追加されると、どうしようもないですね。