带有 post 跳过的惯用完全匹配
Idiomatic complete matching with post skipping
post-skipping 最惯用的方法是什么?更具体地说,我想确保在匹配我的最高规则后我的输入中没有 "non-skippable"(垃圾)字符。
auto const blankOrComment
= ascii::space
| x3::lexeme ['#' >> *(x3::char_ - x3::eol) >> -x3::eol ]
;
auto const program = rule<AstProgram>("program")
= *(as<AstDefinition> (definition > ";"))
;
auto const programEntry = x3::skip(blankOrComment) [program];
一个想法,我认为非常丑陋,如果主迭代器位置不是结束迭代器,则之后对 blankOrComment
进行单独的解析调用。我目前更好的想法是更改根规则:
auto const programEntry = x3::skip(blankOrComment) [program >> x3::omit[*blankOrComment]];
有没有更地道的方法?
最简单的破解方法是添加 >> eps
:Live On Coliru
请注意,我会努力使船长更具自我描述性:
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
同样,您可以使 postskip hack 更具自我描述性:
auto const post_skip = eps;
auto const program = "program" >> post_skip;
#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
namespace Parser {
namespace x3 = boost::spirit::x3;
namespace rules {
using namespace x3;
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
auto const post_skip = eps;
auto const program = "program" >> post_skip;
}
auto const programEntry = x3::skip(rules::skipper) [rules::program];
}
int main() {
using It = std::string::const_iterator;
for (std::string const input : {
"",
" program ",
"#hello\n program # comment\n",
}) {
It f = input.begin(), l = input.end();
if(parse(f, l, Parser::programEntry)) {
std::cout << "Parse success\n";
} else {
std::cout << "Parse failed\n";
}
std::cout << "Remaining: '" << std::string(f,l) << "'\n";
}
}
版画
Parse failed
Remaining: ''
Parse success
Remaining: ''
Parse success
Remaining: ''
post-skipping 最惯用的方法是什么?更具体地说,我想确保在匹配我的最高规则后我的输入中没有 "non-skippable"(垃圾)字符。
auto const blankOrComment
= ascii::space
| x3::lexeme ['#' >> *(x3::char_ - x3::eol) >> -x3::eol ]
;
auto const program = rule<AstProgram>("program")
= *(as<AstDefinition> (definition > ";"))
;
auto const programEntry = x3::skip(blankOrComment) [program];
一个想法,我认为非常丑陋,如果主迭代器位置不是结束迭代器,则之后对 blankOrComment
进行单独的解析调用。我目前更好的想法是更改根规则:
auto const programEntry = x3::skip(blankOrComment) [program >> x3::omit[*blankOrComment]];
有没有更地道的方法?
最简单的破解方法是添加 >> eps
:Live On Coliru
请注意,我会努力使船长更具自我描述性:
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
同样,您可以使 postskip hack 更具自我描述性:
auto const post_skip = eps;
auto const program = "program" >> post_skip;
#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
namespace Parser {
namespace x3 = boost::spirit::x3;
namespace rules {
using namespace x3;
auto const skipper
= space
| '#' >> *(char_ - eol) >> (eol|eoi)
;
auto const post_skip = eps;
auto const program = "program" >> post_skip;
}
auto const programEntry = x3::skip(rules::skipper) [rules::program];
}
int main() {
using It = std::string::const_iterator;
for (std::string const input : {
"",
" program ",
"#hello\n program # comment\n",
}) {
It f = input.begin(), l = input.end();
if(parse(f, l, Parser::programEntry)) {
std::cout << "Parse success\n";
} else {
std::cout << "Parse failed\n";
}
std::cout << "Remaining: '" << std::string(f,l) << "'\n";
}
}
版画
Parse failed
Remaining: ''
Parse success
Remaining: ''
Parse success
Remaining: ''