2009-09-25 65 views
3

我想使用解析的值作爲循環解析器的輸入。如何使用存儲在boost精神閉包中的變量作爲boost精神循環解析器的輸入?

該語法定義了一個指定以下字符串的(可變)大小的標頭。例如,假設以下字符串是某個解析器的輸入。

12 \ r \ NTEST淨荷

分析器應提取,將其轉換爲無符號整型然後讀十二個字符。我可以定義一個編譯的boost語法語法,但是boost語言代碼中的斷言在運行時會失敗。

#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; 
} 

是否可以告訴精神關閉變量應該被懶惰評估?這種行爲是否受到精神支持?

+0

你的問題超出了我對Spirit所做的,但是從我的理解,如果你正在編寫新的代碼,你應該使用Qi而不是Spirit。 – 2009-09-25 02:05:34

+0

我感覺到精神正在發生變化。但是,我無法在新界面上找到任何文檔。我認爲它還沒有準備好。 – Dan 2009-09-25 02:48:22

+0

我在http://svn.boost.org/svn/boost/trunk/libs/spirit/doc/html/index.html – Dan 2009-09-25 03:07:55

回答

3

這是與提供的新氣解析器精神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; 
} 
相關問題