boost::spiritに手を出してみる
噂に違わぬ変態ぶりに感動しつつ、mqoを読むだけの実験コードを書いてみた。
これはいいものだ。
bison, flexの勉強しないといかんなぁと常々思っていたのだが
むしろこっちの方が使うの簡単だし申し分ないです。
http://luxla.net/project/mqo
のblenderのmqoインポータをちょっと参考にしました。
まだ、シンボルの使い方がよくわからないので要練習デス。
#include <boost/spirit/core.hpp> #include <boost/spirit/iterator/file_iterator.hpp> #include <boost/spirit/utility.hpp> #include <boost/lambda/bind.hpp> #include <iostream> void print(const char *text) { std::cout << text << std::endl; } struct MQOParser : boost::spirit::grammar<MQOParser> { template<typename ScannerT> struct definition { boost::spirit::rule<ScannerT> top, header, line, scene, material, object, vertex, face, includexml, backimage; definition(const MQOParser &) { using namespace boost::spirit; top=header >> *(scene | material | object | includexml | backimage | eol_p ) >> "Eof" >> eol_p; line=*(~chset<>("\r}")) >> eol_p; header =str_p("Metasequoia Document\r\nFormat Text Ver 1.0\r\n\r\n") [ boost::lambda::bind(&print, "Header") ]; scene=("Scene " >> confix_p('{', *(~ch_p('}')), '}') >> eol_p) [ boost::lambda::bind(&print, "Scene") ]; material=("Material " >> uint_p >> ' ' >> confix_p('{', *(~ch_p('}')), '}') >> eol_p) [ boost::lambda::bind(&print, "Material") ]; object=("Object " >> confix_p('"', *(~ch_p('"')), '"') >> ' ' >> confix_p('{', *(vertex|face|line), '}') >> eol_p) [ boost::lambda::bind(&print, "Object") ], vertex=("\tvertex " >> uint_p >> ' ' >> confix_p('{', *(~ch_p('}')), '}') >> eol_p) [ boost::lambda::bind(&print, "vertex") ]; face=("\tface " >> uint_p >> ' ' >> confix_p('{', *(~ch_p('}')), '}') >> eol_p) [ boost::lambda::bind(&print, "face") ]; includexml=("IncludeXml " >> confix_p('"', *(~ch_p('"')), '"') >> eol_p) [ boost::lambda::bind(&print, "includexml") ]; backimage=("BackImage " >> confix_p('{', *(~ch_p('}')), '}') >> eol_p) [ boost::lambda::bind(&print, "backimage") ]; } const boost::spirit::rule<ScannerT> &start() const { return top; }; }; }; int main(int argc, char **argv) { if(argc<2){ std::cerr << "usage: " << argv[0] << " {mqo_file}" << std::endl; return 1; } boost::spirit::file_iterator<char> in(argv[1]); if(!in){ std::cerr << "fail to open file: " << argv[1] << std::endl; return 1; } MQOParser parser; if(boost::spirit::parse(in, in.make_end(), MQOParser()).full){ std::cout << "## SUCCESS ##" << std::endl; return 0; } else{ std::cout << "## FAILED ##" << std::endl; return 1; } }