在我实现的语法中,有些元素由空格分隔。使用跳过解析器,将自动跳过元素之间的空格,但这也允许 no 空间,这不是我想要的。当然,我可以明确地编写一个包含这些空格的语法,但是在我看来(凭借精神提供的复杂性和灵活性),有一种更好的方法可以做到这一点。在那儿? 这是一个示例:
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main(int argc, char** argv)
{
if(argc != 2)
{
std::exit(1);
}
std::string str = argv[1];
auto iter = str.begin();
bool r = qi::phrase_parse(iter, str.end(), qi::char_ >> qi::char_, qi::blank);
if (r && iter == str.end())
{
std::cout << "parse succeeded\n";
}
else
{
std::cout << "parse failed. Remaining unparsed: " << std::string(iter, str.end()) << '\n';
}
}
这允许ab
和a b
。我只希望允许后者。
与此相关:跳过解析器如何工作?一个提供了诸如qi :: blank之类的东西,然后将星星应用到跳过分析器中吗?我想在这里得到一些启示,也许这也有助于解决这个问题。
其他信息:我的真实解析器如下所示:
one = char_("X") >> repeat(2)[omit[+blank] >> +alnum] >> qi::omit[+qi::blank] >> +alnum;
two = char_("Y") >> repeat(3)[omit[+blank] >> +alnum];
three = char_("Z") >> repeat(4)[omit[+blank] >> +alnum] >> qi::omit[+qi::blank] >> +alnum;
main = one | two | three;
这使语法非常嘈杂,我想避免。
答案 0 :(得分:2)
首先,我通常在(总是?)RFC中看到这种语法要求。在99%的情况下,没有问题,请考虑例如:
myrule = skip(space) [ uint_ >> uint_ ];
这已经隐含地要求数字之间至少有1个空格字符,原因很简单,否则会有1个数字。在令人惊讶的许多情况下,也会发生相同的简化(例如,上周Boost.Spirit qi value sequence vector,请参见此答案中有关无处不在的WSP生产的简化)。
根据定义,跳过程序将应用零次或多次,因此,没有任何方法可以通过现有的有状态指令(例如skip()
)来获得所需的内容。另请参见{{1},lexeme
和[no_]skip
下的http://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965或docs-。
看看您的特定语法,我会这样做:
skip_flag::dont_postskip
在这里,您可以在词素中添加否定的超前断言,以断言“已到达令牌的末尾”-在解析器中,其将强制为bool r = qi::phrase_parse(iter, end, token >> token, qi::blank);
:
!qi::graph
观看演示:
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
打印
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const str : { "ab", " ab ", " a b ", "a b" }) {
auto iter = str.begin(), end = str.end();
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
bool r = qi::phrase_parse(iter, end, token >> token, qi::blank);
std::cout << " --- " << std::quoted(str) << " --- ";
if (r) {
std::cout << "parse succeeded.";
} else {
std::cout << "parse failed.";
}
if (iter != end) {
std::cout << " Remaining unparsed: " << std::string(iter, str.end());
}
std::cout << std::endl;
}
}
我的准则是:
--- "ab" --- parse failed. Remaining unparsed: ab
--- " ab " --- parse failed. Remaining unparsed: ab
--- " a b " --- parse succeeded.
--- "a b" --- parse succeeded.
打印
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const str : { "ab", " ab ", " a b ", "a b happy trees are trailing" }) {
auto iter = str.begin(), end = str.end();
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
bool r = qi::parse(iter, end, qi::skip(qi::space) [ token >> token >> qi::eoi ]);
std::cout << " --- " << std::quoted(str) << " --- ";
if (r) {
std::cout << "parse succeeded.";
} else {
std::cout << "parse failed.";
}
if (iter != end) {
std::cout << " Remaining unparsed: " << std::quoted(std::string(iter, str.end()));
}
std::cout << std::endl;
}
}