您如何使用 boost spirit x3 实现自定义解析器对象,使其与船长配合得很好?
How do you implement a custom parser object with boost spirit x3 such that it plays nice with a skipper?
我知道我可以通过使用适当的 "parse" 成员函数模板创建一个对象来实现自定义解析器,但我不知道我需要做什么才能让它在上下文中使用船长,它似乎需要这样做。也就是说,下面我预计这两种情况都会成功,但第二种情况会失败:
namespace x3 = boost::spirit::x3;
namespace parser {
struct foobar : x3::parser<foobar> {
using attribute_type = std::string;
template<typename Iterator, typename Context, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last, Context const& context,
RContext const& rcontext, Attribute& attr) const
{
static const std::string foobar_str = "foobar";
auto i = first;
auto j = foobar_str.begin();
while (i != last && j != foobar_str.end()) {
if (*i++ != *j++)
return false;
}
first = i;
attr = foobar_str;
return true;
};
};
const auto foo = foobar();
}
int main()
{
std::string input = "foobarfoobarfoobar";
std::vector<std::string> strings;
auto foobars = parser::foo >> parser::foo >> parser::foo;
bool success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n"; // yes for this one
else
std::cout << "no\n";
input = "foobar foobar foobar";
success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n";
else
std::cout << "no\n"; // no because of the spaces
}
您可以通过从上下文中获取它来简单地应用船长。由您决定何时使用它(例如,post-skip 是否是行为的一部分),但我想当有一个活跃的船长时,预跳过是隐含的。
如果您继承自 x3::parser_base,您只需调用
skip_over(f, l, ctx);
完成工作。
查看示例
我知道我可以通过使用适当的 "parse" 成员函数模板创建一个对象来实现自定义解析器,但我不知道我需要做什么才能让它在上下文中使用船长,它似乎需要这样做。也就是说,下面我预计这两种情况都会成功,但第二种情况会失败:
namespace x3 = boost::spirit::x3;
namespace parser {
struct foobar : x3::parser<foobar> {
using attribute_type = std::string;
template<typename Iterator, typename Context, typename RContext, typename Attribute>
bool parse(Iterator& first, Iterator const& last, Context const& context,
RContext const& rcontext, Attribute& attr) const
{
static const std::string foobar_str = "foobar";
auto i = first;
auto j = foobar_str.begin();
while (i != last && j != foobar_str.end()) {
if (*i++ != *j++)
return false;
}
first = i;
attr = foobar_str;
return true;
};
};
const auto foo = foobar();
}
int main()
{
std::string input = "foobarfoobarfoobar";
std::vector<std::string> strings;
auto foobars = parser::foo >> parser::foo >> parser::foo;
bool success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n"; // yes for this one
else
std::cout << "no\n";
input = "foobar foobar foobar";
success = x3::phrase_parse(input.begin(), input.end(), foobars, x3::space, strings);
if (success)
std::cout << "yes\n";
else
std::cout << "no\n"; // no because of the spaces
}
您可以通过从上下文中获取它来简单地应用船长。由您决定何时使用它(例如,post-skip 是否是行为的一部分),但我想当有一个活跃的船长时,预跳过是隐含的。
如果您继承自 x3::parser_base,您只需调用
skip_over(f, l, ctx);
完成工作。
查看示例