1

すべての列挙型のファイルをチェックしたい (これは単なる MCVE であるため、複雑なことは何もない)。列挙型の名前は、次のstd::vectorようにパーサーを構築する

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);

enum_finderthisを使用して文字列を に解析しようとするとstd::vectorstd::vector多くの空の文字列も含まれます。このパーサーが空の文字列もベクトルに解析するのはなぜですか?

4

1 に答える 1

2

空白を無視して自由形式のテキストから「enum」を解析したいと仮定しました。

あなたが本当に欲しいのは、("enum" >> identifier | any)を合成するためoptional<string>です。悲しいことに、あなたが得るのはvariant<string, unused_type>またはそのようなものです。

anyでラップすると同じことが起こりますx3::omit[any]-それはまだ同じunused_typeです。

プラン B: 本当に「何でも」で区切られた列挙型 ID の繰り返しを解析しているだけなので、リスト演算子を使用しない理由は次のとおりです。

     ("enum" >> identifier) % any

これは少し機能します。いくつかの微調整: 文字ごとに「任意の」文字を食べないようにします。実際、空白で区切られた単語全体を消費する可能性があります: (注+~spaceは同等です+graph):

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

次に、複数の偽の単語が連続して受け入れられるようにするために、リストのサブジェクト パーサーをオプションにするトリックがあります。

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

これは正しく解析されます。完全なデモを見る:

デモ

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 !@#!@#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 !@#!@#Yay'
parsed 2 elements:
    one
    two
于 2016-06-11T16:48:29.467 に答える