文字列を再帰的に解析し、結果を 1 つの構造体に格納したいと考えています。1回の反復を処理できるパーサーを作成しました。入力は次のようにフォーマットされます。
v 1.5 2.0 2.5
v 3.0 3.5 4.0
f 1 2 3
f 4 5 6
v 4.5 5.0 5.5
v 6.0 6.5 7.0
f 7 8 9
f 10 11 12
問題は、最初の 4 行のみを解析し、3 番目に検出された 'v' で停止することです。完全なコードを以下に示します。このコードを変更して、残りの入力も同じ構造体に解析するにはどうすればよいですか? start = vertex >> elements
開始ルールを からに変更しようとしましたstart = *(vertex >> elements)
が、大きなコンパイル エラーが発生するだけです。についても同様ですstart = +(vertex >> elements)
。ルールを変更する方法はありますか?
#include <iostream>
#include <sstream>
#include <fstream>
#include "boost/spirit/include/qi.hpp"
#include "boost/spirit/include/support_iso8859_1.hpp"
#include "boost/fusion/include/adapt_struct.hpp"
struct ElemParseData
{
std::vector<float> verts;
std::vector<unsigned int> idx;
};
BOOST_FUSION_ADAPT_STRUCT(
ElemParseData,
(std::vector<float>, verts)
(std::vector<unsigned int>, idx)
)
bool doParse( ElemParseData &parseData, const std::string &data )
{
namespace qi = boost::spirit::qi;
namespace iso8859 = boost::spirit::iso8859_1;
struct objGram : qi::grammar<std::string::const_iterator, ElemParseData(), iso8859::space_type>
{
objGram() : objGram::base_type(start)
{
vertex = *('v' >> qi::double_ >> qi::double_ >> qi::double_);
elements = *('f' >> qi::int_ >> qi::int_ >> qi::int_);
start = vertex >> elements;
}
qi::rule<std::string::const_iterator, ElemParseData(), iso8859::space_type> start;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;
qi::rule<std::string::const_iterator, std::vector<unsigned int>(), iso8859::space_type> elements;
} objGrammar;
std::string::const_iterator f = data.cbegin();
bool res = qi::phrase_parse( f, data.cend(), objGrammar, iso8859::space, parseData );
// print everything that hasn't been processed by the parser
std::cout << "#### Trail ####" << std::endl;
std::cout << std::string(f, data.cend()) << std::endl;
return res;
}
int main( int argc, char* argv[] )
{
std::stringstream ss;
std::filebuf fb;
if ( fb.open("parsetest.txt", std::ios::in) )
{
std::istream is(&fb);
while (is)
ss << char(is.get());
fb.close();
}
ElemParseData parseData;
bool res = doParse( parseData, ss.str() );
// print results
std::cout << std::endl << "Parsing result: " << res << std::endl;
std::cout << "---######### ResultData #########---" << std::endl;
std::cout << "---- Begin vertex data ----" << std::endl;
std::vector<float>::iterator it;
for ( it = parseData.verts.begin(); it != parseData.verts.end(); ++it )
std::cout << *it << std::endl;
std::cout << "---- End vertex data ----" << std::endl;
std::cout << std::endl;
std::cout << "---- Begin index data ----" << std::endl;
std::vector<unsigned int>::iterator idxIt;
for ( idxIt = parseData.idx.begin(); idxIt != parseData.idx.end(); ++idxIt )
std::cout << *idxIt << std::endl;
std::cout << "---- End index data ----" << std::endl;
std::cout << "Press enter to exit" << std::endl;
std::cin.get();
}
PS: 必要に応じて、コンパイル エラーをここで見つけることができます。
編集: Wavefront .OBJ パーサーを作成しようとしています。ここで与えられた入力は、私の問題を単純化したものです。