Boost.Spirit - 如何使用重复解析为结构
Boost.Spirit - How to use repeat to parse into a struct?
我正在尝试制作一个小程序来使用 Boost.Spirit 解析来自/proc/stat 的 cpu 使用信息。它大部分工作,但是在使用repeat时我无法编译语法。我错过了什么?
整个代码:
#include <vector>
#include "boost/fusion/include/adapt_struct.hpp"
#define BOOST_SPIRIT_DEBUG
#include "boost/spirit/include/qi.hpp"
#include "boost/iostreams/device/mapped_file.hpp"
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct Cpu
{
unsigned int user;
unsigned int nice;
unsigned int system;
unsigned int idle;
unsigned int iowait;
unsigned int irq;
unsigned int softirq;
unsigned int steal;
unsigned int guest;
unsigned int guest_nice;
};
BOOST_FUSION_ADAPT_STRUCT(
Cpu,
(unsigned int, user)
(unsigned int, nice)
(unsigned int, system)
(unsigned int, idle)
(unsigned int, iowait)
(unsigned int, irq)
(unsigned int, softirq)
(unsigned int, steal)
(unsigned int, guest)
(unsigned int, guest_nice)
)
template< typename Iter, typename Skip = ascii::blank_type >
struct Cpu_parser : qi::grammar< Iter, Cpu(), Skip >
{
qi::rule< Iter, Cpu(), Skip > start;
Cpu_parser() : Cpu_parser::base_type(start)
{
using namespace qi;
start = lexeme[lit("cpu") >> omit[-uint_]] >> repeat(10)[uint_];
//start = lexeme[lit("cpu") >> omit[-uint_]] >> uint_ >> uint_ >> uint_ >> uint_ >> uint_ >> uint_ >> uint_ >> uint_ >> uint_ >> uint_;
BOOST_SPIRIT_DEBUG_NODE(start);
}
};
int main(int argc, char** argv)
{
std::vector< Cpu > cpus;
{
std::ifstream ifs("/proc/stat");
ifs >> std::noskipws;
Cpu_parser< boost::spirit::istream_iterator > cpu_parser;
std::cout << phrase_parse(
boost::spirit::istream_iterator(ifs),
boost::spirit::istream_iterator(),
cpu_parser % qi::eol,
ascii::blank,
cpus) << std::endl;
}
return 0;
}
带有所有单个uint_s的注释行工作正常,但我想知道重复我做错了什么。
如果我用无符号整数向量替换 CPU 结构,我也可以重复工作。
你不能。容易。这是因为repeat()[]
合成容器属性。您的结构是一个融合序列,而不是一个容器。
你/可以/假装它
- 不使用FUSION_ADAPT_STRUCT
- 定义自定义点(例如
is_container<Cpu>
.这里有一个示例描述了文档中如何执行操作:http://www.boost.org/doc/libs/1_60_0/libs/spirit/doc/html/spirit/advanced/customize/iterate/container_iterator.html#spirit.advanced.customize.iterate.container_iterator.example。还有一个答案描述了如何使其与std::array
一起工作(
不过,有个好消息:
"好消息">
对于融合序列,qi::auto_
解析器知道该怎么做!
这样可以去除80%的脂肪:
住在科里鲁
#include "boost/fusion/include/adapt_struct.hpp"
#include "boost/spirit/include/qi.hpp"
#include <fstream>
struct Cpu {
unsigned user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;
};
BOOST_FUSION_ADAPT_STRUCT(Cpu, user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice)
int main() {
std::vector<Cpu> cpus;
bool ok = [&cpus] {
using It = boost::spirit::istream_iterator;
using namespace boost::spirit::qi;
std::ifstream ifs("/proc/stat");
return parse(
It(ifs >> std::noskipws), {},
("cpu" >> -omit[uint_] >> skip(blank)[auto_]) % eol,
cpus);
}();
std::cout << std::boolalpha << ok << std::endl;
}
注意
- 输出为
true
。只是不在 Coliru 上(那里无法访问/proc/cpu(。- lambda 技巧是为了使
using namespace
作用域化,同时能够返回ok
的值。
相关文章:
- Boost.Spirit.Qi 语法,用于 Boost.Fusion 自适应结构中的默认值
- 如何使用 spirit x3 将解析的结果移动到结构中
- boost :: Spirit :: Karma语法:逗号从结构上划定了带有选件属性的输出
- 使用 Spirit 将 std::vector<std::vector<double> 解析为结构属性
- 无法使用 Boost Spirit X3 解析空的 C++ 结构
- boost :: Spirit属性分配:struct is_nullary:基本类型无法成为结构或类型
- 在 Boost.Spirit 中,为什么向量(包裹在结构中)需要融合包装器,而不是变体?
- 如何将 std::vector<std::string> 转换为 boost::spirit 中结构的成员?
- Spirit Qi用简单的C风格结构化输入解析问题
- 如何用boost :: Spirit从字符串中提取多个结构
- boost :: Spirit :: Qi-与语法结构中的实例成员一起工作
- Boost Spirit Parser用三个字符串的矢量编译成一个结构,自适应不工作
- 使用Boost Spirit使用数组解析结构
- 正在分析boost::spirit上的递归结构
- 使用 boost::spirit 解析类似 c 结构的声明
- 使用 boost::spirit 在解析结构时将解析的值默认为较早的值
- 如何使用boost::spirit将文本解析为结构
- boost::spirit: qi::rule 或包含 qi::rule 作为解析结果的结构
- Boost.Spirit - 如何使用重复解析为结构
- 在 Boost Spirit 2.5.2 中按层次结构拆分语法