ブースト スピリット クロージャに格納されている変数をブースト スピリット ループ パーサーへの入力として使用するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/1474990

  •  16-09-2019
  •  | 
  •  

質問

解析された値をループパーサーへの入力として使用したいと考えています。

文法は、次の文字列の (変数) サイズを指定するヘッダーを定義します。たとえば、次の文字列がパーサーへの入力であるとします。

12 テスト ペイロード

パーサーは、 12, に変換します。 符号なし整数 そして12文字を読みます。コンパイル可能なブースト スピリット文法を定義できますが、ブースト スピリット コード内のアサーションが実行時に失敗します。

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

using namespace boost::spirit;

struct my_closure : public closure<my_closure, std::size_t> {
member1 size;
};

struct my_grammar : public grammar<my_grammar> {
template <typename ScannerT>
struct definition {
    typedef rule<ScannerT> rule_type;
    typedef rule<ScannerT, my_closure::context_t> closure_rule_type;

    closure_rule_type header;
    rule_type payload;
    rule_type top;

    definition(const my_grammar &self)
    {
        using namespace phoenix;
        header = uint_p[header.size = arg1];
        payload = repeat_p(header.size())[anychar_p][assign_a(self.result)];
        top = header >> str_p("\r\n") >> payload;
    }

    const rule_type &start() const { return top; }
};

my_grammar(std::string &p_) : result(p_) {}
std::string &result;
};

int
main(int argc, char **argv)
{
const std::string content = "12\r\nTest Payload";
std::string payload;
my_grammar g(payload);
if (!parse(content.begin(), content.end(), g).full) {
    std::cerr << "there was a parsing error!\n";
    return -1;
}
std::cout << "Payload: " << payload << std::endl;
return 0;
}

クロージャ変数を遅延評価する必要があることをスピリットに伝えることはできますか?この行動はブースト精神に支えられているのでしょうか?

役に立ちましたか?

解決

これは、次のコードスニペット2.スピリットで利用できる新しい気のパーサとはるかに簡単である、主に動作することを完全な例を提供します。予期しない文字は、最終的な結果に挿入されています。

#include <iostream>
#include <string>

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

using boost::spirit::qi::repeat;
using boost::spirit::qi::uint_;
using boost::spirit::ascii::char_;
using boost::spirit::ascii::alpha;
using boost::spirit::qi::_1;
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;

template <typename P, typename T>
void test_parser_attr(
    char const* input, P const& p, T& attr, bool full_match = true)
{
    using boost::spirit::qi::parse;

    char const* f(input);
    char const* l(f + strlen(f));
    if (parse(f, l, p, attr) && (!full_match || (f == l)))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

static void
straight_forward()
{
    std::string str;
    int n;
    test_parser_attr("12\r\nTest Payload",
                     uint_[phx::ref(n) = _1] >> "\r\n" >> repeat(phx::ref(n))[char_],
                     str);
    std::cout << "str.length() == " << str.length() << std::endl;
    std::cout << n << "," << str << std::endl;  // will print "12,Test Payload"
}

template <typename P, typename T>
void
test_phrase_parser(char const* input, P const& p,
                   T& attr, bool full_match = true)
{
    using boost::spirit::qi::phrase_parse;
    using boost::spirit::qi::ascii::space;

    char const* f(input);
    char const* l(f + strlen(f));
    if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

template <typename Iterator>
struct test_grammar
    : qi::grammar<Iterator, std::string(), qi::locals<unsigned> > {

    test_grammar()
        : test_grammar::base_type(my_rule)
    {
        using boost::spirit::qi::_a;
        my_rule %= uint_[_a = _1] >> "\r\n" >> repeat(_a)[char_];
    }

    qi::rule<Iterator, std::string(), qi::locals<unsigned> > my_rule;
};

static void
with_grammar_local_variable()
{
    std::string str;
    test_phrase_parser("12\r\nTest Payload", test_grammar<const char*>(), str);
    std::cout << str << std::endl;  // will print "Test Payload"
}

int
main(int argc, char **argv)
{
    std::cout << "boost version: " << BOOST_LIB_VERSION << std::endl;

    straight_forward();
    with_grammar_local_variable();

    return 0;
}

他のヒント

探しているのはlazy_pです。ここで例を確認してください。 http://www.boost.org/doc/libs/1_35_0/libs/spirit/doc/the_lazy_parser.html

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