2014-07-21 26 views
1

我對Boost精神仍然很陌生。提升精神分析字符串與領先和尾隨空白

我想解析一個字符串與可能的主角和尾隨空白和中間空白。我想要做的字符串

  1. 刪除任何拖尾和先行空白
  2. 限制的在中間的字空格一個空格

例如

"( my test1 ) (my test2)" 

得到以下解析爲兩項 -

"my test1" 
"my test2" 

雖然它允許在之間保留空間我已經使用以下邏輯

using boost::spirit::qi; 
struct Parser : grammar<Iterator, attribType(), space_type> 
{ 
    public: 
    Parser() : Parser::base_type(term) 
    { 
     group %= '(' >> (group | names) >> ')'; 
     names %= no_skip[alnum][_val=_1]; 
    } 

    private: 
    typedef boost::spirit::qi::rule<Iterator, attribType(), space_type> Rule; 
    Rule group; 
    Rule names 
} 

。不幸的是,它還會保留標題和尾隨空白以及多箇中間空格。我想找到一個更好的邏輯。

我的確看到引用使用boost :: spirit :: qi :: skip online的自定義隊長,但是我還沒有遇到空間的有用示例。其他人有過使用它的經驗嗎?

+0

關於'lexeme','skip','no_skip',隱式船長和'raw'的背景在這裏:http://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#1707396 5 – sehe

回答

2

我建議在(不在)解析後進行修整/標準化

這就是說,你可以砍它是這樣的:

name %= lexeme [ +alnum ]; 
names %= +(name >> (&lit(')') | attr(' '))); 
group %= '(' >> (group | names) >> ')'; 

看到它Live On Coliru

輸出:

Parse success 
Term: 'my test1' 
Term: 'my test2' 

我介紹了name規則僅適用於可讀性。需要注意的是(&lit(')') | attr(' '))是說的一個奇特的方式:

如果下一個字符匹配')'什麼也不做,否則,追加' '的綜合屬性

全碼:

#define BOOST_SPIRIT_DEBUG 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 

using Iterator = std::string::const_iterator; 

using attribType = std::string; 

struct Parser : qi::grammar<Iterator, attribType(), qi::space_type> 
{ 
    public: 
    Parser() : Parser::base_type(group) 
    { 
     using namespace qi; 

     name %= lexeme [ +alnum ]; 
     names %= +(name >> (&lit(')') | eps [ phx::push_back(_val, ' ') ])); 
     group %= '(' >> (group | names) >> ')'; 

     BOOST_SPIRIT_DEBUG_NODES((name)(names)(group)) 
    } 

    private: 
    typedef boost::spirit::qi::rule<Iterator, attribType(), qi::space_type> Rule; 
    Rule group, names, name; 
}; 


int main() 
{ 
    std::string const input = "( my test1 ) (my test2)"; 

    auto f(input.begin()), l(input.end()); 

    Parser p; 

    std::vector<attribType> data; 
    bool ok = qi::phrase_parse(f, l, *p, qi::space, data); 

    if (ok) 
    { 
     std::cout << "Parse success\n"; 
     for(auto const& term : data) 
      std::cout << "Term: '" << term << "'\n"; 
    } 
    else 
    { 
     std::cout << "Parse failed\n"; 
    } 

    if (f!=l) 
     std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n"; 
} 
+0

很好的解決方案。 ['name%= +(name)(&lit(')')| attr('')));'](http://coliru.stacked-crooked.com/a/9c1c5df7f85e8eab)也可以工作嗎?還是會出現我無法理解的問題? – llonesmiz

+0

嗯。它確實跨過了我的腦海,不知道爲什麼我解僱了它。是的,當然這很簡單。我要買它 :) – sehe