Избегайте захвата ничего из струнного потока - PullRequest
2 голосов
/ 01 июня 2011

Я работаю на ассемблере для очень простого ISA.В настоящее время я реализую функцию синтаксического анализатора, и я использую поток строк, чтобы получить слова из строк.Вот пример кода сборки:

; This program counts from 10 to 0
        .ORIG x3000
        LEA R0, TEN     ; This instruction will be loaded into memory location x3000
        LDW R1, R0, #0
START   ADD R1, R1, #-1
        BRZ DONE
        BR  START
                        ; blank line
DONE    TRAP    x25     ; The last executable instruction
TEN     .FILL   x000A   ; This is 10 in 2's comp, hexadecimal
        .END

Не беспокойтесь о природе кода сборки, просто посмотрите на строку 3 с комментарием справа.Мои функции синтаксического анализа не завершены, но вот что у меня есть:

// Define three conditions to code
enum {DONE, OK, EMPTY_LINE};
// Tuple containing a condition and a string vector
typedef tuple<int,vector<string>> Code;

// Passed an alias to a string
// Parses the line passed to it
Code ReadAndParse(string& line)
{

    /***********************************************/
    /****************REMOVE COMMENTS****************/
    /***********************************************/
    // Sentinel to flag down position of first
    // semicolon and the index position itself
    bool found = false;
    size_t semicolonIndex = -1;

    // Convert the line to lowercase
    for(int i = 0; i < line.length(); i++)
    {
        line[i] = tolower(line[i]);

        // Find first semicolon
        if(line[i] == ';' && !found)
        {
            semicolonIndex = i;
            // Throw the flag
            found = true;
        }
    }

    // Erase anything to and from semicolon to ignore comments
    if(found != false)
        line.erase(semicolonIndex);


    /***********************************************/
    /*****TEST AND SEE IF THERE'S ANYTHING LEFT*****/
    /***********************************************/

    // To snatch and store words
    Code code;
    string token;
    stringstream ss(line);
    vector<string> words;

    // While the string stream is still of use
    while(ss.good())
    {
        // Send the next string to the token
        ss >> token;
        // Push it onto the words vector
        words.push_back(token);

        // If all we got was nothing, it's an empty line
        if(token == "")
        {
            code = make_tuple(EMPTY_LINE, words);
            return code;
        }
    }

    /***********************************************/
    /***********DETERMINE OUR TYPE OF CODE**********/
    /***********************************************/


    // At this point it should be fine
    code = make_tuple(OK, words);
    return code;
}

Как видите, кортеж Code содержит условие, представленное в объявлении enum, и вектор, содержащий все слова в строке.Я хочу, чтобы каждое слово в строке помещалось в вектор, а затем возвращалось.

Проблема возникает при третьем вызове функции (третья строка кода сборки).Я использую функцию ss.good (), чтобы определить, есть ли у меня слова в потоке строки.По какой-то причине функция ss.good () возвращает true, даже если в третьей строке нет четвертого слова, и в итоге я вставил слова [lea] [r0,] [ten] и [ten] в вектор.ss.good () имеет значение true при четвертом вызове, и токен ничего не получает, поэтому я дважды вставил [десять] в вектор.

Я замечаю, если уберу пробел между точкой с запятой и последним словом, этоошибка не возникаетЯ хочу знать, как вставить нужное количество слов в вектор.

Пожалуйста, не рекомендуйте Boost library.Мне нравится библиотека, но я хочу, чтобы этот проект был простым.В этом нет ничего большого, есть только дюжина инструкций для этого процессора.Кроме того, имейте в виду, что эта функция только наполовину запечена, я тестирую и отлаживаю ее постепенно.

1 Ответ

5 голосов
/ 01 июня 2011

Флаги ошибок потока устанавливаются только после условия (например, достижения конца потока).

Попробуйте заменить условие цикла на:

while(ss >> token)
{
    // Push it onto the words vector
    words.push_back(token);

    // If all we got was nothing, it's an empty line
    if(token == "")
    {
        code = make_tuple(EMPTY_LINE, words);
        return code;
    }
}

С этим кодом я получаю следующие токены для строки 3:

"LEA"
"R0,"
"TEN"
";"
"This"
"instruction"
"will"
"be"
"loaded"
"into"
"memory"
"location"
"x3000"

Я знаю, что язык, который вы пытаетесь разобрать, прост. Тем не менее, вы бы сделали себе одолжение, если бы рассмотрели использование специализированного инструмента для работы, такого как, например, flex.

...