Функция токенизировать()
является вспомогательной функцией, упрощающей использование лексера в одиночку. Например, у вас может быть отдельный лексер, где все функциональные требования реализуются внутри семантических действий лексера. Хорошим примером для этого является word_count_lexer, более подробно описанный в разделе Lex Quickstart 2 - лучший счетчик слов с использованием Spirit.Lex.
template <typename Lexer>
struct word_count_tokens : lex::lexer<Lexer>
{
word_count_tokens()
: c(0), w(0), l(0)
, word("[^ \t\n]+")
, eol("\n")
, any(".")
{
using boost::spirit::lex::_start;
using boost::spirit::lex::_end;
using boost::phoenix::ref;
this->self
= word [++ref(w), ref(c) += distance(_start, _end)]
| eol [++ref(c), ++ref(l)]
| any [++ref(c)]
;
}
std::size_t c, w, l;
lex::token_def<> word, eol, any;
};
Конструкция, используемая для токенизации данного входа, в то время как отбрасывание всех сгенерированных токенов, является общим приложением лексера. По этой причине Spirit.Lex раскрывает функцию API токенизировать()
минимизируя требуемый код:
std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
word_count_tokens<lexer_type> word_count_lexer;
std::string::iterator first = str.begin();
bool r = tokenize(first, str.end(), word_count_lexer);
Этот код полностью эквивалентен более многословной версии, как показано в разделе Lex Quickstart 2 - лучший счетчик слов с использованием Spirit.Lex. Функция токенизировать()
вернется либо при достижении конца ввода (в этом случае значение возврата будет истинно
), либо если лексер не сможет сопоставить ни одно из определений токена во входе (в этом случае значение возврата будет ложно
и итератор первый
укажет на первый несоответствующий символ во входной последовательности).
Прототипом этой функции является:
template <typename Iterator, typename Lexer>
bool tokenize(Iterator& first, Iterator last, Lexer const& lex
, typename Lexer::char_type const* initial_state = 0);
where:
- Iterator& first
Начало входной последовательности для токенизации. Значение этого итератора будет обновляться лексером, указывая на первый несоответствующий символ ввода после возвращения функции.
- Iterator last
Конец входной последовательности для токенизации.
- Lexer const& lex
Пример лексера, используемый для токенизации.
- Lexer::char_type const* initial_state
Этот дополнительный параметр может быть использован для указания начального состояния лексера для токенизации.
Вторая перегрузка функции токенизировать()
позволяет задать любую произвольную функцию или объект функции, который будет вызываться для каждого из генерируемых токенов. Для некоторых приложений это очень полезно, так как может избежать семантических действий лексера. Для примера использования этой функции, пожалуйста, взгляните на word_count_functor.cpp:
Основная функция просто загружает данный файл в память (как std::string
), инстанцирует экземпляр шаблона определения токена с использованием правильного типа итератора (word_count_tokens<charconst*>
), и, наконец, вызывает lex::токенизировать
, минуя экземпляр объекта контрфункции. Возвратное значение lex::токенизировать()
будет истинно
, если вся входная последовательность была успешно токенизирована, и ложно
в противном случае.
int main(int argc, char* argv[])
{
std::size_t c = 0, w = 0, l = 0;
std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
word_count_tokens<lex::lexertl::lexer<> > word_count_functor;
char const* first = str.c_str();
char const* last = &first[str.size()];
bool r = lex::tokenize(first, last, word_count_functor,
boost::bind(counter(), _1, boost::ref(c), boost::ref(w), boost::ref(l)));
if (r) {
std::cout << "lines: " << l << ", words: " << w
<< ", characters: " << c << "\n";
}
else {
std::string rest(first, last);
std::cout << "Lexical analysis failed\n" << "stopped at: \""
<< rest << "\"\n";
}
return 0;
}
Вот прототип этой функции токенизировать()
:
template <typename Iterator, typename Lexer, typename F>
bool tokenize(Iterator& first, Iterator last, Lexer const& lex, F f
, typename Lexer::char_type const* initial_state = 0);
where:
- Iterator& first
Начало входной последовательности для токенизации. Значение этого итератора будет обновляться лексером, указывая на первый несоответствующий символ ввода после возвращения функции.
- Iterator last
Конец входной последовательности для токенизации.
- Lexer const& lex
Пример лексера, используемый для токенизации.
- F f
Функция или объект функции, который должен быть вызван для каждого совпадающего токена. Предполагается, что эта функция будет иметь прототип: bool f(Lexer::token_type);
. Функция токенизировать()
возвращается немедленно, если F
возвращает 'ложь.
- Lexer::char_type const* initial_state
Этот дополнительный параметр может быть использован для указания начального состояния лексера для токенизации.