保存令牌位置

时间:2014-08-06 11:40:09

标签: c++ boost boost-spirit boost-spirit-qi

我需要将解析后的令牌位置与令牌一起保存。这是简化的示例代码。

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace phoenix = boost::phoenix;

    struct double_w_pos
    {
        double_w_pos() : d(-1.0), pos(0) {}
        double_w_pos(double d, size_t p) : d(d), pos(p) {}
        double d;
        size_t pos;
    };

    template <typename Iterator>
    bool parse_numbers(Iterator first, Iterator last, std::vector<double_w_pos>& v)
    {
        using qi::double_;
        using qi::phrase_parse;
        using qi::_1;
        using ascii::space;
        using phoenix::at_c;
        using phoenix::push_back;

        bool r = phrase_parse(first, last,
            (
                double_[push_back(phoenix::ref(v), phoenix::construct<double_w_pos>(qi::_1, 0))] % ','
            )
            ,
            space);

        if (first != last)
            return false;
        return r;
    }
}

int main()
{
    std::vector<client::double_w_pos> v;
    std::string str = "2.0, 3.45, 5.67, 2.08";

    client::parse_numbers(str.begin(), str.end(), v);

    for(auto i : v)
        std::cout << i.d << " at " << i.pos << ", ";
    std::cout << std::endl;

    return 0;
}

您可以在Coliru上直播 现在0被保存为令牌位置。我怎样才能获得实际的解析位置。它不必是size_t。它可以是迭代器或任何东西,可用于识别文本中的位置,找到哪个令牌。 感谢。

更新 我没有设法直接从解析中获得size_t的位置,但我设法获得了迭代器位置。这不是我需要的,但总比没有好。 这是代码

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace phoenix = boost::phoenix;

    struct double_w_pos
    {
        double_w_pos(double d, std::string::iterator p) : d(d), pos(p) {}
        double d;
        std::string::iterator pos;
    };


    template <typename Iterator>
    bool parse_numbers(Iterator first, Iterator last, std::vector<double_w_pos>& v)
    {
        using qi::double_;
        using qi::phrase_parse;
        using qi::_1;
        using ascii::space;
        using phoenix::at_c;
        using phoenix::push_back;
        using phoenix::begin;
        using boost::spirit::repository::qi::iter_pos;

        bool r = phrase_parse(first, last,
            (
               (iter_pos >> qi::double_)[push_back(phoenix::ref(v), phoenix::construct<double_w_pos>(qi::_2,  qi::_1))] % ","
            )
            ,
            space);

        if (first != last)
            return false;
        return r;
    }
}

int main()
{
    std::vector<client::double_w_pos> v;
    std::string str = "2.0, 3.45, 5.67, 2.08";

    client::parse_numbers(str.begin(), str.end(), v);

    for(auto i : v)
        std::cout << i.d << " at " << std::distance(str.begin(), i.pos) << ", ";
    std::cout << std::endl;

    return 0;
}

Coliru link

1 个答案:

答案 0 :(得分:1)

您可以按照以下指南进行操作:

但到目前为止,我首选的方法(最少侵入性)使用on_success,在使用它的样本之外,遗憾地记录不足:

相关问题