Шрифт:
Функция-член
putback
возвращает аргументы обратно в буфер объекта класса Token_stream
.
void Token_stream::putback(Token t)
{
buffer = t; // копируем объект t в буфер
full = true; // теперь буфер полон
}
Ключевое слово
void
(означающее “ничто”) означает, что функция putback
не возвращает никакого значения. Если бы мы хотели гарантировать, что эта функция не будет использована дважды без считывания лексем, возвращенных в промежутке между ее вызовами (с помощью функции get
), то нам следовало бы добавить проверку.
void Token_stream::putback(Token t)
{
if (full) error("putback в полный буфер");
buffer = t; // копируем объект t в буфер
full = true; // буфер теперь полон
}
Проверка переменной
full
соответствует проверке предусловия “В буфере нет ни одного объекта класса Token
”. 6.8.2. Считывание лексем
Всю реальную работу выполняет функция
get
. Если в переменной Token_stream::buffer
еще нет ни одного объекта класса Token
, то функция get
должна считать символы из потока cin
и составить из них объект класса Token
.
Token Token_stream::get
{
if (full) { // если в буфере есть лексема,
// удаляем ее оттуда
full=false;
return buffer;
}
char ch;
cin >> ch; // обратите внимание на то, что оператор >>
// пропускает разделители (пробелы, символы перехода
// на новую строку, символы табуляции и т.д.)
switch (ch) {
case ';': // для печати
case 'q': // для выхода
case '(': case ')': case '+': case '–': case '*': case '/':
return Token(ch); // пусть каждый символ
// представляет себя сам
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{ cin.putback(ch); // возвращаем цифру обратно в поток ввода
double val;
cin >> val; // считываем число с плавающей точкой
return Token('8',val); // пусть символ '8' означает "число"
}
default:
error("Неправильная лексема");
}
}
Детально рассмотрим функцию
get
. Сначала проверим, есть ли в буфере объект класса Token
. Если есть, то мы просто вернем его.
if (full) { // если в буфере есть лексема,
// удаляем ее оттуда
full=false;
return buffer;
}
Только если переменная
full
равна false
(т.е. в буфере нет лексем), нам придется иметь дело с символами. В данном случае считываем символ и соответствующим образом обрабатываем его. Мы распознаем скобки, операторы и числа. Любой другой символ становится причиной вызова функции error
, которая прекращает выполнение программы.
default:
error("Неправильная лексема");
Функция
error
описана в разделе 5.6.3 и находится в заголовочном файле std_lib_facilities.h
. Необходимо решить, как представлять разные виды лексем, т.е. выбрать значения, идентифицирующие вид члена. Для простоты отладки мы решили обозначать скобки и операторы соответствующими им символами.
Это позволяет чрезвычайно просто обрабатывать скобки и операторы.
case '(': case ')': case '+': case '–': case '*': case '/':