簡體   English   中英

Boost :: Spirit :: QI解析器:已解析元素的索引

[英]Boost::Spirit::QI parser: index of parsed element

是否可以(使用Boost :: Spirit :: QI)從逗號分隔的字符串中解析數字,以便獲得每個已解析數字的索引?

假設我有一個字符串"23,123,65,1" ,我想將這些數字中的每一個插入到給定位置(0,1,2,3)的矩陣中。 一種方法是將數字解析為std :: vector,然后將它們復制到矩陣行,但速度並不是特別快。

目前我正在使用矢量變體:

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函數或類似的功能,那就太棒了。

有很多方法。

  • 我通常建議的是使用經過深思熟慮的repeat(n)表達式與直接暴露的容器屬性 (如vector<vector<double> > )。

  • 似乎在尋找的是與國家的語義行為。 (這是來自lex / yacc的常見做法)。

我在下面的三個完整演示中處理這些方法 (1.,2。和3.)

  • 一種高級技術是使用自定義點來允許Spirit直接將Matrix類型視為容器屬性,並使用spirit::traits覆蓋它的插入邏輯。 對於這種方法,我引用這個答案: 在boost精神中將屬性傳遞給子規則

使用繼承的屬性

這是一個相對簡單的方法:

  1. 直接解析為vector<vector<double> >完整代碼在線直播

     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"; 
  2. 同樣,但適應Matrix結構( 完整代碼在這里生活

     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"; 

使用語義動作/ qi :: locals

3.這是更多的工作,但可能更靈活。 您將定義一個多態可調用類型以在給定單元格中插入值:

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)

最后一行使它成為一個phoenix惰性函數,因此您可以在語義操作中使用它而不需要奇怪的綁定語法:

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*/])
     ;

完整代碼再次在liveworkspace.org上發布

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM