TokenizerFunctionは2つのメソッドを持つファンクターであり、どちらも実装が非常に難しいはずではありません。1つはreset
、ファンクターが持つ可能性のある状態をリセットすることを意味する、もう1つはoperator()
、3つのパラメーターをとるです。最初の2つはイテレータであり、3つ目は結果のトークンです。
以下のアルゴリズムは単純です。まず、スペースをスキップします。最初の非スペース文字は3種類のうちの1つであると予想されます。引用符または左括弧の場合は、対応する終了区切り文字が見つかるまで検索し、見つかったものをトークンとして返します。引用符は削除されることになっていますが、括弧は残っているようです。最初の文字が別のものである場合は、次の区切り文字を検索して、代わりにそれを返します。
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<> >
。別のイテレータタイプまたは別のトークンタイプがある場合は、テンプレートパラメータでとの両方にそれらを示す必要がありtokenizer
ます QuoteParenTokenizer
。
エスケープされた区切り文字を処理する必要がある場合は、より洗練されたものにすることができます。ネストするために括弧で囲まれた式が必要な場合は、作業が難しくなります。
現在のところ、上記のコードはテストされていないことに注意してください。