|
Программирование >> Формирование пользовательского контейнера
Функция prescanO работает следующим образом. Каждый раз, когда обнаруживается открывающая фигурная скобка, переменная brace увеличивается на единицу. Когда же найдена закрывающая фигурная скобка, переменная brace уменьшается на единицу. Следовательно, если переменная brace больше нуля, текущая лексема читается из тела функции. Если же при обнаружении переменной brace равна нулю, пресканер знает, что найдена глобальная переменная. Точно так же, если при brace, равной нулю, обнаружено имя функции, то это должно быть определение функции (напоминаю, что интерпретатор Mini С++ не поддерживает прототипы функций). Глобальные переменные сохраняются в векторе, названном giobai vars и содержащем структуры типа var type, описание которых приведено далее. Эта структура инкапсулирует информацию, связанную с переменными, struct var type { char var name[MAX ID LEN+l]; имя token ireps v type; тип данных int value; значение Приведенная структура содержит имя, значение и тип переменной. Глобальные переменные помещаются в вектор giobai vars с помощью функции deci giobai (), Приведенной далее. Объявление глобешьной переменной void decllobalO token ireps vartype; var type vt; get token(); получает тип vartype = tok; сохраняет тип переменной Обрабатывает список, разделенный запятыми, do { vt.v type = vartype; vt.value =0; инициализирует с нулевым значением get token(); получает имя Проверяет, не дублируется ли переменная, for(unsigned i=0; i < global vars.size(); i++) i f(!s trcmp(global vars[i].var pame, token)) throw InterpExc(DUP VAR); strcpy(vt.var name, token); global vars. push back (vt); get token(); } while(*token == ); if(*token != ;) throw InterpExc(SEMI EXPECTED); По существу функция decl giobal () получает тип и имя переменной, инициализирует ее с нулевым значением и помещает в конец вектора giobai vars. Но сначала проверяется, нет ли уже объявленной переменной с таким же именем. Местоположение каждой функции, определенной пользователем, помещается в вектор, названный func table и содержащий структуры типа func type, описание которых приведено далее. Эта структура инкапсулирует данные о функции, struct func type { char func name[MAX ID LEN+l]; имя token ireps ret type; тип возвращаемого значения char *1ос; положение точки входа в программе Каждый элемент вектора содержит тип возвращаемого значения, имя и местоположение точки входа функции в исходном коде. Прежде чем внести эти сведения в вектор, функция prescanO проверяет, не существует ли уже функции с тем же именем. Обратите внимание на то, что никакой информации о параметрах не сохраняется. Она будет получена во время выполнения, когда будет сделан действительный вызов функции. Функция interpO Функция interpO - ЭТО сердце интерпретатора. Она рещает, какое действие предпринять, основываясь на лексеме, следующей за текущей во входном потоке. Эта функция интерпретирует одну логическую единицу кода и заверщается. Если единица кода содержит один оператор, то он интерпретируется, и функция возвращается. Если же прочитана открывающая фигурная скобка, то интерпретируются все операторы, входящие в блок. Для этого служит переменная-флаг - block, которой присваивается 1, если считана else { фигурная скобка }, поэтому восстанавливает область видимости и возвращается Восстанавливает вложенную область видимости. local var stack.resize(nest scope stack.top()); nest scope stack.pop(); return; открывающая фигурная скобка. Благодаря этому функция продолжает интерпретировать операторы до тех пор, пока не будет прочитана закрывающая фигурная скобка. Далее приведен код функции interpo. Интерпретирует отдельный оператор или блок кода. Функиия interpO возвращается из первоначального вызова, если обнаружена конечная фигурная скобка (или return) в функции main(). void interpO int value; int block = 0; do { He интерпретирует, пока не обработан break, if(breakfound) return; token type = get token(); Проверяет, какая лексема представлена, if(token type == IDENTIFIER ♦token == INC I I *token == DEC) He ключевое слово, поэтому обрабатывает выражение, putbackO; возвращает лексему во входной поток для последугацей обработки с помощью eval exp() eval eэф (value); обрабатывает выражение if(*token != ;) throw InterpExc(SEMI EXPECTED); else if(token type==BLOCK) { ограничитель блока? if(*token == ) { блок block =1; интерпретирует блок, a не оператор Записывает вложенную область видимости. nest scope stack.push(local var stack.size());
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |