Чтение онлайн

на главную - закладки

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

switch (t.kind) {

case let:

return declaration;

default:

ts.putback(t);

return expression;

}

}

Вместо функции

expression
в функции
calculate
можем использовать функцию
statement
.

void calculate

{

while (cin)

try {

cout << prompt;

Token t = ts.get;

while (t.kind == print) t=ts.get; //
игнорируем
"печать"

if (t.kind == quit) return; // выход

ts.putback(t);

cout << result << statement << endl;

}

catch (exception& e) {

cerr << e.what << endl; // выводим сообщение об ошибке

clean_up_mess;

}

}

Теперь необходимо написать функцию

declaration
. Что следует сделать? Нужно убедиться, что после ключевого слова
let
следует Имя, а за ним — символ = и Выражение. Именно это утверждает грамматика. Что делать с членом
name
? Мы должны добавить в вектор
var_table
типа
vector<Variable>
объект класса
Variable
c заданными строкой name и значением выражения. После этого мы сможем извлекать значения с помощью функции
get_value
и изменять их с помощью функции
set_value
. Однако сначала надо решить, что случится, если мы определим переменную дважды. Рассмотрим пример.

let v1 = 7;

let v1 = 8;

Мы решили, что повторное определение является ошибкой. Обычно это просто синтаксическая ошибка. Вероятно, мы имели в виду не то, что написали, а следующие инструкции:

let v1 = 7;

let v2 = 8;

Определение объекта класса

Variable
с именем
var
и значением
val
состоит из двух логических частей.

1. Проверяем, существует ли в векторе

var_table
объект класса
Variable
с именем
var
.

2. Добавляем пару (

var
,
val
) в вектор
var_table
.

Мы не должны использовать неинициализированные переменные, поэтому определили функции

is_declared
и
define_name
, представляющие эти две операции.

bool is_declared(string var)

// есть ли переменная var в векторе var_table?

{

for (int i = 0; i<var_table.size; ++i)

if (var_table[i].name == var) return true;

return false;

}

double define_name(string var, double val)

//
добавляем пару (var,val) в вектор var_table

{

if (is_declared(var)) error(var,"declared twice");

var_table.push_back(Variable(var,val));

return val;

}

Добавить новый объект класса

Variable
в вектор типа
vector<Variable>
легко; эту операцию выполняет функция-член вектора
push_back
.

var_table.push_back(Variable(var,val));

Вызов конструктора

Variable(var,val)
создает соответствующий объект класса
Variable
, а затем функция
push_back
добавляет этот объект в конец вектора
var_table
. В этих условиях и с учетом лексем
let
и
name
функция
declaration
становится вполне очевидной.

double declaration

// предполагается, что мы можем выделить ключевое слово "let"

// обработка: name = выражение

// объявляется переменная с именем "name" с начальным значением,

// заданным "выражением"

{

Token t = ts.get;

if (t.kind != name) error ("в объявлении ожидается переменная
name");

string var_name = t.name;

Token t2 = ts.get;

if (t2.kind != '=') error("в объявлении пропущен символ =",

var_name);

double d = expression;

define_name(var_name,d);

return d;

}

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

let v = d/(t2–t1);

Это объявление определяет переменную

v
и выводит ее значение. Кроме того, печать переменной упрощает код функции
calculate
, поскольку при каждом вызове функция
statement
возвращает значение. Как правило, общие правила позволяют сохранить простоту кода, а специальные варианты приводят к усложнениям.

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

map
(см. раздел 21.6.1).

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

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Сердце Дракона. Том 11

Клеванский Кирилл Сергеевич
11. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.50
рейтинг книги
Сердце Дракона. Том 11

Первый среди равных. Книга IV

Бор Жорж
4. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IV

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Мастер Разума IV

Кронос Александр
4. Мастер Разума
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер Разума IV

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Кадры решают все

Злотников Роман Валерьевич
2. Элита элит
Фантастика:
боевая фантастика
попаданцы
альтернативная история
8.09
рейтинг книги
Кадры решают все

Плеяда

Суконкин Алексей
Проза:
военная проза
русская классическая проза
5.00
рейтинг книги
Плеяда

Потусторонний. Книга 2

Погуляй Юрий Александрович
2. Господин Артемьев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Потусторонний. Книга 2

Ученик. Книга 4

Первухин Андрей Евгеньевич
4. Ученик
Фантастика:
фэнтези
5.67
рейтинг книги
Ученик. Книга 4

Законник Российской Империи. Том 3

Ткачев Андрей Юрьевич
3. Словом и делом
Фантастика:
городское фэнтези
альтернативная история
аниме
дорама
5.00
рейтинг книги
Законник Российской Империи. Том 3

Ваше Сиятельство 7

Моури Эрли
7. Ваше Сиятельство
Фантастика:
боевая фантастика
аниме
5.00
рейтинг книги
Ваше Сиятельство 7

Война

Валериев Игорь
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Война

Младший сын князя. Том 4

Ткачев Андрей Юрьевич
4. Аналитик
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Младший сын князя. Том 4