如何让 which() 在 boost spirit x3 expectation_failure 中正常工作?
How do I get which() to work correctly in boost spirit x3 expectation_failure?
在 expectation_failure returns 中调用 which() 一个奇怪的 std::string.
我该如何解决?
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
struct my_error_handler {
template <typename Iterator, typename Context>
auto on_error(Iterator&,
Iterator const&,
const x3::expectation_failure<Iterator>& x,
const Context&)
{
std::cerr << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
struct test_class : my_error_handler {
};
const x3::rule<test_class, int> test{"test"};
const auto test_def = x3::expect[x3::int_];
BOOST_SPIRIT_DEFINE(test)
auto parse(std::string&& input)
{
auto first = std::cbegin(input);
const auto last = std::cend(input);
x3::error_handler<decltype(first)> error_handler{first, last, std::cerr};
const auto parser
= x3::with<x3::error_handler_tag>(std::ref(error_handler))[test];
x3::phrase_parse(std::cbegin(input), std::cend(input), parser, x3::space);
}
int main()
{
parse("a123");
}
执行结果如下图
N5boost6spirit2x310int_parserIiLj10ELj1ELin1EEE
该字符串是解析器的错位类型名称。如果您不提供,这是默认名称:
std::cerr << boost::core::demangle(x.which().c_str()) << '\n';
现在打印 Live
boost::spirit::x3::int_parser<int, 10u, 1u, -1>
如果您不想要默认值,请提供一个。你可以为规则,例如"test"
:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace Parser {
x3::rule<struct test_class, int> const test{"test"};
x3::rule<struct parser_class, int> const parser{"parser"};
auto const test_def = x3::int_;
auto const parser_def = x3::skip(x3::space)[x3::expect[test]];
BOOST_SPIRIT_DEFINE(test, parser)
struct my_error_handler {
template <typename It, typename Ctx>
auto on_error(It, It, x3::expectation_failure<It> const& x, Ctx const&) const
{
std::cerr << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
struct test_class : my_error_handler {};
struct parser_class : my_error_handler {};
} // namespace Parser
auto parse(std::string const input)
{
x3::parse(begin(input), cend(input), Parser::parser);
}
int main() { parse("a123"); }
打印“测试”
更简单?
这些规则实际上并不需要 DEFINE 宏。相反,也许使用一些助手:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace Parser {
struct my_error_handler {
template <typename It, typename Ctx>
auto on_error(It, It, x3::expectation_failure<It> const& x, Ctx const&) const
{
std::cerr << "Expected: " << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
template <typename T = x3::unused_type>
auto as(auto p, char const* name = typeid(decltype(p)).name())
{
struct tag : my_error_handler { };
return x3::rule<tag, T>{name} = p;
}
template <typename T>
auto mandatory(auto p, char const* name = typeid(decltype(p)).name())
{
return x3::expect[as<T>(p, name)];
}
auto const test = mandatory<unsigned>(x3::uint_, "non-negative number");
auto const parser = as(x3::skip(x3::space)[test]);
} // namespace Parser
auto parse(std::string const input)
{
x3::parse(begin(input), cend(input), Parser::parser);
}
int main() { parse("a123"); }
版画
Expected: non-negative number
我相信你可以改变这个主题。如果你真的不强调属性类型强制,也许你可以将助手命名为 with_errors
等
在 expectation_failure returns 中调用 which() 一个奇怪的 std::string.
我该如何解决?
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
struct my_error_handler {
template <typename Iterator, typename Context>
auto on_error(Iterator&,
Iterator const&,
const x3::expectation_failure<Iterator>& x,
const Context&)
{
std::cerr << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
struct test_class : my_error_handler {
};
const x3::rule<test_class, int> test{"test"};
const auto test_def = x3::expect[x3::int_];
BOOST_SPIRIT_DEFINE(test)
auto parse(std::string&& input)
{
auto first = std::cbegin(input);
const auto last = std::cend(input);
x3::error_handler<decltype(first)> error_handler{first, last, std::cerr};
const auto parser
= x3::with<x3::error_handler_tag>(std::ref(error_handler))[test];
x3::phrase_parse(std::cbegin(input), std::cend(input), parser, x3::space);
}
int main()
{
parse("a123");
}
执行结果如下图
N5boost6spirit2x310int_parserIiLj10ELj1ELin1EEE
该字符串是解析器的错位类型名称。如果您不提供,这是默认名称:
std::cerr << boost::core::demangle(x.which().c_str()) << '\n';
现在打印 Live
boost::spirit::x3::int_parser<int, 10u, 1u, -1>
如果您不想要默认值,请提供一个。你可以为规则,例如"test"
:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace Parser {
x3::rule<struct test_class, int> const test{"test"};
x3::rule<struct parser_class, int> const parser{"parser"};
auto const test_def = x3::int_;
auto const parser_def = x3::skip(x3::space)[x3::expect[test]];
BOOST_SPIRIT_DEFINE(test, parser)
struct my_error_handler {
template <typename It, typename Ctx>
auto on_error(It, It, x3::expectation_failure<It> const& x, Ctx const&) const
{
std::cerr << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
struct test_class : my_error_handler {};
struct parser_class : my_error_handler {};
} // namespace Parser
auto parse(std::string const input)
{
x3::parse(begin(input), cend(input), Parser::parser);
}
int main() { parse("a123"); }
打印“测试”
更简单?
这些规则实际上并不需要 DEFINE 宏。相反,也许使用一些助手:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;
namespace Parser {
struct my_error_handler {
template <typename It, typename Ctx>
auto on_error(It, It, x3::expectation_failure<It> const& x, Ctx const&) const
{
std::cerr << "Expected: " << x.which() << '\n';
return x3::error_handler_result::fail;
}
};
template <typename T = x3::unused_type>
auto as(auto p, char const* name = typeid(decltype(p)).name())
{
struct tag : my_error_handler { };
return x3::rule<tag, T>{name} = p;
}
template <typename T>
auto mandatory(auto p, char const* name = typeid(decltype(p)).name())
{
return x3::expect[as<T>(p, name)];
}
auto const test = mandatory<unsigned>(x3::uint_, "non-negative number");
auto const parser = as(x3::skip(x3::space)[test]);
} // namespace Parser
auto parse(std::string const input)
{
x3::parse(begin(input), cend(input), Parser::parser);
}
int main() { parse("a123"); }
版画
Expected: non-negative number
我相信你可以改变这个主题。如果你真的不强调属性类型强制,也许你可以将助手命名为 with_errors
等