2016-08-27 5 views
3

ブーストスピリットqi :: symbolsはキーと値のペアのマップを実装しています。文字列のキーを指定すると、特定の値を返すことができます。私の質問は次のとおりです:ブーストスピリットQi記号デフォルト値とNULL値

1)空白文字列の場合、デフォルト値を返すことはできますか? (コード中のQ1)

2)空の文字列以外の文字列、またはキーと値のペアのマップにリストされているキーについては、キーが無効であることを示す値を返すことはできますか? (コード中のQ2)

**以下のコードは、BOOST SPIRITの文書に基づいています。 **ご提案いただきありがとうございます。

#include <boost/spirit/include/support_utree.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/assert.hpp> 
#include <iostream> 
#include <string> 
#include <cstdlib> 

template <typename P, typename T> 
void test_parser_attr(
    char const* input, P const& p, T& attr, bool full_match = true) 
{ 
    using boost::spirit::qi::parse; 

    char const* f(input); 
    char const* l(f + strlen(f)); 
    if (parse(f, l, p, attr) && (!full_match || (f == l))) 
     std::cout << "ok" << std::endl; 
    else 
     std::cout << "fail" << std::endl; 
} 

int main() 
{ 
    using boost::spirit::qi::symbols; 

    symbols<char, int> sym; 
    sym.add 
     ("Apple", 1) 
     ("Banana", 2) 
     ("Orange", 3) 
    ; 

    int i; 
    test_parser_attr("Banana", sym, i); 
    std::cout << i << std::endl;  // 2 


    test_parser_attr("", sym, i);  // Q1: key is "", 
    std::cout << i << std::endl;  // would like it to be 1 as default 

    test_parser_attr("XXXX", sym, i); // Q2: key is other than "Apple"/"Banana"/"Orange", 
    std::cout << i << std::endl;  // would like it to be 4 

    return 0; 
} 

答えて

2

あなたはちょうどqi::symbolsを使用して欲しいものを達成することはできません。希望の結果を達成するスピリットターミナル/ディレクティブを作成することは可能ですが、そうすることは実際には複雑で、qi::symbolsの内部動作の知識と関連するクラスを必要とするので、それは価値あるアプローチだとは思いません。幸運にも、入力を消費せず、valをその属性として公開し、常に成功するパーサーであるqi::attr(val)を使用して、本当に簡単な代替方法があります。文字列は、文字列が空の戻り1 ->であればちょうどちょうどattr(1)

  • あれば使用sym
  • を使用しその値->を返すシンボルテーブルにある場合

    • のは、すべての3例を見てみましょう文字列はシンボルテーブルにありませんreturn ->ここではattr(4)を使用する必要がありますが、文字列を消費する必要があるため、これでは不十分です。文字列が文字のみで構成されていると仮定すると、はテキストを破棄し、+は少なくとも1文字が存在することを確認します。

      sym | omit[+alpha] >> attr(4) | attr(1) 
      

      可能性のある問題:

      は、あなたが実際にそれぞれの場合に使用するパーサが成功するための最初の1になることを念頭に置いてalternative parser維持にこれら三つのパーサを置く必要があります

    • シンボルテーブル以外の文字列が複雑な場合は、+alphaを適切に変更する必要があります。
    • あなたはおそらく貪欲+を停止するomit[lexeme[+alpha]]を使用する必要がありますスキッパーを使用している場合。

    全サンプル(Running on WandBox)

    #include <iostream> 
    #include <string> 
    
    #include <boost/spirit/include/qi.hpp> 
    
    
    template <typename P, typename T> 
    void test_parser_attr(
        char const* input, P const& p, T& attr, bool full_match = true) 
    { 
        using boost::spirit::qi::parse; 
    
        char const* f(input); 
        char const* l(f + strlen(f)); 
        if (parse(f, l, p, attr) && (!full_match || (f == l))) 
         std::cout << "ok" << std::endl; 
        else 
         std::cout << "fail" << std::endl; 
    } 
    
    int main() 
    { 
        using boost::spirit::qi::symbols; 
    
        symbols<char, int> sym; 
        sym.add 
         ("Apple", 1) 
         ("Banana", 2) 
         ("Orange", 3) 
        ; 
    
        using boost::spirit::qi::attr; 
        using boost::spirit::qi::alpha; 
        using boost::spirit::qi::omit; 
        using boost::spirit::qi::lexeme; 
    
        //if the text is in the symbol table return the associated value 
        //else if the text is formed by letters (you could change this using for example `alnum`) and contains at least one, discard the text and return 4 
        //else return 1 
        boost::spirit::qi::rule<char const*,int()> symbols_with_defaults = sym | omit[+alpha] >> attr (4) | attr(1); 
    
    
        int i; 
        test_parser_attr("Banana", symbols_with_defaults, i); 
        std::cout << i << std::endl;  // 2 
    
        test_parser_attr("", symbols_with_defaults, i);  // Q1: key is "", 
        std::cout << i << std::endl;  // would like it to be 1 as default 
    
        test_parser_attr("XXXX", symbols_with_defaults, i); // Q2: key is other than "Apple"/"Banana"/"Orange", 
        std::cout << i << std::endl;  // would like it to be 4 
    
        std::vector<int> values; 
        test_parser_attr("<Banana>,<>,<xxxx>", ('<' >> symbols_with_defaults >> '>')%',', values); 
        for(int val : values) 
         std::cout << val << " "; // should be '2 1 4' 
        std::cout << std::endl; 
    
        return 0; 
    } 
    
  • +0

    +1。私は80%が正確にそれを書いていました。 – sehe

    +0

    恐ろしい!完璧なソリューション、詳細な説明、迅速な対応。どうもありがとうございました。 – jianz

    関連する問題