- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这个问题与 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";
}
成功解析输入:
输出是:
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
出现问题是因为我需要跳过一些行,即具有不感兴趣的属性的行(未在我的语法中定义)
编辑:例如,可能有一个我想跳过的属性 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;
解析器成功,但现在输出是
name= UBMB number= 125 visible= 2 pitch= 0.005 minCutsTblSize= 22.7 lengthPrecision= 0.15 gridResolution= 21.7
这是错误的(只有一个部分,在这里和那里使用的属性...)
很明显问题出在skipLine规则上
auto skipLine = *(x3::char_ - x3::eol);
我不知道为什么。我认为规则 *(char - eol) >> eol 很明显会匹配任何行,但我想它不是..
有什么线索吗?
最佳答案
首先,我会简化跳过。 skipper 不属于调用站点,因为它对语法很重要。将其封装到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);
Pro Tip:
When in doubt, debug: 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 << "\n\n";
}
int main() {
std::string const sample =
"\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 f = sample.begin(), l = sample.end();
bool ok = boost::spirit::x3::parse(f, l, Parser::mainRule, 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";
}
}
打印
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++ - Boost Spirit X3 eol 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45753683/
这与这个问题非常相似: What is the differrence between `* text=auto` and `* text eol=lf` in .gitattributes? 但我特
Notepad++(甚至使用其他工具)是否有任何方法可以一次性在多个文件上自动更改行结尾? 即将 Windows EOL (CRLF) 和 UNIX EOL (LF) 文件的混合转换为所有 Windo
我正在尝试根据设置更改字符串的行结尾。基本上我有字符串,大多以 LF 结尾,很少有其他东西,但它会发生,并且我希望能够将它们更改为 CRLF 或 CR(如果被要求),或者确保它们是纯粹的 LF(如果被
当我尝试在我的服务器上上传一个 php 文件时,我收到一条消息:"Parse error: ..." 我知道这是什么意思,但问题是别的。 如果我在本地服务器上编辑文件(我的计算机上安装了 XAMPP)
我正在尝试创建一个输出文件以在类项目中使用,但在扫描此行上的字符串文字时它不断给出 EOL: outfile = open(r'C:\Users\kay\Documents\CCA Classes\C
这是我的代码并收到以下错误消息:第 8 行 sepFile=readFile.read().split('\')SyntaxError:扫描字符串文字时 EOL你可以帮帮我吗?谢谢。 import m
我有一个包含\n EOL 字符的制表符分隔文件,看起来像这样: User Name\tCode\tTrack\tColor\tNote\n\nUser Name2\tCode2\tTrack2\tCo
所以我正在尝试使用这段代码 我收到错误 SyntaxError: EOL while scanning string literal 代码: def clean_tweet(self, tweet):
在路径= bla bla行上,它在扫描字符串文字时显示EOL,即使它是用“”关闭的,我在我的代码中经常发生这种情况,这真的很烦人,因为我永远无法修复它。 import os import shutil
我试图在输入字符串中找到每个“a -> b, c, d”模式。我使用的模式如下: "^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$" 这个模式
我正在尝试使用简单的所见即所得编辑器。 JSLint 表示它有“Bad escapeing of EOL”。由于我是 javascript 的新手,我很难弄清楚它的含义,因为我正在使用在线找到的代码。
我正在为 Android 编写一个网络应用程序。根据协议(protocol)规范,每行的结尾必须是 CR/LF 组合。虽然我用自己的字符串生成它没有问题,但有时我必须处理用户输入并转换行尾。 我在内部
这个问题应该由 Oracle 支持人员在技术上回答,但他们的响应时间很慢。因此,我想问一下,是否有版本指南提到哪些版本的 Oracle Weblogic 已停产及其日期? http://www.ora
BufferedReader.readLine() 会自动删除 EOL 字符,我不能简单地执行 readLine(),然后在其末尾添加“\r”。我试过了 InputStream myFile = ne
在扫描字符串文字时,它不断出现EOL,但这是什么意思? 这是它不断调用错误的部分: if health2 <= 3: print ("With all the strength you have
我有这个方法: def get_chunksize(path): """ Breaks a file into chunks and yields the chunk sizes.
这个问题在这里已经有了答案: Remove the newline character in a list read from a file [duplicate] (5 个答案) 关闭 8 年前。
基本上我正在用 C 语言编写一个基于文本的角色扮演游戏,我想创建一个 map 系统。基本上,我遇到问题的功能是从如下所示的文件中读取“文本映射”: ----------\n |c x [\n
我正在尝试从给定的 .txt 或 .csv 平面文件中识别 EOL 字符是什么。根据平面文件中第一行数据的 EOL 字符是什么,我想相应地处理该文件中的数据(我正在使用批量加载在 SQL Server
有人可以帮我修改这些脚本以忽略错误并继续运行吗?我只需要弄清楚如何使脚本跳过这些错误并完成其余的行。 这是完整的 Python 脚本: # Import system modules import s
我是一名优秀的程序员,十分优秀!