Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

default:

if (isalpha(ch)) {

cin.putback(ch);

string s;

cin>>s;

if (s == declkey) return Token(let); // ключевое
слово let

return Token(name,s);

}

error("Неправильная лексема");

}

}

В первую очередь обратите внимание на вызов функции

isalpha(ch)
. Этот вызов отвечает на вопрос “Является ли символ
ch
буквой?”; функция
isalpha
принадлежит стандартной библиотеке и описана в заголовочном файле
std_lib_facilities.h
. Остальные функции классификации символов описаны в разделе 11.6. Логика распознавания имен совпадает с логикой распознавания чисел: находим первый символ соответствующего типа (в данном случае букву), а затем возвращаем его назад в поток с помощью функции
putback
и считываем все имя целиком с помощью оператора
>>
.

К сожалению, этот код не компилируется; класс

Token
не может хранить строку, поэтому компилятор отказывается распознавать вызов
Token(name,s)
. К счастью, эту проблему легко исправить, предусмотрев такую возможность в определении класса
Token
.

class Token {

public:

char kind;

double value;

string name;

Token(char ch):kind(ch), value(0) { }

Token(char ch, double val) :kind(ch), value(val) { }

Token(char ch, string n) :kind(ch), name(n) { }

};

Для представления лексемы

let
мы выбрали букву
'L'
, а само ключевое слово храним в виде строки. Очевидно, что это ключевое слово легко заменить ключевыми словами
double
,
var
,
#
, просто изменив содержимое строки
declkey
, с которой сравнивается строка
s
.

Попытаемся снова протестировать программу. Если напечатать следующие выражения, то легко убедиться, что программа работает:

let x = 3.4;

let y = 2;

x + y * 2;

Однако следующие выражения показывают, что программа еще не работает так, как надо:

let x = 3.4;

let y = 2;

x+y*2;

Чем различаются эти примеры? Посмотрим, что происходит. Проблема в том, что мы небрежно определили лексему

Имя
. Мы даже “забыли” включить правило вывода
Имя
в грамматику (раздел 7.8.1). Какие символы могут бы частью имени? Буквы? Конечно. Цифры? Разумеется, если с них не начинается имя. Символ подчеркивания? Нет? Символ
+
? Неужели?

Посмотрим на код еще раз. После первой буквы считываем строку в объект класса

string
с помощью оператора
>>
. Он считывает все символы, пока не встретит пробел. Так, например, строка
x+y*2;
является отдельным именем — даже завершающая точка с запятой считывается как часть имени. Это неправильно и неприемлемо.

Что же сделать вместо этого? Во-первых, мы должны точно определить, что представляет собой имя, а затем изменить функцию

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

a

ab

a1

Z12

asdsddsfdfdasfdsa434RTHTD12345dfdsa8fsd888fadsf

А следующие строки именами не являются:

1a

as_s

#

as*

a car

За исключением отброшенного символа подчеркивания это совпадает с правилом языка С++. Мы можем реализовать его в разделе

default
в функции
get
.

default:

if (isalpha(ch)) {

string s;

s += ch;

while (cin.get(ch) && (isalpha(ch) || isdigit(ch)))

s+=ch;

cin.putback(ch);

if (s == declkey) return Token(let); // ключевое слово let

return Token(name,s);

}

error("Неправильная лексема");

Вместо непосредственного считывания в объект

string s
считываем символ и записываем его в переменную
s
, если он является буквой или цифрой. Инструкция
s+=ch
добавляет (приписывает) символ
ch
в конец строки
s
. Любопытная инструкция

while (cin.get(ch) && (isalpha(ch) || isdigit(ch)) s+=ch;

считывает символ в переменную

ch
(используя функцию-член
get
потока
cin
) и проверяет, является ли он символом или цифрой. Если да, то она добавляет символ
ch
в строку
s
и считывает символ снова. Функция-член
get
работает как оператор
>>
, за исключением того, что не может по умолчанию пропускать пробелы.

  • Читать дальше
  • 1
  • ...
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: