Чтение токенов из файла (сложное) - PullRequest
1 голос
/ 07 ноября 2010

У меня есть базовая структура / алгоритм токенизации.Это довольно сложно, и я надеюсь, что смогу прояснить это достаточно просто, чтобы проинформировать вас о «недостатке» в моем дизайне.

class ParserState

// bool functions return false if getline() or stream extraction '>>' fails
static bool nextLine(); // reads and tokenizes next line from file and puts it in m_buffer
static bool nextToken(); // gets next token from m_buffer, via fetchToken(), and puts it in m_token
static bool fetchToken( std::string &token ); // procures next token from file/buffer

static size_t m_lineNumber;
static std::ifstream m_fstream;
static std::string m_buffer;
static std::string m_token;

Причиной такой настройки является возможностьсообщить номер строки в случае синтаксической ошибки.В зависимости от фазы / состояния синтаксического анализатора в моей программе происходят разные вещи, и подклассы этого ParserState используют m_token и nextToken для продолжения.fetchToken вызывает nextLine, если m_buffer пусто, и помещает следующий токен в свой аргумент:

istringstream stream;

do // read new line until valid token can be extracted
{
    Debug(5) << "m_buffer contains: " << m_buffer << "\n";
    stream.str( m_buffer );

    if( stream >> token )
    {
        Debug(5) << "Token extracted: " << token << "\n";
        m_token = token;
        return true; // return when token found
    }
    stream.clear();
} while( nextLine() );
// if no tokens can be extracted from the whole file, return false
return false;

Проблема в том, что токен, удаленный из m_buffer, не удален, а тот же токенчитается с каждым звонком на nextToken().Проблема в том, что m_buffer может быть изменено, таким образом, вызов istringstream::str в цикле.Но это является причиной моей проблемы, и, насколько я понимаю, это не может быть решено, поэтому мой вопрос: как я могу позволить stream >> token удалить что-то из строки, на которую указывает внутренний поток строки?Возможно, мне нужно не использовать stringstream, а что-то более элементарное в этой ситуации (например, найти первый пробел и вырезать первый токен из строки)?

Спасибо за миллиард!

PS: любые предложения по изменению структуры моей функции / класса в порядке, если они позволяют отслеживать номера строк (поэтому полный файл не читается в m_buffer и член класса istringstream, чтоРаньше я хотел получать отчеты об ошибках в номерах строк).

Ответы [ 3 ]

1 голос
/ 07 ноября 2010

Почему бы просто не сделать m_buffer std::istringstream вместо std::string?Вы удалите временную переменную, а также получите желаемый эффект.Всякий раз, когда вы изменяете m_buffer в таких выражениях, как

m_buffer = ...

, пишите это вместо:

m_buffer.str(...);
0 голосов
/ 08 ноября 2010

Обычная схема обработки отчетов о номерах строк заключается в том, чтобы читать строки по одной за раз, увеличивая счетчик строк, а затем, когда ваш токенизатор начинает создавать токен, он делает снимок номера строки и сохраняет его в структуре данных токена (обычно содержит номер строки, тип токена и значение токена, если есть).

Это отделяет чтение строки от построения токена без потери номера строки. Это также означает, что у вас может быть много токенов, все они могут иметь номера строк (включая разные), токен может начинаться с одной строки и заканчиваться на другой и т. Д.

0 голосов
/ 08 ноября 2010

Чтобы не читать один и тот же токен несколько раз, я думаю, что вам нужно получить позицию в stream с помощью tellg, а затем восстановить ее с помощью seekg (эти методы описаны здесь ). Однако использование std::istringstream выглядит для меня излишним. Я бы предпочел работать с m_buffer напрямую.

...