2016-07-25 33 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; 
} 
相关问题