3

私のBoostSpirit文法では、これを行うルールが必要です。

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

しかし、私がこれを行うことができるように、カスタムキーワードの場合:

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

これはブーストスピリットルールで可能ですか?もしそうならどのように?

PS例として大文字と小文字を区別しないものを使用します。私が求めているのは、一般的なルールのパラメーター化です。

編集: コメントの「sehe」によって提供されたリンクを通して、私は私が望んでいたものに近づくことができましたが、私はまだそこにいません。

/* Defining the noCaseLit rule */
rule<Iterator, string(string)> noCaseLit = no_case[lit(_r1)];
/* Using the noCaseLit rule */
rule<...> someRule = ... >> noCaseLit(phx::val("SomeSpecialKeyword")) >> ...

次のようなルールを使用できるように、リテラル文字列をフェニックス値に自動的に変換する方法をまだ理解していません。

rule<...> someRule = ... >> noCaseLit("SomeSpecialKeyword") >> ...
4

1 に答える 1

4

最も簡単な方法は、ルール/パーサーを返す関数を単純に作成することです。このページの最後にある例では、関数の戻り値を宣言する方法を見つけることができます。(コメント付きの例でも同じです)。

#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;
}
于 2012-11-29T10:23:25.130 に答える