【发布时间】:2017-08-18 09:51:01
【问题描述】:
这个问题与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 << "\n\n";
return os;
}
int main() {
std::stringstream ss;
ss
<<"\r\nLayer \"UBMB\" {\r\n"
<< " layerNumber = 170\r\n"
<< " pitch = 33.6\r\n"
<< "}\r\n"
<< "\r\n"
<< "Layer \"RV\" {\r\n"
<< " gridResolution = 0.34\r\n"
<< " minCutsTblSize = 22.7\r\n"
<< " layerNumber = 85\r\n"
<< " visible = 2\r\n"
<< " pitch = 331\r\n"
<< "}\r\n"
<< " \r\n"
<< "Layer \"foffo\" {\r\n"
<< " layerNumber = 125\r\n"
<< " pitch = 0.005\r\n"
<< " gridResolution = 21.7\r\n"
<< " lengthPrecision = 0.15\r\n"
<< "}\r\n"
<< "\r\n";
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 << "\n\n Parsed successfully \n\n";
for(auto& s : sections)
{
std::cout << s;
}
}
else
std::cout << "Parse failed\n";
}
成功解析输入:
输出是:
名称= UBMB 数字= 170 可见= 0 间距= 33.6 minCutsTblSize= 0 长度精度= 0 网格分辨率= 0
名称=房车 数字= 85 可见= 2 间距= 331 minCutsTblSize=22.7 长度精度= 0 网格分辨率= 0.34
名称= foffo 数字= 125 可见= 0 间距= 0.005 minCutsTblSize= 0 长度精度= 0.15 网格分辨率= 21.7
问题出现是因为我需要跳过一些行,即具有不感兴趣的属性的行(未在我的语法中定义)
编辑:例如,可能有一个属性 dummy = "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 minCutsTblSize= 22.7 lengthPrecision= 0.15 gridResolution= 21.7
这是错误的(只有一节,这里和那里的属性......)
很明显问题出在skipLine规则中
auto skipLine = *(x3::char_ - x3::eol);
我不知道为什么。 我认为很明显规则 *(char - eol) >> eol 会匹配任何行,但我想它不是..
有什么线索吗?
【问题讨论】:
-
我注意到了 - 尚未使用的 - TECHNOLOGY_SECTION。你能告诉我们你真正想要解析的最终目标吗?我认为你可以更简单地完成这一切。并更好地匹配您的域。
-
@sehe 我真的不能 :) 顺便说一句,非常感谢您的贡献,您无法想象您的帮助有多大。
标签: c++ boost boost-spirit boost-spirit-x3