的boost ::精神:: QI解析器:解析的元素的索引 [英] Boost::Spirit::QI parser: index of parsed element

查看:158
本文介绍了的boost ::精神:: QI解析器:解析的元素的索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能(使用boost ::精神:: QI)从一个逗号分隔的字符串分析数字,所以我得到每个解析数的指数?

Is it possible (using Boost::Spirit::QI) to parse numbers from a comma separated string so that I get the index of each parsed number?

假设我有一个字符串23,123,65,1,我想给这些号码的给定位置(0,1,2插入到一个矩阵, 3)。一个办法做到这一点将向数字解析成一个std :: vector的,然后将它们复制到矩阵行,但它并不是特别快。

Suppose I have a string "23,123,65,1" and I want to insert each of these numbers into a matrix at given locations (0, 1, 2, 3). One way to do it would to parse the numbers into an std::vector and then copy them to the matrix row, but it isn't particularly fast.

目前我使用的矢量变种:

Currently I'm using the vector variant:

Matrix data(10, 4);
int row = 0;
int col = 0;
std::string str = "23,123,65,1";
std::vector<double> res;
if (qi::parse(str.begin(), str.end(), qi::double_ % ',', res))
{
  std::for_each(res.begin(), res.end(), [&col, &data, &row](double elem) {

      data(row, col) = elem;
      col++;
});
}

这将会是真棒,如果解析器有一个成功的回调需要一个lambda函数或类似的功能。

It'd be awesome if the parser had a success callback that takes a lambda function or a similar feature.

推荐答案

有多种方法。


  • 我想通常建议相反,是用经过深思熟虑的重复(N)前pressions直接暴露的容器的属性的(如矢量&lt;矢量&lt;&双GT;&GT; )。

  • What I'd usually recommend instead, is using well thought out repeat(n) expressions with directly exposed container attributes (like vector<vector<double> >).

在什么看起来的要寻找的是与国家语义动作。 (这是自法/ yacc的到来常见的做法)。

What you seem to be looking for is semantic actions with state. (This is common practice coming from lex/yacc).

我在下面(1,2和3)。


  • 先进的技术是使用的自定义点的允许圣灵直接把你的矩阵键入作为容器的属性和覆盖插入逻辑,它使用精神特质:: 。对于这种做法我指的是这样的回答:<一href=\"http://stackoverflow.com/questions/12520649/pass-attribute-to-child-rule-in-boost-spirit/12527010#12527010\">pass归因于独生子女政策在升压精神。

  • An advanced technique is using customization points to allow Spirit to directly treat your Matrix type as a container attribute and override the insertion logic for it using spirit::traits. For this approach I refer to this answer: pass attribute to child rule in boost spirit.

下面是一个相对简单的方法:

Here is a relatively straightforward approach:


  1. 直接解析成一个矢量&lt;矢量&lt;&双GT; &GT; 满code在线直播

  1. parsing directly into a vector<vector<double> > (full code live online)

qi::rule<It, Matrix::value_type(size_t cols), qi::blank_type> row;
qi::rule<It, Matrix(size_t rows,size_t cols), qi::blank_type> matrix;

row    %= skip(char_(" \t,")) [ repeat(_r1) [ double_ ] ];
matrix %= eps // [ std::cout << phx::val("debug: ") << _r1 << ", " << _r2 << "\n" ]
       >> repeat(_r1) [ row(_r2) >> (eol|eoi) ];

用法:

if (qi::phrase_parse(f,l,parser(10, 4),qi::blank, m))
    std::cout << "Wokay\n";
else
    std::cerr << "Uhoh\n";


  • 同样的,但适应一个矩阵结构(满code住这里

  • Similarly, but adapting a Matrix struct (full code live here)

    struct Matrix
    {
        Matrix(size_t rows, size_t cols) : _cells(), _rows(rows), _cols(cols) { }
    
        double       & data(size_t col, size_t row)       { return _cells.at(row).at(col); } 
        const double & data(size_t col, size_t row) const { return _cells.at(row).at(col); } 
    
        size_t columns() const { return _cols; }
        size_t rows()    const { return _rows; }
    
        std::vector<std::vector<double> > _cells;
        size_t _rows, _cols;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(Matrix, (std::vector<std::vector<double> >,_cells))
    

    用法

    Matrix m(10, 4);
    
    if (qi::phrase_parse(f,l,parser(m.rows(),m.columns()),qi::blank, m))
        std::cout << "Wokay\n";
    else
        std::cerr << "Uhoh\n";
    


  • 3。这是更多的工作,但可能更灵活。你会定义一个多态型可赎回在给定的单元格中插入值:

    Using semantic actions/qi::locals

    3. This is more work, but potentially more flexible. You'd define a polymorphic callable type to insert a value at a given cell:

    struct MatrixInsert
    {
        template <typename, typename, typename, typename> struct result { typedef bool type; };
        template <typename Matrix, typename Row, typename Col, typename Value>
            bool operator()(Matrix &m, Row& r, Col& c, Value v) const
            {
                if (r < m.rows() && c < m.columns())
                {
                    m.data(r, c++) = v;
                    return true; // parse continues
                }
                return false;    // fail the parse
            }
    };
    
    BOOST_PHOENIX_ADAPT_CALLABLE(matrix_insert, MatrixInsert, 4)
    

    最后一行使这是一个凤凰懒的功能,这样你就可以在你的语义动作使用它没有怪异的绑定语法:

    The last line makes this a phoenix lazy function, so you can use it without weird bind syntax in your semantic actions:

    qi::rule<It, Matrix(), qi::blank_type, qi::locals<size_t /*_a: row*/, size_t/*_b: col*/> > matrix;
    matrix = eps    [ _a = 0 /*current row*/ ]
         >> (
                eps     [ _b = 0 /*current col*/ ] 
             >> double_ [ _pass = matrix_insert(_val, _a, _b, _1) ] % ','
            ) % (eol    [ ++_a /*next row*/])
         ;
    

    全部code是,再 住在liveworkspace.org

    Full code is, again live on liveworkspace.org

    这篇关于的boost ::精神:: QI解析器:解析的元素的索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆