Студопедия

КАТЕГОРИИ:


Архитектура-(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)

Лекция 14




Лекция 13

Расширенная функция expr ()

 

void expr ()

{

int neg = (lex == ' - ');

if (lex == '+' || lex == '-')

get();

term();

if (neg)

gen (OPR, 8);

while (lex == '+' || lex == '-')

{

neg = (lex == ' - '? 4: 3);

get();

term();

gen (OPR, neg);

}

return;

}

Если после вызова expr () лексема lex равняется «-», то присваивается «истина» т.е. 1. В этом случае генерируется команда OPR 8 – изменение знака числа в вершине стека.

Затем пеg используется для запоминания последующих «+»или «-» с соответствующей генерацией операций сложения OPR 3 или вычитания OPR 4.

 

Расширенная функция term()

void term ()

{

int op;

fact();

while (lex == '*' || lex == '/' || lex == '%')

{

op = (lex == '*'? 5: (lex == '/'? 6: 7));

get();

fact();

gen (OPR, op);

}

return;

}

Переменная op приобретает значение 5 или 6, или 7 в зависимости от операции. Соответственно генерируются команды OPR 5 или OPR 6, или OPR 7.

 

Расширенная функция fact()

void fact ()

{

char *nm;

int cp; // Количество аргументов

odc *p;

fnd *p1;

switch (lex)

{

 

case IDEN: nm = (char *)lval; get();

if (lex == '(')

{

get();

cp = (lex == ')'? 0: fctl()); // FCTL вернет количество фактических

переменных

exam(')');

p1 = eval (nm, cp); // Вызов функции по имени nm и количеству параметров cp

gen (LIT, cp);// Занесение в стек количества параметров функции

cp = gen (CAL, p1->start); // Запоминание адреса в TCD команды вызова

if (!p1->isd)

p1->start = cp;/* Если функция не описана, тов p1->start заносится адресTCDеё вызова */

}

else

{

p = findob (nm);

gen (p->what == 1? LIT: (p->what == 2? LDE: LDI), p->val);

}

break;

case '(': get(); expr(); exam(')');

break;

case NUMB: gen (LIT, lval); get();

break;

default: printf ("Ошибка синтаксиса в функции fact() lex=%i nst=%i \n", lex, nst);

exit(1);

}

return;

}

 

По case IDEN. В случае, если после идентификатора следует круглая скобка, это означает, что имеет место функция.

В этом случае определяется её количество параметров ср и происходит вызов.

Если после идентификатора скобка отсутствует, то имеет место переменная или константа. Производится поиск объекта по имени в ТОВ, и в случае нахождения его генерируется одна из команд {LIT, lval},{LDE, lval} или {LDI, lval } в зависимости от того, это константа, глобальная или локальная переменная.

 

Расширенная функция fctl()

int fctl ()

{

int cf = 1; // Это значит, что одно выражение уже есть. Могут быть и другие

expr();

while (lex == ',')

{

get();

expr();

cf++;

}

return cf;

}

Расширенная fctl() «по совместительству», также подсчитывает количество выражений cf.

 

Заполнение других таблиц

 

Кроме таблицы команд, несколько расширенных функций также заполняют таблицы объектов ТОВ и функций TFN.

 

Заполнение таблицы объектов

 

Используется функция newob(). Вызывается из расширенных функций cons(), dvarb(), param(). Обычно вызов функции newob() происходит перед exam(IDEN) или exam(NUMB) после get().

 

Расширенная функция cons()

void cons ()

{

char *nm = (char *)lval; //указатель на имя константы

int s;

exam (IDEN);

exam('=');

s = (lex == '-'? -1: 1);

if (lex == '-' || lex == '+')

get();

newob (nm, 1, s*lval); //Занесение константы в ТОВ.

exam (NUMB);

return;

}

 

 

Расширенная функция dvarb()

 

void dvarb ()

{

do

{

get();

newob ((char *)lval, (out? 2: 3), (out? cgv++: ++clv));

exam (IDEN);

} while (lex == ',');

exam (';');

return;

}

При занесении в ТОВ переменной с помощью признака out определяют, является она глобальной или локальной. Если глобальная, то в структуре odc компонента what получает значение 2, а компонента val (смещение в стеке)- cgv+ +. Иначе- what примет значение 3, а val - + +clv. Следует обратить внимание, что смещение для глобальных переменных начинается с нуля. Глобальная переменная int cgv=0 при инициализации обнуляется. Поэтому самая первая глобальная переменная имеет смещение нуль и будет помещена в st[0]. Благодаря увеличению cgv на 1 после операции, следующая глобальная переменная попадет в st[1] и т.д.

Для локальных переменных смещение начинается с единицы. Поскольку предварительно

clv обнуляется, прежде чем заносить локальную переменную, выполняется увеличение clv на единицу (++clv).

Признак out всегда равен единице, а при занесении локальных переменных в функции dfunc() out=0, а затем снова восстанавливается out=1.

Расширенная функция dfunc()

void dfunc ()

{

int cp; // Количество параметров функции

int st; // Точка входа в функцию

char *nm = (char *)lval; //Идентификатор функции

get();

out = 0; //Признак того, что будет локальная переменная

cp = param(); // вернет количество параметров

st = body(); // вернет точку входа в функцию

out = 1; // Восстановили признак out.

ptol = pto; //заполняется указатель, откуда можно заносить локальные переменные

defin (nm, cp, st); //Определение функции

return;

}

 

Расширенная функция param ()

 

int param ()

{

odc *p;

int cp = 0; //количество параметров

exam('(');

if (lex!= ')')

{

newob ((char *)lval, 3, ++cp);

exam (IDEN);

while (lex == ',')

{

get();

newob ((char *)lval, 3, ++cp);

exam (IDEN);

}

}

exam (')');

for (p = ptol; p < pto; p++)

p->val -= cp+3;

return cp;

}

 

«Сверху» над ptol размещаются глобальные переменные. Между ptol и pto- локальные. После занесения параметров функции в ТОВ необходимо скорректировать их смещение в стеке на три (для хранения в стеке количества параметров функции и двух адресов: адрес возврата АВОЗ и адреса активации ААК). Это осуществляется в цикле for(), где смещение p→val уменьшается на ср+3. Например, функция f(x,y,z) имеет три параметра. До цикла for смещение у переменной x равно 1, для y равно 2, для z равно 3. После цикла for() смещение для x равно -5, для y - -4,

для z --3.

 

Расширенная функция prog()

В языке SPL предусмотрено, что программа начинает работу с функции main(). Для этого необходимо организовать поиск этой функции в тексте программы на SPL. В случае, если функция найдена, надо запомнить адрес её точки входа (начальный адрес в таблице команд TCD) и имеющееся у неё количество параметров. Для этого нужны глобальные переменные:

 

int adrnm; // Адрес начала main()

int cpnm; //количество параметров для main()

 

Текст расширенной функции prog()

 

void prog ()

{

fnd *p;

while (lex!= EOF)

switch (lex)

{

case CONSTL: dconst(); break;

case INTL: dvarb(); break;

case IDEN: dfunc(); break;

default: printf (“ В prog недопустимая лексема lex=%i в строке

nst=%i\n”,lex, nst);

}

p = fmain();

adrnm = p->start;// Адрес точки входа main() в TCD

cpnm = p->cpt;/ Количество параметров у функции main()

return;

}

В заключение приведем таблицу функций, предназначенных для обслуживания таблиц и функции fmain() и откуда они вызываются.

 

  Название функции Функции,использующие данную функцию
  newob(char*nm, int wt, int vl) cons(), dvarb(), param()
  findob(char*nm) stat(), fact
  newfn(char*nm, int df, int cp, int ps) eval(char*nm, int cp); define(char*nm, int cp, int ad)
  findfn(char*nm) eval(char*nm, int cp); defin(char*nm, int cp, int ad)
  eval(char*nm, int cp) fact()
  defin(char*nm, int cp, int ad) dfunc()
  fmain() prog()

 

 




Поделиться с друзьями:


Дата добавления: 2015-06-27; Просмотров: 336; Нарушение авторских прав?; Мы поможем в написании вашей работы!


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



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




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