2016-06-11 5 views
1

すべての列挙型(これは単なるMCVEなので何も複雑ではありません)と列挙型の名前をstd::vectorに保存する必要があります。 :ブースト・スピリットから返された空文字列x3パーサー

auto const any = x3::rule<class any_id, const x3::unused_type>{"any"} 
       = ~x3::space; 

auto const identifier = x3::rule<class identifier_id, std::string>{"identifier"} 
         = x3::lexeme[x3::char_("A-Za-z_") >> *x3::char_("A-Za-z_0-9")]; 

auto const enum_finder = x3::rule<class enum_finder_id, std::vector<std::string>>{"enum_finder"} 
         = *(("enum" >> identifier) | any); 

私はstd::vectorにこのenum_finderで文字列を解析しようとしています、std::vectorも空の文字列が多く含まれています。 このパーサも空の文字列を解析してベクトルに変換されるのはなぜですか?

+3

これは** ** MCVEではありません。それは最小限ではありません。それは完全ではありません。それは検証可能ではありません。サンプル入力がありますか? – sehe

+0

@sehe [ここ](http://melpon.org/wandbox/permlink/51qsx3qf6z8flvi4)は何か完全なものです(悲しいことに、私は自分のコンピュータにアクセスできないので悲しいことに1.60を使うだけです。私はオンラインコンパイラには1.61があります)。 'a'の属性がstd :: stringで' b'が未使用のときの 'a | b'の属性はboost :: optionalの代わりにstd :: stringになっているようです。 – llonesmiz

+0

FWIW私はちょうどそこにSSCCEの素敵な例を載せたと思う。 – sehe

答えて

2

空白を無視して自由形式のテキストから "enum"を解析したいと思っています。

("enum" >> identifier | any)にはoptional<string>を合成してください。悲しいことに、あなたが得るのはvariant<string, unused_type>またはそれです。

anyx3::omit[any]とラップすると同じことが起こります。これはまだ同じ未使用タイプです。

プランB:これは少し作品

 ("enum" >> identifier) % any 

:あなたは本当にただ「何」で区切って繰り返し列挙-IDSを解析しているので、なぜリスト演算子を使用していません。今やいくつかの微調整:「任意の」文字を文字で食べないようにします。 (+~space+graph同等であることに注意):実際には、我々は可能性が高いだけで全体の空白で区切られた単語を消費することができます

auto const any = x3::rule<class any_id>{"any"} 
       = x3::lexeme [+x3::graph]; 

次に、リストの対象を作るためのトリックがあります複数の偽の言葉が一列に受け入れられるためにはできるようにしますパーサー(任意):

 -("enum" >> identifier) % any; 

これは正しく解析されます。完全なデモを参照してください。

DEMO

Live On Coliru

#include <boost/spirit/home/x3.hpp> 
namespace x3 = boost::spirit::x3; 

namespace parser { 
    using namespace x3; 
    auto any   = lexeme [+~space]; 
    auto identifier = lexeme [char_("A-Za-z_") >> *char_("A-Za-z_0-9")]; 
    auto enum_finder = -("enum" >> identifier) % any; 
} 

#include <iostream> 
int main() { 

    for (std::string input : { 
      "", 
      " ", 
      "bogus", 
      "enum one", 
      "enum one enum two", 
      "enum one bogus bogus more bogus enum two [email protected]#[email protected]#Yay", 
     }) 
    { 
     auto f = input.begin(), l = input.end(); 
     std::cout << "------------ parsing '" << input << "'\n"; 

     std::vector<std::string> data; 
     if (phrase_parse(f, l, parser::enum_finder, x3::space, data)) 
     { 
      std::cout << "parsed " << data.size() << " elements:\n"; 
      for (auto& el : data) 
       std::cout << "\t" << el << "\n"; 
     } else { 
      std::cout << "Parse failure\n"; 
     } 

     if (f!=l) 
      std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; 
    } 

} 

プリント:

------------ parsing '' 
parsed 0 elements: 
------------ parsing ' ' 
parsed 0 elements: 
------------ parsing 'bogus' 
parsed 0 elements: 
------------ parsing 'enum one' 
parsed 1 elements: 
    one 
------------ parsing 'enum one enum two' 
parsed 1 elements: 
    one 
------------ parsing 'enum one bogus bogus more bogus enum two [email protected]#[email protected]#Yay' 
parsed 2 elements: 
    one 
    two 
+0

非常にあなたは私のブーストスピリットヒーロー – Exagon

+0

ですが、例では "enum one enum two"なぜそれは1つの要素を見つけるのですか?他のものも解析すればよいでしょうか? – Exagon

+0

@Exagon私は 'auto any = lexeme [*(〜space - " enum ")];を使って動作するはずですが、テストできません。 – llonesmiz

関連する問題