Как использовать 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, ... ));   
}

и это будет работать.

Для второй части вашего вопроса (связанной с номером строки / столбца ввода): да, можно отслеживать позицию ввода с помощью лексера. Это не тривиально, хотя. Вам необходимо создать собственный тип токена, в котором будет храниться информация о строке / столбце, и использовать его вместо предопределенного типа токена. Многие люди просят об этом, поэтому я мог бы просто пойти дальше и создать пример.

Другие вопросы по тегам