我有一个非常基本的Boost精神气语法来解析IP端口或IP端口范围,即"6322"
或"6322-6325"
。
语法看起来像:
template<class It>
void init_port_rule(u16_rule<It>& port)
{
port = boost::spirit::qi::uint_parser<uint16_t, 10, 2, 5>();
port.name("valid port range: (10, 65535)");
}
typedef boost::fusion::vector
< std::uint16_t
, boost::optional<std::uint16_t>
> port_range_type
;
template<class It>
struct port_range_grammar
: boost::spirit::qi::grammar
< It
, port_range_type()
>
{
typedef typename port_range_grammar::base_type::sig_type signature;
port_range_grammar()
: port_range_grammar::base_type(start, "port_range")
{
init_port_rule(port);
using namespace boost::spirit::qi;
start = port > -(lit("-") > port);
}
private:
boost::spirit::qi::rule<It, signature> start;
boost::spirit::qi::rule<It, std::uint16_t()> port;
};
我有点难以下定义,在一个范围内,port1
必须小于port2
。我认为我必须在这里使用eps
解析器,但似乎没有找到适当的方法来指定它。任何建议都非常欢迎。
发布于 2017-11-11 17:18:08
好吧,我想我已经弄明白了.
port_range_grammar()
: port_range_grammar::base_type(start, "port_range")
{
init_port_rule(port);
using namespace boost::spirit::qi;
namespace pnx = boost::phoenix;
namespace fus = boost::fusion;
start = port > -(lit("-") > port)
> eps( pnx::bind
( [](auto const& parsed)
{
if(!fus::at_c<1>(parsed).is_initialized())
return true;
auto lhs = fus::at_c<0>(parsed);
auto rhs = *fus::at_c<1>(parsed);
return lhs < rhs;
}
, _val
)
)
;
}
其思想是将解析后的值传递给eps
解析器,解析器将检查构造的port_range_type
是否包含小于第二个元素的第一个元素。
https://stackoverflow.com/questions/47243884
复制相似问题