提升精神 X3 eol 意外行为
Boost Spirit X3 eol unexpected behaviour
这个问题与boost-spirit-x3-parse-into-structs严格相关
我有这个语法
#include <iostream>
//#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
struct sectionInfo
{
std::string name;
int number = 0;
float pitch = 0.0f;
int visible = 0;
float minCutsTblSize = 0.0f;
//technology section attributes
float gridResolution = 0.0f;
float lengthPrecision = 0.0f;
};
const char START_SECTION = '{';
const char END_SECTION = '}';
const char QUOTE = '"';
const char EQUALS = '=';
const char* LAYER_SECTION = "Layer";
const char* TECHNOLOGY_SECTION = "Technology";
const char* NUMBER_ATTR = "layerNumber";
const char* VISIBLE_ATTR = "visible";
const char* COLOR_ATTR = "color";
const char* PITCH_ATTR = "pitch";
const char* MIN_CUTS_TBL_SIZE_ATTR = "minCutsTblSize";
const char* GRID_RESOLUTION_ATTR = "gridResolution";
const char* LENGTH_PRECISION_ATTR = "lengthPrecision";
namespace Parser {
namespace x3 = boost::spirit::x3;
namespace detail {
template <typename T> auto propagate(T member) {
return [=](auto& ctx) { x3::traits::move_to(x3::_attr(ctx), x3::_val(ctx).*member); };
}
template <typename T = sectionInfo, typename P>
auto rule(const char* debug, P p) { return x3::rule<struct _, T> {debug} = x3::skip(x3::space)[p]; };
auto quoted = rule<std::string>("quoted", x3::lexeme[QUOTE >> +(x3::char_ - QUOTE) >> QUOTE]);
template <typename T> auto make_member_parser(bool T::* const member) { return x3::bool_[propagate(member)]; }
template <typename T> auto make_member_parser(int T::* const member) { return x3::int_[propagate(member)]; }
template <typename T> auto make_member_parser(double T::* const member) { return x3::double_[propagate(member)]; }
template <typename T> auto make_member_parser(float T::* const member) { return x3::double_[propagate(member)]; }
template <typename T> auto make_member_parser(std::string T::* const member) { return quoted[propagate(member)]; }
auto property = [](auto label, auto member) {
return x3::as_parser(label) >> EQUALS >> make_member_parser(member);
};
}
using detail::rule;
using detail::propagate;
using detail::property;
using detail::quoted;
auto number = property(NUMBER_ATTR, §ionInfo::number);
auto visible = property(VISIBLE_ATTR, §ionInfo::visible);
auto pitch = property(PITCH_ATTR, §ionInfo::pitch);
auto minCutsTblSize = property(MIN_CUTS_TBL_SIZE_ATTR, §ionInfo::minCutsTblSize);
auto lengthPrecision = property(LENGTH_PRECISION_ATTR, §ionInfo::lengthPrecision);
auto gridResolution = property(GRID_RESOLUTION_ATTR, §ionInfo::gridResolution);
auto skipLine = *(x3::char_ - x3::eol);
x3::rule<struct sectionInfoId, sectionInfo> const layer = "layer";
x3::rule<struct mainRuleId, std::vector<sectionInfo>> const mainRule = "mainRule";
auto layer_def =
LAYER_SECTION >> quoted[propagate(§ionInfo::name)] >> START_SECTION >> x3::eol
>> *( (number | visible | pitch | minCutsTblSize | lengthPrecision | gridResolution) >> +x3::eol )
>> END_SECTION;
auto skipper = x3::blank;
auto mainRule_def = *(*x3::eol >> layer >> *x3::eol);
BOOST_SPIRIT_DEFINE(layer, mainRule);
}
std::ostream& operator<<(std::ostream& os, const sectionInfo& s)
{
os
<< "name=" << " " << s.name << "n"
<< "number=" << " " << s.number << "n"
<< "visible=" << " " << s.visible << "n"
<< "pitch=" << " " << s.pitch << "n"
<< "minCutsTblSize=" << " " << s.minCutsTblSize << "n"
<< "lengthPrecision=" << " " << s.lengthPrecision << "n"
<< "gridResolution=" << " " << s.gridResolution << "nn";
return os;
}
int main() {
std::stringstream ss;
ss
<<"rnLayer "UBMB" {rn"
<< " layerNumber = 170rn"
<< " pitch = 33.6rn"
<< "}rn"
<< "rn"
<< "Layer "RV" {rn"
<< " gridResolution = 0.34rn"
<< " minCutsTblSize = 22.7rn"
<< " layerNumber = 85rn"
<< " visible = 2rn"
<< " pitch = 331rn"
<< "}rn"
<< " rn"
<< "Layer "foffo" {rn"
<< " layerNumber = 125rn"
<< " pitch = 0.005rn"
<< " gridResolution = 21.7rn"
<< " lengthPrecision = 0.15rn"
<< "}rn"
<< "rn";
std::vector<sectionInfo> sections;
auto sample = ss.str();
auto f = sample.begin(), l = sample.end();
bool ok = boost::spirit::x3::phrase_parse(
f, l,
Parser::mainRule,
Parser::skipper,
sections
);
if (ok && f==l)
{
std::cout << "nn Parsed successfully nn";
for(auto& s : sections)
{
std::cout << s;
}
}
else
std::cout << "Parse failedn";
}
成功解析输入:
输出为:
名称 = UBMB 数字= 170 可见= 0 节距= 33.6 最小切割TblSize= 0 长度精度= 0 网格分辨率= 0
名称= 房车 数字= 85 可见= 2 音高= 331 最小切割TblSize= 22.7 长度精度= 0 网格分辨率= 0.34
名称= 福福 数字= 125 可见= 0 间距= 0.005 最小切割TblSize= 0 长度精度= 0.15 网格分辨率= 21.7
出现问题是因为我需要跳过一些行,即具有不感兴趣的属性的行(未在我的语法中定义(
编辑:例如,可能有一个属性虚拟="foo",我想跳过它。
为此,图层规则
auto layer_def = LAYER_SECTION >> quoted[propagate(§ionInfo::name)] >> START_SECTION >> x3::eol
>> *( (number | visible | pitch | minCutsTblSize | lengthPrecision | gridResolution ) >> +x3::eol )
>> END_SECTION;
成为
auto layer_def = LAYER_SECTION >> quoted[propagate(§ionInfo::name)] >> START_SECTION >> x3::eol
>> *( (number | visible | pitch | minCutsTblSize | lengthPrecision | gridResolution | skipLine) >> +x3::eol )
>> END_SECTION;
解析器成功,但输出现在
名称= UBMB 编号 = 125 可见= 2 间距 = 0.005 分钟切割TblSize= 22.7 长度精度= 0.15 网格分辨率= 21.7
这是错误的(只有一个部分,这里和那里的属性...
很明显,问题出在跳过线规则上
auto skipLine = *(x3::char_ - x3::eol);
我不知道为什么。 我认为很明显规则 *(字符 - eol(>> eol 会匹配任何行,但我想它不是..
有什么线索吗?
首先,我会简化跳过。船长不属于调用站点,因为它对语法很重要。将其封装到 mainRule 中,并简化:
auto mainRule_def = x3::skip(x3::blank) [ -layer % x3::eol ];
-layer
表达式是接受空行的技巧。现在使用解析器变成:
bool ok = boost::spirit::x3::parse(f, l, Parser::mainRule, sections);
下一篇:skipLine
也吃'}'
,使一切都分崩离析:之后的所有内容都被视为同一层的(无效(属性,最后没有END_SECTION
因此语法不匹配。
只是:
auto skipLine = *(x3::char_ - x3::eol - END_SECTION);
专业提示:
如有疑问,请调试:Live On Coliru
// debug it auto skipLine = x3::rule<struct skipLine_> {"skipLine"} = *(x3::char_ - x3::eol/* - END_SECTION*/);
完整演示
有一些小的简化
住在科里鲁
#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/spirit/home/x3.hpp>
struct sectionInfo {
std::string name;
int number = 0;
float pitch = 0.0f;
int visible = 0;
float minCutsTblSize = 0.0f;
// technology section attributes
float gridResolution = 0.0f;
float lengthPrecision = 0.0f;
};
char const START_SECTION = '{';
char const END_SECTION = '}';
char const QUOTE = '"';
char const EQUALS = '=';
char const* LAYER_SECTION = "Layer";
char const* TECHNOLOGY_SECTION = "Technology";
char const* NUMBER_ATTR = "layerNumber";
char const* VISIBLE_ATTR = "visible";
char const* COLOR_ATTR = "color";
char const* PITCH_ATTR = "pitch";
char const* MIN_CUTS_TBL_SIZE_ATTR = "minCutsTblSize";
char const* GRID_RESOLUTION_ATTR = "gridResolution";
char const* LENGTH_PRECISION_ATTR = "lengthPrecision";
namespace Parser {
namespace x3 = boost::spirit::x3;
namespace detail {
template <typename T> auto propagate(T member) {
return [=](auto &ctx) { x3::traits::move_to(x3::_attr(ctx), x3::_val(ctx).*member); };
}
template <typename T = sectionInfo, typename P> auto rule(const char *debug, P p) {
return x3::rule<struct _, T>{ debug } = x3::skip(x3::space)[p];
};
auto quoted = rule<std::string>("quoted", x3::lexeme[QUOTE >> +(x3::char_ - QUOTE) >> QUOTE]);
#define MMP_(T, p) template <typename U> auto make_member_parser(T U::*const member) { return (p)[propagate(member)]; }
MMP_(bool, x3::bool_);
MMP_(int, x3::int_);
MMP_(double, x3::double_);
MMP_(float, x3::double_);
MMP_(std::string, quoted);
#undef MMP_
auto property = [](auto label, auto member) { return x3::as_parser(label) >> EQUALS >> make_member_parser(member); };
}
using detail::rule;
using detail::propagate;
using detail::property;
using detail::quoted;
auto number = property(NUMBER_ATTR, §ionInfo::number);
auto visible = property(VISIBLE_ATTR, §ionInfo::visible);
auto pitch = property(PITCH_ATTR, §ionInfo::pitch);
auto minCutsTblSize = property(MIN_CUTS_TBL_SIZE_ATTR, §ionInfo::minCutsTblSize);
auto lengthPrecision = property(LENGTH_PRECISION_ATTR, §ionInfo::lengthPrecision);
auto gridResolution = property(GRID_RESOLUTION_ATTR, §ionInfo::gridResolution);
auto skipLine = *(x3::char_ - x3::eol - END_SECTION);
x3::rule<struct sectionInfoId, sectionInfo> const layer = "layer";
x3::rule<struct mainRuleId, std::vector<sectionInfo> > const mainRule = "mainRule";
auto layer_def =
LAYER_SECTION >> quoted[propagate(§ionInfo::name)]
>> START_SECTION >> x3::eol
>> *((number | visible | pitch | minCutsTblSize | lengthPrecision | gridResolution | skipLine) >> +x3::eol)
>> END_SECTION
;
auto mainRule_def = x3::skip(x3::blank) [ -layer % x3::eol ];
BOOST_SPIRIT_DEFINE(layer, mainRule);
}
std::ostream &operator<<(std::ostream &os, const sectionInfo &s) {
return os
<< "name=" << " " << s.name << "n"
<< "number=" << " " << s.number << "n"
<< "visible=" << " " << s.visible << "n"
<< "pitch=" << " " << s.pitch << "n"
<< "minCutsTblSize=" << " " << s.minCutsTblSize << "n"
<< "lengthPrecision=" << " " << s.lengthPrecision << "n"
<< "gridResolution=" << " " << s.gridResolution << "nn";
}
int main() {
std::string const sample =
"rnLayer "UBMB" {rn"
" layerNumber = 170rn"
" pitch = 33.6rn"
"}rn"
"rn"
"Layer "RV" {rn"
" gridResolution = 0.34rn"
" minCutsTblSize = 22.7rn"
" layerNumber = 85rn"
" visible = 2rn"
" pitch = 331rn"
"}rn"
" rn"
"Layer "foffo" {rn"
" layerNumber = 125rn"
" pitch = 0.005rn"
" gridResolution = 21.7rn"
" lengthPrecision = 0.15rn"
"}rn"
"rn";
std::vector<sectionInfo> sections;
{
auto f = sample.begin(), l = sample.end();
bool ok = boost::spirit::x3::parse(f, l, Parser::mainRule, sections);
if (ok && f == l) {
std::cout << "nn Parsed successfully nn";
for (auto &s : sections) {
std::cout << s;
}
} else
std::cout << "Parse failedn";
}
}
指纹
Parsed successfully
name= UBMB
number= 170
visible= 0
pitch= 33.6
minCutsTblSize= 0
lengthPrecision= 0
gridResolution= 0
name= RV
number= 85
visible= 2
pitch= 331
minCutsTblSize= 22.7
lengthPrecision= 0
gridResolution= 0.34
name= foffo
number= 125
visible= 0
pitch= 0.005
minCutsTblSize= 0
lengthPrecision= 0.15
gridResolution= 21.7
- 在C++中对T*类型执行std::move的意外行为
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 处理除以零会导致<csignal>意外行为
- vscode下的Arduino代码出现意外编译错误
- 使用++运算符会导致意外的结果
- 套接字读取后,我在缓冲区中看到意外输入
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 使用vscode调试时,GDB意外退出
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 尝试将字符串/字符转换为整数会产生意外结果
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- C++标头错误 C2238 意外标记";"
- C++中意外的多头值
- vector.size() 在比较中意外工作
- 使用 malloc() 时出现意外大小
- 多线程程序中出现意外的内存泄漏
- 为什么static_cast基础类型的枚举类int8_t获得意外值?
- 字符串比较中的意外输出
- 我的代码中的意外价值以及我如何修复它
- 提升精神 X3 eol 意外行为