2

私は Spirit::Qi が初めてで、単純な Wavefront Obj パーサーを作成しようとしています。Boost::Spirit ドキュメンテーション サイト (リンク) のチュートリアルに従いましたが、ほとんどのインライン ルールが機能するようになりました。文法の実験を始めましたが、うまく機能しないようです。しばらくしてコンパイルできましたが、解析に失敗しました。私は自分が間違っていることを本当に知りません。

簡単に始めるために、次の内容を含む簡単なテキスト ファイルを作成しました。

v  -1.5701 33.8087 0.3592
v  -24.0119 0.0050 21.7439
v  20.8717 0.0050 21.7439
v  20.8717 0.0050 -21.0255
v  -24.0119 0.0050 -21.0255
v  -1.5701 0.0050 0.3592

念のため: 入力ファイルの読み取りは正常に機能します。

入力文字列を解析する小さな関数を作成しましたが、何らかの理由で失敗します。

bool Model::parseObj( std::string &data, std::vector<float> &v )
{
    struct objGram : qi::grammar<std::string::const_iterator, float()>
    {
        objGram() : objGram::base_type(vertex)
        {
            vertex = 'v' >> qi::float_
                         >> qi::float_
                         >> qi::float_; 
        }

        qi::rule<std::string::const_iterator, float()> vertex;
    };

    objGram grammar;

    return qi::phrase_parse( data.cbegin(), data.cend(),
                                grammar, iso8859::space, v );
}

qi::phrase_parse は false を返し続け、 std::vector v は最後にまだ空です...

助言がありますか?

編集:

スペース スキッパーを追加した後 (正しい名前ですか?)、float (118.0f) としてエンコードされた std::vector に最初の 'v' のみが追加されますが、実際の数値は追加されません。私の推測では、私のルールは正しくありません。数字のみを追加し、v をスキップしたい。

これが私の変更された関数です:

bool Model::parseObj( std::string &data, std::vector<float> &v )
{
    struct objGram : qi::grammar<std::string::const_iterator, float(), iso8859::space_type>
    {
        objGram() : objGram::base_type(vertex)
        {
            vertex = qi::char_('v') >> qi::float_
                         >> qi::float_
                         >> qi::float_; 
        }

        qi::rule<std::string::const_iterator, float(), iso8859::space_type> vertex;
    } objGrammar;

    return qi::phrase_parse( data.cbegin(), data.cend(),
                                objGrammar, iso8859::space, v );
}
4

1 に答える 1

2

ルールで間違った公開属性が宣言されています。それを変更:

qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;

ただし、(反復子/スキッパー型などの) 何に対しても文法構造体をテンプレート化しないため、文法構造体を使用しても意味がありません。代わりに、phrase_parse単純にイテレータ、スキッパー、およびルール タイプをすべて一度に推測して、次のように記述します。

bool parseObj(std::string const& data, std::vector<float> &v )
{
    return qi::phrase_parse( 
            data.cbegin(), data.cend(),
            'v' >> qi::float_ >> qi::float_ >> qi::float_, 
            qi::space, v);
}

それがより重要な点であることに同意していただけると思います。おまけに、属性の自動伝播ルールという優れた機能のおかげで、「ただうまくいく」(TM) のです。

しかし、あなたの文法を見て、あなたは確かにこれらを見たいと思うでしょう:

于 2013-07-08T21:43:43.107 に答える