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<> >
. Если у вас другой тип итератора или другой тип токена, вам необходимо указать их в параметрах шаблона как tokenizer
, так и QuoteParenTokenizer
.
Вы можете стать хитрее, если вам нужно обработать экранированные символы-разделители. Все будет сложнее, если вам понадобятся выражения в скобках для вложения.
Остерегайтесь того, что на данный момент приведенный выше код не был проверен.