3

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

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

12\r\nテスト ペイロード

パーサーは12を抽出し、それをunsigned intに変換してから、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;
}

クロージャー変数を遅延評価する必要があることを精神に伝えることは可能ですか? この行動はブーストスピリットによってサポートされていますか?

4

2 に答える 2

3

これは、Spirit 2 で利用可能な新しい qi パーサーを使用すると、はるかに簡単になります。次のコード スニペットは、ほとんどが機能する完全な例を示しています。最終結果に予期しない文字が挿入されています。

#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;
}
于 2010-02-06T13:05:23.743 に答える
0

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

于 2010-02-04T16:35:48.057 に答える