1

boost::spiritの使用方法を学習していますが、非常に単純なパーサーでもいくつかの問題に直面しています。コロンで区切られた数字のリスト (0 または 1 のみ) を受け入れるパーサーを構築しようとしています。リストには 3 桁または 4 桁を含めることができます。したがって、0:0:0and1:0:1:0は有効ですが、たとえば0:0or0:0:0:0:0は有効ではありません。

次のコードでは、オプションの演算子を使用して最初の桁が存在するかどうかを指定する方法を確認できます。ただし、機能しません (シーケンスの解析に失敗します0:0:0)。コードに何か問題がありますか? それは正しいと思いますが、繰り返しになりますが、私はスピリットを学び始めたばかりです。

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

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;

void parse_tuple(const std::string& tuple) {
    using qi::char_;

    auto begin = tuple.begin();
    auto end = tuple.end();

    bool r = qi::parse(begin, end,
            -(char_('0', '1') >> ':') >> 
              char_('0', '1') >> ':' >>
              char_('0', '1') >> ':' >>
              char_('0', '1')
            );
    if (!r || begin != end)
        throw std::runtime_error("wrong format");
}

int main() {
    parse_tuple("0:0:0"); // It fails for this one
    parse_tuple("0:0:0:0");

    try { parse_tuple("0:0"); } catch (...) {
        std::cout << "expected error\n"; }
    try { parse_tuple("0:0:0:0:0"); } catch (...) {
        std::cout << "expected error\n"; }
}
4

2 に答える 2

1

ここ

bool r = qi::parse(begin, end,
        -(char_('0', '1') >> ':') >> 
          char_('0', '1') >> ':' >>
          char_('0', '1') >> ':' >>
          char_('0', '1')
        );

オプションの char_ は、最初のものではなく、最後のものでなければなりません。ルールは順番に適用されるため、「0:0:0」を解析しているときに、コードの最初の行 (オプションのもの) がテストに合格すると、ルールは 2 桁ではなく 3 桁が続くことを期待します。

私の意見では、 % 演算子を使用してリストを照合し、後で 3 つまたは 4 つの要素を解析したかどうかを確認する必要があります。

編集 またはqi::repeatを使用して、読みやすさを向上させます。

于 2012-12-14T22:50:09.143 に答える
0

これは最も簡単な解決策です。

bool r = qi::parse(begin, end,
        char_("01") > ':' >
        char_("01") > ':' >
        char_("01") > -(':' > char_("01"))
        );

完全なサンプルhttp://liveworkspace.org/code/3U0QJW$0 :

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

void parse_tuple(const std::string& tuple) {
    using qi::char_;

    auto begin = tuple.begin();
    auto end = tuple.end();

    bool r = qi::parse(begin, end,
            char_("01") > ':' >
            char_("01") > ':' >
            char_("01") > -(':' > char_("01"))
            );
    if (!r || begin != end)
        throw std::runtime_error("wrong format");
}

int main() {
    parse_tuple("0:0:0"); // It fails for this one
    parse_tuple("0:0:0:0");

    try { parse_tuple("0:0"); } catch (...) {
        std::cout << "expected error\n"; }
    try { parse_tuple("0:0:0:0:0"); } catch (...) {
        std::cout << "expected error\n"; }
}
于 2012-12-15T01:31:34.150 に答える