【问题标题】:Can Boost Spirit Rules be parameterized提升精神规则可以参数化吗
【发布时间】:2012-11-28 17:08:41
【问题描述】:

在我的 Boost Spirit 语法中,我希望有一个规则来做到这一点:

规则<...> noCaseLit = no_case[ lit( "KEYWORD" ) ];

但对于自定义关键字,我可以这样做:

... >> noCaseLit( "SomeSpecialKeyword" ) >> ... >> noCaseLit( "OtherSpecialKeyword1" )

Boost Spirit 规则是否可以做到这一点?如果可以,如何实现?

附:我以不区分大小写的东西为例,我追求的是一般的规则参数化。

修改: 通过 cmets 中“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") >> ...

【问题讨论】:

标签: c++ boost rules boost-spirit boost-spirit-qi


【解决方案1】:

最简单的方法是简单地创建一个返回您的规则/解析器的函数。在this page 末尾附近的示例中,您可以找到一种声明函数返回值的方法。 (注释示例中的 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;
}

【讨论】:

  • 感谢此解决方案。您的方向与我在“半”解决方案中的方向不同。这行得通,并且符合我的要求。
  • +1 获得另一个令人震惊的答案,显示了对 Spirit 界面下发生的事情的理解。 [哦,还有 Vim g~iw 很多吗? :)]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多