2012-02-21 98 views
2

我想使用Boost.Tokenize將字符串拆分爲令牌。要求引號或括號中的文字是單個整體標記。更具體地講,我需要一個像Boost.Tokenizer用於引號和圓括號

"one (two),three" four (five "six".seven) eight(nine, ten) 

線分成令牌像

one (two),three 
four 
(five "six".seven) 
eight 
(nine, ten) 

也許

one (two),three 
four 
(
five "six".seven 
) 
eight 
(
nine, ten 
) 

我知道the way來標記中引號的文字,但我沒有同時想象如何在紀念章中標出文字。可能需要執行TokenizerFunction
如何按我描述的方式拆分字符串?

+2

這不是簡單的詞法標記化,而是_parsing_。 – 2012-02-21 19:23:22

+0

@LightnessRacesinOrbit:那麼,我需要'Boost.Spirit'來完成我的任務嗎? – Loom 2012-02-21 19:33:07

+0

我不知道。這可能是你需要它來很好地完成你的任務。 – 2012-02-21 19:37:09

回答

1

TokenizerFunction是一個有兩種方法的仿函數,它們都不應該很難實現。第一個是reset,這意味着重置函數可能有的任何狀態,另一個是operator(),它有三個參數。前兩個是迭代器,第三個是結果標記。

下面的算法很簡單。首先,我們跳過任何空格。我們期望第一個非空間角色是三種類型之一。如果它是一個引號或左括號,那麼我們會搜索,直到找到相應的結束分隔符並返回我們找到的令牌爲止,注意引號應該被剝離,但顯然,括號會保留。如果第一個字符是別的,那麼我們搜索下一個分隔符並返回。

template < 
    typename Iter = std::string::const_iterator, 
    typename Type = std::string 
    > 
struct QuoteParenTokenizer 
{ 
    void reset() { } 

    bool operator()(Iter& next, Iter end, Type& tok) const 
    { 
    while (next != end && *next == ' ') 
     ++next; 
    if (next == end) 
     return false; // nothing left to read 

    switch (*next) { 
     case '"': { 
     ++next; // skip token start 
     Item const quote = std::find(next, end, '"'); 
     if (quote == end) 
      return false; // unterminated token 
     tok.assign(next, quote); 
     next = quote; 
     ++next; 
     break; 
     } 
     case '(': { 
     Iter paren = std::find(next, end, ')'); 
     if (paren == end) 
      return false; // unterminated token 
     ++paren; // include the parenthesis 
     tok.assign(next, paren); 
     next = paren; 
     break; 
     } 
     default: { 
     Iter const first = next; 
     while (next != end && *next != ' ' && *next != '"' && *next != '(') 
      ++next; 
     tok.assign(first, next); 
     } 
    } 
    return true; 
    } 
}; 

您可以將其實例化爲tokenizer<QuoteParenTokenizer<> >。如果您有不同的迭代器類型或不同的標記類型,則需要在模板參數中指定它們以tokenizerQuoteParenTokenizer

如果您需要處理轉義的分隔符,您可以獲得更多信息。如果你需要用括號表達式嵌套,事情會變得更復雜。

請注意,截至目前,上述代碼尚未經過測試。