Как использовать Boost::Spirit::Lex для лексирования файла без предварительного чтения всего файла в память?
Я смотрю на написание лексера с использованием boost::spirit::lex, но все примеры, которые я могу найти, предполагают, что вы сначала прочитали весь файл в ОЗУ. Я хотел бы написать лексер, который не требует, чтобы вся строка была в ОЗУ, это возможно? Или мне нужно использовать что-то еще?
Я пытался использовать istream_iterator, но boost дает мне ошибку компиляции, если я не использую const char * в качестве типов итераторов.
Например, все примеры, которые я могу найти, в основном делают это:
lex_functor_type< lex::lexertl::lexer<> > lex_functor;
// assumes entire file is in memory
char const* first = str.c_str();
char const* last = &first[str.size()];
bool r = lex::tokenize(first, last, lex_functor,
boost::bind(lex_callback_functor(), _1, ... ));
Кроме того, возможно ли как-то определить номера строк / столбцов из лекс-токенов?
Спасибо!
1 ответ
Spirit Lex работает с любым итератором, если он соответствует требованиям стандартных прямых итераторов. Это означает, что вы можете кормить лексера lex::tokenize()
) с любым соответствующим итератором. Например, если вы хотите использовать std::istream
Вы могли бы обернуть это в boost::spirit::istream_iterator
:
bool tokenize(std::istream& is, ...)
{
lex_functor_type< lex::lexertl::lexer<> > lex_functor;
boost::spirit::istream_iterator first(is);
boost::spirit::istream_iterator last;
return lex::tokenize(first, last, lex_functor,
boost::bind (lex_callback_functor(), _1, ... ));
}
и это будет работать.
Для второй части вашего вопроса (связанной с номером строки / столбца ввода): да, можно отслеживать позицию ввода с помощью лексера. Это не тривиально, хотя. Вам необходимо создать собственный тип токена, в котором будет храниться информация о строке / столбце, и использовать его вместо предопределенного типа токена. Многие люди просят об этом, поэтому я мог бы просто пойти дальше и создать пример.