Литмир - Электронная Библиотека
A
A

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();

  }

}

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

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()
становится вполне очевидной.

102
{"b":"847443","o":1}