在我的 Boost Spirit 语法中,我希望有一条规则可以做到这一点:
规则<...> noCaseLit = no_case[ lit( "KEYWORD" ) ];
但对于自定义关键字,我可以这样做:
... >> noCaseLit( "SomeSpecialKeyword" ) >> ... >> noCaseLit( "OtherSpecialKeyword1" )
Boost Spirit 规则是否可能实现这一点?如果可以,如何实现?
附:我以不区分大小写的事情为例,我所追求的是一般的规则参数化。
Edits:通过评论中“sehe”提供的链接,我能够接近我想要的,但我还没有完全实现。
/* Defining the noCaseLit rule */
rule<Iterator, string(string)> noCaseLit = no_case[lit(_r1)];
/* Using the noCaseLit rule */
rule<...> someRule = ... >> noCaseLit(phx::val("SomeSpecialKeyword")) >> ...
我还没有找到一种方法来自动将文字字符串转换为 Phoenix 值,以便我可以使用如下规则:
rule<...> someRule = ... >> noCaseLit("SomeSpecialKeyword") >> ...
最简单的方法是简单地创建一个返回规则/解析器的函数。在接近结尾的示例中这一页您可以找到一种方法来声明函数的返回值。 (相同here在评论的例子中)。
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
namespace ascii = boost::spirit::ascii;
namespace qi = boost::spirit::qi;
typedef boost::proto::result_of::deep_copy<
BOOST_TYPEOF(ascii::no_case[qi::lit(std::string())])
>::type nocaselit_return_type;
nocaselit_return_type nocaselit(const std::string& keyword)
{
return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]);
}
//C++11 VERSION EASIER TO MODIFY (AND DOESN'T REQUIRE THE TYPEDEF)
//auto nocaselit(const std::string& keyword) -> decltype(boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]))
//{
// return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]);
//}
int main()
{
std::string test1="MyKeYWoRD";
std::string::const_iterator iter=test1.begin();
std::string::const_iterator end=test1.end();
if(qi::parse(iter,end,nocaselit("mYkEywOrd"))&& (iter==end))
std::cout << "Parse 1 Successful" << std::endl;
else
std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl;
qi::rule<std::string::const_iterator,ascii::space_type> myrule =
*(
( nocaselit("double") >> ':' >> qi::double_ )
| ( nocaselit("keyword") >> '-' >> *(qi::char_ - '.') >> '.')
);
std::string test2=" DOUBLE : 3.5 KEYWORD-whatever.Double :2.5";
iter=test2.begin();
end=test2.end();
if(qi::phrase_parse(iter,end,myrule,ascii::space)&& (iter==end))
std::cout << "Parse 2 Successful" << std::endl;
else
std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl;
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)