Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 引号和括号的标记器_C++_Boost_Tokenize_Boost Tokenizer - Fatal编程技术网

C++ 引号和括号的标记器

C++ 引号和括号的标记器,c++,boost,tokenize,boost-tokenizer,C++,Boost,Tokenize,Boost Tokenizer,我想使用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 ( ni

我想使用
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
)
我知道用引号标记文本,但我不知道如何同时标记Parentese中的文本。可能需要实现
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;
  }
};
模板<
typename Iter=std::string::const_迭代器,
typename Type=std::string
>
结构QuoteParenTokenizer
{
void reset(){}
布尔运算符()(Iter和next、Iter端、类型和tok)常数
{
while(下一步!=结束和下一步=“”)
++其次;
如果(下一步==结束)
return false;//没有留下要读取的内容
开关(*下一个){
案例'':{
++下一步;//跳过令牌开始
Item const quote=std::find(下一步,结束“”);
如果(引号==结束)
返回false;//未终止的令牌
tok.分配(下一步,报价);
下一步=报价;
++其次;
打破
}
格“(”:{
Iter paren=std::find(下一步,结束“)”;
如果(paren==结束)
返回false;//未终止的令牌
++paren;//包含括号
tok.分配(下一步,paren);
next=paren;
打破
}
默认值:{
国际热核实验堆常数第一=下一;
while(next!=end&&&*next!=''&&&*next!='''和&&*next!='('))
++其次;
tok.分配(第一个,下一个);
}
}
返回true;
}
};
您可以将其实例化为
tokenizer
。如果您有不同的迭代器类型或不同的令牌类型,则需要在模板参数中将它们指示给
tokenizer
QuoteParenTokenizer

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


请注意,到目前为止,上述代码还没有经过测试。

这不是简单的词法标记,而是解析。@LightnessRacesinOrbit:那么,我的任务是否需要
Boost.Spirit
?我不知道。可能是您需要它来很好地执行任务。可能是解析,@Lightness,但我看不出为什么它仍然不能被解决RobKennedy:我认为它不是为这个设计的。