2016-07-25 24 views
1

我真的放棄了(和以前的許多其他)一樣,自己找到這個仍然非常簡單的boost-spirit-業力圖書館。我想顯示的字符串之前,作爲許多白色空格作爲字符串中的字符:如何在符號的映射值前面顯示與空格相同的空格

typedef enum {A, B, C} E; 

class EName : public ka::symbols<E, std::string> 
{ 
public: 
    EName() {add (A,"A") (B,"the B") (C,"a C");} 
}; 

class grm: public ka::grammar<iterator, E()> 
{ 
public: 
    grm():grm::base_type(start) 
    { 
     namespace phx = boost::phoenix; 
     namespace ka = boost::spirit::karma;   
     start = ka::duplicate[ka::repeat(phx::bind(&std::string::size,b))[ka::lit(' ')] << b]; 
    } 
private: 

    ka::rule<iterator,E()> start; 
    EName b; 
}; 

int main(int argc, char * argv[]) 
{ 
    grm g; 
    E e = A; 

    std::string generated; 
    std::back_insert_iterator<std::string> sink(generated); 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 
    generated.clear(); 
    e = B; 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 
    return 0; 
} 

預期輸出因此一個空白空間,接着由「A」和下一行5個空格,隨後「B」(如「B」是一個5個字符的字符串)。

我知道變量「b」在ka::repeat()[]發生器的參數的上下文中是不可訪問的......我試過ka::_val而沒有成功。實際上,我沒有足夠的經驗來解決業力,鳳凰和融合問題,從而構建了答案的路徑,儘管我可能訪問了文檔中所有需要的信息。因此,我還希望提供一些關於如何通過文件(或通過推論)而不是經驗來回答問題的提示。

UPDATE:

我用投沒有成功一個屬性的嘗試:

namespace boost { 
    namespace spirit { 
     namespace traits { 
      template <> 
      struct transform_attribute<const E, std::string, ka::domain> 
      { 
       typedef std::string type; 
       static type pre(const E & e) { 
        EName s; 
        int num = s.find(e)->size(); 
        return std::string(num, ' '); 
       } 
      }; 
} } } 

依次爲:

start = ka::attr_cast<std::string>(ka::string) << b; 

但它也不編譯。

+0

你強制使用boost辦呢? – Angelos

+0

這是我的問題。當然,我知道如何做到這一點。 – Heyji

回答

1

您的問題可以分割成兩部分:

  • 獲取來自枚舉值的字符串。
  • 在字符串中預留儘可能多的空格作爲字符。

問題的第二部分是相當簡單的使用right_align directive。你可以簡單地使用:

prepend_spaces = ka::right_align(2*phx::size(ka::_val))[ka::string]; 

(如果你想用別的東西,除了簡單的空格,你可以使用第二個參數來right_align(例如ka::right_align(2*phx::size(ka::_val),ka::lit('*'))[ka::string]))

在第一部分,你可以做什麼正如你所示的attr_cast。在下面的代碼中,我使用了phx::bind以從符號表中獲取字符串。

Running on WandBox

#include <iostream> 
#include <string> 
#include <vector> 

#include <boost/spirit/include/karma.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace phx = boost::phoenix; 
namespace ka = boost::spirit::karma; 

typedef enum {A, B, C} E; 

class EName : public ka::symbols<E, std::string> 
{ 
public: 
    EName() {add (A,"A") (B,"the B") (C,"a C");} 
}; 

template <typename Iterator> 
class grm: public ka::grammar<Iterator, E()> 
{ 
public: 
    grm():grm::base_type(start) 
    { 

     prepend_spaces = ka::right_align(2*phx::size(ka::_val))[ka::string]; 
     start = prepend_spaces[ka::_1=phx::bind(&EName::at<E>,phx::ref(name),ka::_val)]; 
    } 
private: 

    ka::rule<Iterator,E()> start; 
    ka::rule<Iterator,std::string()> prepend_spaces; 
    EName name; 
}; 

int main(int argc, char * argv[]) 
{ 
    grm<std::back_insert_iterator<std::string> > g; 
    E e = A; 

    std::string generated; 
    std::back_insert_iterator<std::string> sink(generated); 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 
    generated.clear(); 
    e = B; 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 

    generated.clear(); 
    std::vector<E> v {A,B,C}; 
    ka::generate(sink,+g,v); 
    std::cout << generated << "\n"; 
    return 0; 
} 
+0

不錯。應該有一個類似ka :: _ 1 = phx :: bind(&EName :: at,phx :: ref(name),ka :: _ val)的較短路徑,但我無法設法使其工作。 – Heyji

+0

[This](http://melpon.org/wandbox/permlink/l8U5r0fasq4fZ08c)就是我使用「attr_cast」(實際上''transform_attribute'',因爲'attr_cast'似乎並不需要)的方法。我不喜歡這種方法,因爲我已經看到很多(也許已經在當前版本中已經解決了)'attr_cast'問題,特別是Karma。 – llonesmiz

1

我不是那麼遠,所以我在這裏發表我的第一次嘗試。其他解決方案也是受歡迎的。

namespace ka = boost::spirit::karma;  

typedef enum {A, B, C} E; 

class EName : public ka::symbols<E, std::string> 
{ 
public: 
    EName() {add (A,"A") (B,"the B") (C,"a C");} 
}; 

namespace boost { 
    namespace spirit { 
     namespace traits { 
      template <> 
      struct transform_attribute<const E, std::string, ka::domain> 
      { 
       typedef std::string type; 
       static type pre(const E & e) { 
        EName s; 
        int num = s.find(e)->size(); 
        return std::string(num, ' '); 
       } 
      }; 
} } } 

class grm: public ka::grammar<iterator, E()> 
{ 
public: 
    grm():grm::base_type(start) 
    {  
     start = ka::duplicate[ka::attr_cast<std::string>(ka::string) << b]; 
    } 
private: 

    ka::rule<iterator,E()> start; 
    EName b; 
}; 

int main(int argc, char * argv[]) 
{ 
    grm g; 
    E e = A; 

    std::string generated; 
    std::back_insert_iterator<std::string> sink(generated); 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 
    generated.clear(); 
    e = B; 
    ka::generate(sink,g,e); 
    std::cout << generated << "\n"; 
    return 0; 
} 
相關問題