使用升灵气qi::iter_pos却无法获取价值
Using Boost Spirit Qi qi::iter_pos but can't capture value
我需要跟踪一些项目在我使用升灵气解析的文本中的位置。我找到了 this example 并适应了这样:
#include <iostream>
#include <string>
#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
template<typename Iterator>
struct CurrentPos
{
CurrentPos()
{
save_start_pos = qi::omit[boost::spirit::repository::qi::iter_pos[
phx::bind(&CurrentPos::setStartPos, this, qi::_1)]];
current_pos = boost::spirit::repository::qi::iter_pos[
qi::_val = phx::bind(&CurrentPos::getCurrentPos, this, qi::_1)];
}
qi::rule<Iterator> save_start_pos;
qi::rule<Iterator, std::size_t()> current_pos;
private:
void setStartPos(const Iterator &iterator)
{
start_pos_ = iterator;
}
std::size_t getCurrentPos(const Iterator &iterator)
{
return std::distance(start_pos_, iterator);
}
Iterator start_pos_;
};
using InfoTuple = std::tuple<std::size_t, std::uint32_t>;
struct Header
{
std::uint32_t x;
InfoTuple y;
};
BOOST_FUSION_ADAPT_STRUCT(
Header,
(std::uint32_t, x)
(InfoTuple, y)
)
template<typename Iterator>
struct HeaderParse
: boost::spirit::qi::grammar<Iterator, Header()>
{
HeaderParse()
: HeaderParse::base_type(_start)
{
using boost::spirit::qi::uint_parser;
_thing = (current_pos.current_pos >> uint_parser<std::uint32_t, 10, 1, 3>());
_start = current_pos.save_start_pos
>> '<'
>> uint_parser<std::uint32_t, 10, 1, 3>()
>> '>'
>> _thing;
}
qi::rule<Iterator, InfoTuple()> _thing;
qi::rule<Iterator, Header()> _start;
CurrentPos<Iterator> current_pos;
};
int main()
{
const std::string d1 = "<13>937";
const HeaderParse<std::string::const_iterator> parser;
Header header;
std::string::const_iterator begin = d1.begin();
std::string::const_iterator end = d1.end();
assert(boost::spirit::qi::parse(begin, end, parser, header));
assert(begin == end);
std::cout << "x : " << header.x << std::endl;
std::cout << "y : " << std::get<1>(header.y) << std::endl;
std::cout << "y pos: " << std::get<0>(header.y) << std::endl;
}
当我 运行 它时,我看到以下输出:
$> ./testme
x : 13
y : 0
y pos: 4
出于某种原因,它不会捕获值 937
。
我在 Coliru 上试过这个,起初它没有编译,现在我不断得到 "execution expired"。请参阅此处:https://coliru.stacked-crooked.com/a/724c7fcd296c8803 但这让我怀疑它是否有效。我使用的是 clang,而 Coliru 使用的是 gcc。
有人可以提供任何关于为什么这行不通的见解吗?
由于缺少 Fusion std::tuple
集成 header (boost/fusion/include/std_tuple.hpp
),您的示例无法为我编译。添加后,示例编译并输出预期结果。 https://wandbox.org/permlink/wOf8JxnKKeBGCihk
P.S:我建议不要在解析器中计算偏移量,它不会为您节省任何东西,存储迭代器本身具有相同的内存占用,但复杂性和痛苦更少。
我需要跟踪一些项目在我使用升灵气解析的文本中的位置。我找到了 this example 并适应了这样:
#include <iostream>
#include <string>
#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
template<typename Iterator>
struct CurrentPos
{
CurrentPos()
{
save_start_pos = qi::omit[boost::spirit::repository::qi::iter_pos[
phx::bind(&CurrentPos::setStartPos, this, qi::_1)]];
current_pos = boost::spirit::repository::qi::iter_pos[
qi::_val = phx::bind(&CurrentPos::getCurrentPos, this, qi::_1)];
}
qi::rule<Iterator> save_start_pos;
qi::rule<Iterator, std::size_t()> current_pos;
private:
void setStartPos(const Iterator &iterator)
{
start_pos_ = iterator;
}
std::size_t getCurrentPos(const Iterator &iterator)
{
return std::distance(start_pos_, iterator);
}
Iterator start_pos_;
};
using InfoTuple = std::tuple<std::size_t, std::uint32_t>;
struct Header
{
std::uint32_t x;
InfoTuple y;
};
BOOST_FUSION_ADAPT_STRUCT(
Header,
(std::uint32_t, x)
(InfoTuple, y)
)
template<typename Iterator>
struct HeaderParse
: boost::spirit::qi::grammar<Iterator, Header()>
{
HeaderParse()
: HeaderParse::base_type(_start)
{
using boost::spirit::qi::uint_parser;
_thing = (current_pos.current_pos >> uint_parser<std::uint32_t, 10, 1, 3>());
_start = current_pos.save_start_pos
>> '<'
>> uint_parser<std::uint32_t, 10, 1, 3>()
>> '>'
>> _thing;
}
qi::rule<Iterator, InfoTuple()> _thing;
qi::rule<Iterator, Header()> _start;
CurrentPos<Iterator> current_pos;
};
int main()
{
const std::string d1 = "<13>937";
const HeaderParse<std::string::const_iterator> parser;
Header header;
std::string::const_iterator begin = d1.begin();
std::string::const_iterator end = d1.end();
assert(boost::spirit::qi::parse(begin, end, parser, header));
assert(begin == end);
std::cout << "x : " << header.x << std::endl;
std::cout << "y : " << std::get<1>(header.y) << std::endl;
std::cout << "y pos: " << std::get<0>(header.y) << std::endl;
}
当我 运行 它时,我看到以下输出:
$> ./testme
x : 13
y : 0
y pos: 4
出于某种原因,它不会捕获值 937
。
我在 Coliru 上试过这个,起初它没有编译,现在我不断得到 "execution expired"。请参阅此处:https://coliru.stacked-crooked.com/a/724c7fcd296c8803 但这让我怀疑它是否有效。我使用的是 clang,而 Coliru 使用的是 gcc。
有人可以提供任何关于为什么这行不通的见解吗?
由于缺少 Fusion std::tuple
集成 header (boost/fusion/include/std_tuple.hpp
),您的示例无法为我编译。添加后,示例编译并输出预期结果。 https://wandbox.org/permlink/wOf8JxnKKeBGCihk
P.S:我建议不要在解析器中计算偏移量,它不会为您节省任何东西,存储迭代器本身具有相同的内存占用,但复杂性和痛苦更少。