首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提升精神语义动作

提升精神语义动作
EN

Stack Overflow用户
提问于 2014-05-20 10:38:31
回答 1查看 263关注 0票数 2

我一直在尝试使用Boost精灵解析字符串,如下所示:

代码语言:javascript
复制
integer_count int1 int2 int3 ... intN

其中N是integer_count。例如,

代码语言:javascript
复制
5 1 2 3 4 5

守则如下:

代码语言:javascript
复制
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;

template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, std::string(), ascii::space_type>
{   
public:
    x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
    {   
        using namespace qi; 
        int repeat_count = 0;
        start_rule = int_[ref(repeat_count) = _1] > repeater > *char_;
        std::cout << "repeat_count == " << repeat_count << std::endl;
        repeater = repeat(repeat_count)[int_[std::cout << _1 << ".\n"]];
    }   
private:
    qi::rule<Iterator, std::string(), ascii::space_type> start_rule;
    qi::rule<Iterator, std::string(), ascii::space_type> repeater;
};  

int main()
{   
    typedef std::string::const_iterator iter;
    std::string storage("5 1 2 3 4 5 garbage");
    iter it_begin(storage.begin());
    iter it_end(storage.end());
    std::string read_data;
    using boost::spirit::ascii::space;
    x_grammar<iter> g;
    try {
        bool r = qi::phrase_parse(it_begin, it_end, g, space, read_data);
        if(r) {
            std::cout << "Pass!\n";
        } else {
            std::cout << "Fail!\n";
        }   
    } catch (const qi::expectation_failure<iter>& x) {
        std::cout << "Fail!\n";
    }   
}   

产出如下:

代码语言:javascript
复制
repeat_count == 0
Pass!

这意味着

代码语言:javascript
复制
ref(repeat_count) = _1

从未被提起过。那么,是否有办法将整数运行时读入局部变量并使用该值进行进一步的解析?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-20 11:06:45

我想你是说

代码语言:javascript
复制
repeat(boost::phoenix::ref(repeat_count))

此外,当有语义操作时,规则将禁用自动属性传播。您可以使用%=强制属性传播。

下面是一个简单的固定版本住在Coliru

代码语言:javascript
复制
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;

template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, ascii::space_type>
{   
public:
    x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
    {   
        using namespace qi; 
        int repeat_count = 0;
        start_rule = int_[ref(repeat_count) = _1] > repeater > *char_;
        std::cout << "repeat_count == " << repeat_count << std::endl;
        repeater = repeat(ref(repeat_count))[int_[std::cout << _1 << ".\n"]];
    }   
private:
    qi::rule<Iterator, ascii::space_type> start_rule;
    qi::rule<Iterator, ascii::space_type> repeater;
};  

int main()
{   
    typedef std::string::const_iterator iter;
    std::string storage("5 1 2 3 4 5 garbage");
    iter it_begin(storage.begin());
    iter it_end(storage.end());
    using boost::spirit::ascii::space;
    x_grammar<iter> g;
    try {
        bool r = qi::phrase_parse(it_begin, it_end, g, space);
        if(r) {
            std::cout << "Pass!\n";
        } else {
            std::cout << "Fail!\n";
        }   
    } catch (const qi::expectation_failure<iter>& x) {
        std::cout << "Fail!\n";
    }   
}   

打印

代码语言:javascript
复制
repeat_count == 0
1.
2.
3.
4.
5.
Pass!

显然,注意到repeat_count == 0是如何打印的,因为它是在语法构造过程中执行的,而不是解析过程中执行的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23757504

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档