Программирование >>  Формирование пользовательского контейнера 

1 ... 137 138 139 [ 140 ] 141 142 143 ... 156


else ключевое слово switch(tok) { case CHAR:

case INT: объявляет локальные переменные putbackO ; decl local(); break;

case RETURN: возвращается из вызванной функции func ret(); return;

case IF: обрабатывает оператор if

exec if(); break;

case ELSE: обрабатывает оператор else findeobO; находит конец блока else и продолжает выполнение

break;

case WHILE: обрабатывает цикл while exec while(); break;

case DO: обрабатьшает цикл do-while

, exec do(); break;

case FOR: обрабатьшает цикл for exec f or (); break;

case BREAK: обрабатьшает break breakfound = true;

Восстанавливает вложенную область видимости. local var stack. resize (nest scope stack. top О ); nest scope stack.pop(); return;

case SWITCH: обрабатывает оператор switch

exec switch (); ,

break;

case COUT: обрабатьшает консольный вывод



exec cout(); break;

case CIN: обрабатывает консольный ввод

exec cin();

break; case END:

exit(O);

} while (tok != END && block); return;

Если нет вызовов таких функций, как exito, профамма на С++ завершается когда обнаружена последняя фигурная скобка (или оператор return) - необязательно в последней сфоке исходного кода. Это одна из причин, по которой функция interpO выполняет оператор или блок кода, а не всю профамму целиком. Кроме того, концептуально С++ состоит из блоков кода. Следовательно, функция interpO вызывается каждый раз, когда обнаружен новый блок кода. Это может быть блок функции и блок, начинающийся в различных операторах С++, таких как if. В процессе выполнения профаммы интерпретатор Mini С++ может вызывать функцию interpO рекурсивно.

Функция interpO работает следующим образом. Сначала она определяет, не обнаружен ли в профамме оператор break. Если да, то глобальная переменная breakfound будет равна true. Эта переменная сохраняет свое значение, пока она не будет очищена другой частью интерпретатора, вы увидите это при описании интерпретации управляющих операторов.

Предположим, что breakfound равна false, тогда функция interpO читает следующую лексему из профаммы. Если прочитан идентификатор, то текущий оператор - выражение, поэтому вызывается анализатор выражений. Поскольку анализатор будет читать первую лексему выражения самостоятельно, она возвращается во входной поток с помощью функции putbackO. Когда завершится функция evai exp(), переменная token будет содержать последнюю лексему, прочитанную анализатором выражений, которая должна быть точкой с запятой, если обрабатываемый оператор синтаксически корректен. Если лексема не содержит точки с запятой, выводится сообщение об ошибке.

Если следующая лексема профаммы - открывающая фигурная скобка, переменной block присваивается 1, и текущий размер стека, названного local var stack, помешается в стек nest scope stack. Стек 1 осаl var stack содержит все локальные переменные, включая те, которые объявлены



в областях видимости вложенных блоков. И наоборот, если следующая лексема - закрывающая фигурная скобка, стек iocai var stack усекается до размера, заданного в вершине стека nest scope stack. Это действие эффективно удаляет любые локальные переменные, которые могли быть объявлены внутри блока. Таким образом, { вызывает сохранение размера стека локальных переменных, а } возвращает стеку его предыдущий размер. Описанный механизм поддерживает вложенные локальные области видимости переменных.

Наконец, если лексема - ключевое слово, выполняется оператор switch, вызывающий соответствующую процедуру для обработки оператора. В функции get token () ключевым словам поставлены в соответствие целочисленные эквиваленты, что позволяет использовать оператор switch вместо требуемой последовательности операторов if, включающих сравнения строк (которые выполняются очень медленно).

Обработка локальных переменных

Когда интерпретатор находит ключевые слова int или char, он вызывает функцию deci iocal{) ДЛЯ размещения в памяти локальных переменных. Как установлено ранее, во время выполнения программы интерпретатор не может встретить ни одного оператора объявления глобальной переменной, потому что выполняемый код находится внутри функции. Следовательно, если обнаружен оператор объявления переменной, то это должна быть локальная переменная (или параметр функции, о котором речь пойдет в следующем разделе). Как правило, локальные переменные хранятся в стеке. Если язык компилируется, то обычно используется системный стек, однако в режиме интерпретации стек для локальных переменных должен nozmep-живаться интерпретатором.

В Mini С++ переменная 1 осаl var stack предоставляет стек для хранения локальных переменных. Кое-что неожиданное: эта переменная - контейнер типа vector, а не stack. Причина заключается в том, что хотя локальные переменные обрабатываются как элементы стека, хранящий их контейнер должен обеспечивать последовательный поиск, если нужен доступ к значению переменной. В отличие от вектора, у контейнера типа stack нет удобного механизма такого поиска. Далее приведен код функции deci iocai (). ОСъявление локальной переменной, void decl local() {

var type vt;

get token(); получает тип переменной



1 ... 137 138 139 [ 140 ] 141 142 143 ... 156

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика