Boost.Tokenizer 用于引号和括号

Posted

技术标签:

【中文标题】Boost.Tokenizer 用于引号和括号【英文标题】:Boost.Tokenizer for quotation marks and parentheses 【发布时间】:2012-02-21 19:19:56 【问题描述】:

我想使用Boost.Tokenize 将字符串拆分为标记。要求引号或括号中的文本是一个完整的标记。更具体地说,我需要像这样分割一行

"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. 如我所述,如何拆分字符串?

【问题讨论】:

这不是简单的词法标记,而是解析 @LightnessRacesinOrbit:那么,我的任务需要Boost.Spirit 吗? 我不知道。您可能需要它来很好地执行您的任务。 也许它正在解析,@Lightness,但我看不出为什么它仍然不能用 Boost.Tokenize 解决。 @RobKennedy:我不认为它是为此而设计的。 【参考方案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&lt;QuoteParenTokenizer&lt;&gt; &gt;。如果您有不同的迭代器类型或不同的令牌类型,则需要在模板参数中将它们指示给tokenizer QuoteParenTokenizer

如果您需要处理转义的分隔符,您可以变得更有趣。如果您需要嵌套带括号的表达式,事情会变得更加棘手。

请注意,截至目前,上述代码尚未经过测试。

【讨论】:

以上是关于Boost.Tokenizer 用于引号和括号的主要内容,如果未能解决你的问题,请参考以下文章

Boost tokenizer 无法解析具有双引号字段的 csv 文件

如何定义 boost tokenizer 以返回 boost::iterator_range<const char*>

字符串迭代器不兼容 boost::tokenizer

Boost::tokenizer 逗号分隔 (c++)

boost::tokenizer 考虑分隔符之间没有标记

从 Boost::Tokenizer 中删除重复项?