2016-11-01 7 views
2

私はBoost.Qi初心者ですので、私はいくつかの簡単な例を試してみてください。オプションのパーサーでBoost.Qiコンパイラエラーが発生しました

文字列内の各コンポーネント間に任意の量の空白があります。 A:などの部分は固定されており、整数値を解析したいと思います。上記の例では、文字列の3番目の要素、C:3はオプションです。私は、このアプリケーションにBoost.Qiをテストするには、次の簡単な例を思い付いた:

#include <boost/optional.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <iostream> 

namespace qi = boost::spirit::qi; 

int main() 
{ 
    std::string s = "A:1 B:2   C:3"; 

    int a, b; 
    boost::optional<int> c; 

    if (!qi::parse(s.begin(), s.end(), 
     qi::lit("A:") >> qi::int_ >> +qi::space >> "B:" >> qi::int_ >> 
      -(+qi::space >> "C:" >> qi::int_), a, b, c)) 
    { 
     std::cout << "failed to parse" << std::endl; 
    } 

    std::cout << a << ' ' << b << ' ' << c.value_or(-1) << std::endl; 
} 

しかし、これは(C++ 11モードでブーストv1.58およびg ++ 5.4.0を使用して)コンパイルに失敗しました。 C++テンプレート・エラー・メッセージの典型的な海の中で、私は次を見つける:

spirit.cc:15:55: required from here 
/usr/include/boost/spirit/home/support/container.hpp:130:12: error: ‘int’ is not a class, struct, or union type 
    struct container_value 

spirit.cc:15:55: required from here 
/usr/include/boost/spirit/home/qi/detail/pass_container.hpp:316:66: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<int, void>’ 
      typedef typename traits::container_value<Attr>::type value_type; 
                   ^
/usr/include/boost/spirit/home/qi/detail/pass_container.hpp:329:15: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<int, void>’ 

は、私がここで間違ってやっている誰にもそれは明らかですか?

+0

私はあなたが明示的に[省略](http://www.boost.org/doc/libs/1_60_0/libs/spirit/docする必要があると思います/html/spirit/qi/reference/directive/omit.html)あなたはその属性に興味がないので、 '+ qi :: space'の両方が出現します。 –

答えて

3

あなたの元の文法は、(いくつかのフォーマットで)次のようになります。

qi::lit("A:") 
>> qi::int_ 
>> +qi::space 
>> qi::lit("B:") 
>> qi::int_ 
>> -( +qi::space 
    >> qi::lit("C:") 
    >> qi::int_ 
    ) 

それは属性を注意することが重要です各端末のタイプは、以下を生成する:

を生成し、生成を生成しません。

その上で、あなたが実際に持っている:(原因+へ)

  • 整数
  • 文字ベクトル
  • を(原因-に)オプションの整数
  • が原因>>に(タプル)は
    • 文字ベクタ(+
    • 整数

これはあなたがparse呼んで一致していません。

重要な点は、気にしない属性を抑制するためにomitディレクティブを使用することです。

その場合の正しい文法は次のようになります。

qi::lit("A:") 
>> qi::int_ 
>> qi::omit[+qi::space] 
>> qi::lit("B:") 
>> qi::int_ 
>> -( qi::omit[+qi::space] 
    >> qi::lit("C:") 
    >> qi::int_ 
    ) 
+0

優秀な説明;ありがとう。私は誤って、 'qi :: space'が(' qi :: lit'のような)関連する属性を持たないパーサータイプの1つであると考えていました。あなたの答えはそれを明確にします。 –

4

phrase_parseqi::spaceを使用することによって可能性があり、これを修正する方法スキッパー:

if (!qi::phrase_parse(s.begin(), s.end(), 
     qi::lit("A:") >> qi::int_ >> "B:" >> qi::int_ >> -("C:" >> qi::int_), qi::space, a, b, c)) 
+1

これはうまくいく(実際はもっと簡単な実装です)ので、おそらく行く方法です。なぜ私の例が間違っていたのかの詳細な説明を与えたので、私は他の答えを受け入れました。この入力をありがとう。 –

+0

@JasonRはい、とにかくこのスペースをスキップしたいので、これが行く方法だとも言いたいと思います。 –

関連する問題