КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Лекция 15
Выполнение SPL- программы Опишем в качестве глобальных переменных в программе на Си еще две переменные: int t; //st[t]- вершина стека; int sp; //st[sp]- начало области локальных переменных; int p; // Счетчик команд, считываемых из TCD. В функции main() интерпретатора на Си после вызова функций get();, prog(); добавим вызов функции interp();. Функция interp(); начинает и завершает выполнение SPL - программы, которая в виде последовательности промежуточных команд находится в таблице TC D. Эта функция использует следующие функции: comman()- исполняет текущую команду, прочитанную из таблицы команд TCD[p], где р- значение счетчика команд; operat(a)- выполняет одну из десяти операций OPR a; push(a)- заносит значение параметра а в вершину стека; reader()- служит для ввода с клавиатуры числа в вершину стека (stdin→t).
Функция interp() void interp () { int i; t = -1; /*В вершину стека st[t] заносится -1, чтобы при вызове функции push(а) первое занесение по st[+ +t]=а произошло в st[0] */ puts(“SPL-интерпретация \n”); for (i = 0; i < cgv; i++) push(0); /* В стек заносятся нулевые значения глобальных переменных, количество которых cqv уже известно, а конкретные значения будут введены позже*/
if (cpnm) { printf ("%d>", cpnm); fflush (stdin); for (i = 0; i < cpnm; i++) push (reader()); }/*Если количество параметров cpnm у функции main() не равно нулю, то в цикле for() вводятся с клавиатуры их значения*/ push (cpnm); /*В стек вводится количество параметров функций main()*/ push(-2);/* при р=-2 остановка*/ push(-1);/* при р= -1 - вывод на экран содержимого вершины стека st[t]*/ sp = t; /*при заполнении стека изменяется значение t. Теперь это значение присваивается переменной sp - верхней записи активации в стеке*/ p = adrnm; /*В счетчик команд записывается начальный адрес (точка входа) функции main() в таблице команд. Именно с этого номера начнут считываться и выполняться промежуточные команды, записанные в TCD* /
do { comman(); // Выполняются команды из TCD[p] p++; //Изменение счетчика команд } while (p >= 0); if (p == -1) printf ("%d\n", st[t]);/*Если р<0 и р= = -1, то происходит вывод на экран значения вершины стека st[t]*/ return; } Исполнение команд void comman () { int a = TCD[p].opd; //Значение операнда присваивается переменной а
switch (TCD[p].cod) { case OPR: operat(a); break; case LIT: push(a); break;//{LIT a} case LDE: push(st[a]); break;//{LDE a} case LDI: push(st[sp+a]); break;//{LDI a} case STE: st[a] = st[t--]; break; /*Следует обратить внимание, что после присваивания глобальной переменной st[a] значения из вершины стека t, значение t уменьшается на единицу*/ case STI: st[sp+a] = st[t--]; break; case CAL: push(p); push(sp);sp = t; p = a-1; break;/*Запоминаются в стеке текущие значения счетчика команд p и sp. Затем sp=t. Теперь верхняя запись активации является вершиной стека. В счетчик команд р заносится а-1. При возврате в функцию interp() будет выполняться команда р + +. В результате счетчик р станет равным а. Таким образом, будет реализован вызов функции {CAL a }*/ case INI: for (i =0; i<a; i++) push(0); /* Нужно увеличить адрес вершины стека на а. В вершину стека последовательно заносятся а нулей*/ break; case JMP: p = a-1; break;/*В счетчик команд р заносится на единицу меньший номер команды в TCD, которая должна выполняться следующей*/ case JMC: if (st[t--] <= 0) p = a-1;/*Если число в стеке ≤0, то в счетчик команд заносится а-1. Вследствие того, что адрес t уменьшается после проверки, проверяемое в вершине стека число теряется*/ } return; } Исполнение операций
void operat (int a) { int j = t-1; switch (a) { case 1: printf ("1>"); fflush (stdin); push (reader()); /*занесение числа с клавиатуры в вершину стека*/ break; case 2: printf ("%d\n", st[t--]); break; case 3: st[j] += st[t--]; break; /* Например t=10, j=10-1=9 st[9]=st[9]+ st[10]. После этого t - - и t=9. Итак, результат находится в st[9]. Теперь это вершина стека */ case 4: st[j] -= st[t--]; break; case 5: st[j] *= st[t--]; break; case 6: if (st[t] == 0) { printf ("/: Деление на ноль"); exit(1); } st[j] /= st[t--]; break; case 7: if (st[t] = = 0) { printf ("%: Деление на ноль"); exit(1); } st[j] %= st[t--]; break; case 8: st[t] = -st[t]; break; case 9: j = st[sp-2]; st[sp-j-2] = st[t]; t = sp-j-2;//Новое значение t p= st[sp-1]; //В счетчик команд заносится адрес возврата АВОЗ sp = st[sp]; // Новый адрес активации ААК break; case 10: p = -3;/*После возвращения в comman() и затем в interp() после р + + счетчик станет р= -2 */ break; } return; } Занесение в стек void push (int а) { if (t >= 499) // t- вершина стека (глобальная переменная) { puts («Переполнение стека»); exit(1); } st[++t] = а; return; } Ввод последующего целого числа из stdin int reader () { int v, c; do { putsh (“Введите целое число”); fflus(stdin); c = getchar();//Ввод символа с клавиатуры } while (isspace(c)); /*Цикл будет повторяться, пока вводятся символы: ‘\ ’,’ \n’,’\t’,’\v’,’\f’ */ if (! isdigit(c)) { printf ("Ошибка при вводе данных"); exit(1)); } for (v = 0; isdigit(c); c = getchar()) v = v*10 + c - '0 '; /*По isdigit() проверяется ввод цифры. Иначе- сообщение об ошибке ввода и прекращение работы интерпретатора. Если была введена цифра, то в цикле for() формируется число v. Сначала v=0, проверяется условие, что с – цифра, и выполняется v=v*10+с-‘0’; Пусть вводится число 521. Код цифры 5 в 16 -ричной системе 35, а код нуля – 30. v=0*10+35-30=5. Затем вновь считывается код 32 цифры «2». Выполняется v=5*10+32-30=52. Считывается код 31 цифры «1» v=52*10+31-30=521. Следующий введенный символ не будет цифрой. Происходит выход из цикла */ ungetc (c, stdin); /*Выталкивание символа с обратно во входной поток*/ return v;/*Возврат результата в вызывающую функцию*/ }
Дата добавления: 2015-06-27; Просмотров: 384; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |