Студопедия

КАТЕГОРИИ:


Архитектура-(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; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.007 сек.