vector
В вектор var_table
можно записать сколько угодно объектов класса Variable
, а найти их можно, просматривая элементы вектора один за другим. Теперь можно написать функцию get_value()
, которая ищет заданную строку name
и возвращает соответствующее ей значение value
.
double get_value(string s)
// возвращает значение переменной с именем s
{
for (int i = 0; i
if (var_table[i].name == s) return var_table[i].value;
error("get: неопределенная переменная", s);
}
Этот код действительно прост: он перебирает объекты класса Variable
в векторе var_table
(начиная с первого элемента и продолжая до последнего включительно) и проверяет, совпадает ли их член name c аргументом s
. Если строки name и s
совпадают, функция возвращает член value
соответствующего объекта. Аналогично можно определить функцию set_value()
, присваивающую новое значение члену value
объекта класса Variable
.
void set_value(string s, double d)
// присваивает объекту класса Variable с именем s значение d
{
for (int i = 0; i
if (var_table[i].name == s) {
var_table[i].value = d;
return;
}
error("set: неопределенная переменная", s);
}
Теперь можем считать и записывать переменные, представленные в виде объектов класса Variable
в векторе var_table
. Как поместить новый объект класса Variable
в вектор var_table
? Как пользователь калькулятора должен сначала записать переменную, а затем присвоить ей значения? Можно сослаться на обозначения, принятые в языке С++.
double var = 7.2;
Это работает, но все переменные в данном калькулятора и так хранят значения типа double
, поэтому явно указывать этот тип совершенно не обязательно. Можно было бы написать проще.
var = 7.2;
Что ж, возможно, но теперь мы не можем отличить определение новой переменной от синтаксической ошибки.
var1 = 7.2; // определение новой переменной с именем var1
var1 = 3.2; // определение новой переменной с именем var2
Ой! Очевидно, что мы имели в виду var2 = 3.2;
но не сказали об этом явно (за исключением комментария). Это не катастрофа, но будем следовать традициям языков программирования, в частности языка С++, в которых объявления переменных с их инициализацией отличаются от присваивания. Мы можем использовать ключевое слово double
, но для калькулятора нужно что-нибудь покороче, поэтому — следуя другой старой традиции — выбрали ключевое слово let
.
let var = 7.2;
Грамматика принимает следующий вид:
Вычисление:
Инструкция
Печать
Выход
Инструкция вычисления
Инструкция:
Объявление
Выражение
Объявление:
"let" Имя "=" Выражение
Вычисление — это новое правило вывода в грамматике. Оно выражает цикл (в функции calculate()
), который позволяет выполнять несколько вычислений в ходе одного сеанса работы программы. При обработке выражений и объявлений это правило опирается на правило Инструкция. Например, инструкцию можно обработать следующим образом:
double statement()
{
Token t = ts.get();
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();
}
}