質問

私はちょうどBoost :: Spirit、最新バージョンを掘り始めました-v2.4。私の問題のエッセンスは次のとおりです。

「1A2」のような文字列を解析したい また 「3B4」。したがって、私が使用するルールは次のとおりです。

  (double_ >> lit('b') >> double_)
| (double_ >> lit('a') >> double_);

ルールの属性は「ベクトル」でなければなりませんu003Cdouble>"。そして、私はそれをコンテナに読んでいます。

完全なコード:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>

int main(int argc, char * argv[])
{
    using namespace std;
    using namespace boost::spirit;
    using namespace boost::spirit::qi;
    using boost::phoenix::arg_names::arg1;

    char const * first = "1a2";
    char const * last  = first + std::strlen(first);
    vector<double> h;

    rule<char const *, vector<double>()> or_test;
    or_test %=    (double_ >> lit('b') >> double_) 
            | (double_ >> lit('a') >> double_);

    if (parse(first, last, or_test,h)) {
           cout << "parse success: "; 
           for_each(h.begin(), h.end(), (cout << arg1 << " "));
           cout << "end\n";
    } else cout << "parse error\n" << endl;
    return 0;
 }

G ++ 4.4.3でコンパイルしています。そして、それは「1 1 2」を返します。 「1 2」を期待しています。

私が理解している限り、これはパーサーのために起こります:

  • 最初の代替品に行きます
  • double_を読み取り、コンテナに保存します
  • その後、lit(「b」)を期待しながら、「a」で停止します
  • 2番目の代替品に進みます
  • さらに2つのダブルを読み取ります

私の質問は - これは正しい動作ですか、もしそうなら、なぜですか?

役に立ちましたか?

解決

それは予想される動作です。バックトラッキング中に、スピリットは属性の変更を「メイクする」ことはありません。したがって、を使用する必要があります hold[] 指令は、パーサーに属性のコピーを保持するように明示的に強制します(属性の変更をロールバックすることができます):

or_test =    
        hold[double_ >> lit('b') >> double_)]
    |   (double_ >> lit('a') >> double_)
    ; 

この指令は、最後の属性を除く属性を変更するすべての代替案に適用する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top