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

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

Шрифт:

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).

7.8.2. Использование имен

Все это очень хорошо, но, к сожалению, не работает. Это не должно было стать для нас сюрпризом. Первый вариант никогда — почти никогда — не работает. В данном случае мы даже не закончили программу — она даже не скомпилируется. У нас нет лексемы

'='
, но это легко исправить, добавив дополнительный раздел
case
в функцию
Token_stream::get
(см. раздел 7.6.3). А как представить ключевые слова
let
и
name
в виде лексем? Очевидно, для того чтобы распознавать эти лексемы, необходимо модифицировать функцию
get
. Как? Вот один из способов.

const char name = 'a'; // лексема name

const char let = 'L'; // лексема let

const string declkey = "let"; // ключевое слово let

Token Token_stream::get

{

if (full) { full=false; return buffer; }

char ch;

cin >> ch;

switch (ch) {

// как и прежде

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

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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