c++ - 在使用 boost spirit 解析时更改属性值

标签 c++ boost-spirit

给定一个字符串 "1, 2, 3, 10, 15", 预期的输出应该是 01、02、03、10、15——也就是说,如果它的大小不是 2,则将“0”附加到已解析的属性。我很容易用 lambda 作为语义 Action 来做到这一点,但是如何在没有使用它们?我怀疑这里应该玩一些棘手的 qi::_val 和 qi::_1 游戏。 我真正想要的是

s = qi::repeat(1,2)[qi::digit] 
[(
        [](auto& parsed_number)
        { 
            return parsed_number.size()==2 ? 
            parsed_number : std::string("0") + parsed_number;
        } 
 ]); 

但是这样不行

#include <boost/spirit/include/qi.hpp>
#include <vector>
#include <string>
#include <iostream>

namespace qi = boost::spirit::qi;

using V = std::vector<std::string>;

template<typename It, typename Skipper>
struct G: qi::grammar<It, V(), Skipper>
{
    G(): G::base_type(v)
    {
        v = s % ',';
        s = qi::repeat(1,2)[qi::digit];
    }
private:
    qi::rule<It, V(), Skipper> v;
    qi::rule<It, std::string(), Skipper> s;
};


int main()
{
    const std::string s = "1, 2, 3, 10, 15";
    std::string::const_iterator beg(s.begin()), e;
    G<decltype(beg), qi::space_type> g;
    V R;
    bool b = qi::phrase_parse(beg, e, g, qi::space, R);
    if(!b){
        std::cerr << "parsing failed\n";
        return -1;
    }

    for(const auto& r: R) std::cout << r << '\n';
}

最佳答案

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/at.hpp>
#include <vector>
#include <string>
#include <iostream>

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

using V = std::vector<std::string>;

template<typename It, typename Skipper>
struct G: qi::grammar<It, V(), Skipper>
{
    G(): G::base_type(v)
    {
        v = s % ',';
        //s = qi::hold[qi::repeat(2)[qi::digit]]|(qi::attr('0') >> qi::digit);
        //s = (&qi::repeat(2)[qi::digit] | qi::attr('0')) >> qi::repeat(1,2)[qi::digit];
        //s = qi::as_string[qi::repeat(1,2)[qi::digit]] [qi::_val = phx::if_else(phx::size(qi::_1)==2,qi::_1,phx::val('0')+qi::_1)]; 
        s = qi::as_string[qi::repeat(1,2)[qi::digit]]
[(
        [](auto& parsed_number, auto& ctx)
        { 
            fusion::at_c<0>(ctx.attributes) = parsed_number.size()==2 ? 
            parsed_number : '0' + parsed_number;
        } 
 )]; 
    }
private:
    qi::rule<It, V(), Skipper> v;
    qi::rule<It, std::string(), Skipper> s;
};


int main()
{
    const std::string s = "1, 2, 3, 10, 15";
    std::string::const_iterator beg(s.begin()), e;
    G<decltype(beg), qi::space_type> g;
    V R;
    bool b = qi::phrase_parse(beg, e, g, qi::space, R);
    if(!b){
        std::cerr << "parsing failed\n";
        return -1;
    }

    for(const auto& r: R) std::cout << r << '\n';
}

关于c++ - 在使用 boost spirit 解析时更改属性值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54887955/

相关文章:

c++ - 提升精神数字解析器并获得所需的综合属性

c++ - 将基类的引用传递给另一个函数

c++ - 为什么不能将 `decltype()` 用于 lambda 的 `std::function<>`?

c++ - 静态变量未初始化

c++ - 在运行时组合规则并返回规则

c++ - spirit boost : parameter type when using semantic actions and phoenix

c++ - C++中整数异或的可能结果

c++ - 单例中的全局对象

c++ - boost spirit : Lex + Qi error reporting

c++ - boost spirit skipper - 编译时错误