我有一个以逗号分隔的 ID 对列表,空列表也是有效的
a b, c d
我的规则是预期的序列id > id
有效
但是当我尝试在前面添加一个可选的整数值时-qi::int_ > id > id
a b, 2 c d
空列表不再被允许,并且我收到一个要求输入 id 的期望异常
例如:Coliru 上的直播
// #define BOOST_SPIRIT_DEBUG
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
#include <optional>
namespace qi = boost::spirit::qi;
namespace Ast
{
struct Identifier : std::string
{
using std::string::string;
using std::string::operator=;
};
struct Test
{
std::optional<int> a;
Identifier b, c;
};
} // namespace Ast
BOOST_FUSION_ADAPT_STRUCT( Ast::Test, a, b, c )
using It = std::string_view::const_iterator;
template <typename Attr, typename Skipper>
void run_tests( qi::rule<It, Attr(), Skipper> const& rule_, std::vector<std::string> const& tests )
{
using boost::core::demangle;
std::cout << "======[ " << demangle( typeid( Attr ).name() ) << " ]======" << std::endl;
for( std::string_view test : tests )
{
It f = test.begin(), l = test.end();
try
{
std::cout << "Parsing: " << quoted( test ) << " -> ";
Attr v;
bool ok;
if constexpr( std::is_same_v<Skipper, qi::unused_type> )
ok = parse( f, l, qi::eps > rule_ > qi::eoi, v );
else
ok = phrase_parse( f, l, qi::eps > rule_ > qi::eoi, Skipper{}, v );
std::cout << ( ok ? "OK" : "FAIL" ) //
<< " Remaining: " << quoted( std::string( f, l ) ) //
<< "\n";
}
catch( qi::expectation_failure<It> const& ef )
{
auto p = ef.first - test.begin();
auto bol = test.find_last_of( "\r\n", p ) + 1;
auto line = std::count( f, f + bol, '\n' ) + 1;
auto eol = test.find_first_of( "\r\n", p );
std::cout << "EXPECTED " << ef.what_ << " in line:" << line << " col:" << ( p - bol ) << "\n"
<< " " << test.substr( bol, eol - bol ) << "\n"
<< " " << std::setw( p - bol ) << "" << "^--- here\n";
}
}
}
template <typename Attr>
using Rule = qi::rule<It, Attr(), qi::space_type>;
int main()
{
qi::rule<It, Ast::Identifier()> id = qi::char_( "a-zA-Z_" ) >> *qi::char_( "a-zA-Z0-9_" );
Rule<Ast::Test> test = -qi::int_ > id > id;
Rule<std::vector<Ast::Test>> list = -( test % ',' );
BOOST_SPIRIT_DEBUG_NODES( (id)(test)( list ) )
run_tests( list, { "a b, c d", "" } );
}
输出:
Parsing: "a b, c d" -> OK Remaining: ""
Parsing: "" -> EXPECTED <id> in line:1 col:0
我不明白为什么添加可选的 int 会破坏-( test % ',' )
它也可以为空的规则
您必须告知
-qi::int_
如果没有任何内容则不匹配:查看直播
印刷
或者,不要对期望过于严格。毕竟,你的期望不是“如果没有匹配的整数,则需要一个 id”:
相同输出,直播