КАТЕГОРИИ: Архитектура-(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) |
Контроль контекстных условий в выражении
Пусть есть функция char *gettype (char *op, char *t1, char *t2), которая проверяет допустимость сочетания операндов типа t1 (первый операнд) и типа t2 (второй операнд) в операции op; если типы совместимы, то выдает тип результата этой операции; иначе - строку "no". Типы операндов и обозначение операции будем хранить в стеке; для этого нам нужны функции для работы со стеком строк:
void spush (char *s); /* значение s - в стек */ char *spop (void); /* из стека - строку */
Если в выражении встречается лексема-целое_число или логические константы true или false,то соответствующий тип сразу заносим в стек с помощью spush("int") или spush("bool"). Если операнд - лексема-переменная, то необходимо проверить, описана ли она; если описана, то ее тип надо занести в стек. Эти действия можно выполнить с помощью функции checkid:
void checkid (void) {int i; i = curr_lex.value; if (TID [i].declare) /* описан? */ spush (TID [i].type); /* тип - в стек */ else ERROR(); /* описание отсутствует */ }
Тогда для контроля контекстных условий каждой тройки - "операнд-операция-операнд" будем использовать функцию checkop:
void checkop (void) {char *op; char *t1;char *t2; char *res; t2 = spop(); /* из стека - тип второго операнда */ op = spop(); /* из стека - обозначение операции */ t1 = spop(); /* из стека - тип первого операнда */ res = gettype (op,t1,t2); /* допустимо? */ if (strcmp (res, "no")) spush (res); /* да! */ else ERROR(); /* нет! */ }
Для контроля за типом операнда одноместной операции not будем использовать функцию checknot:
void checknot (void) {if (strcmp (spop (), "bool")) ERROR(); else spush ("bool");}
Теперь главный вопрос: когда вызывать эти функции? В грамматике модельного языка задано старшинство операций: наивысший приоритет имеет операция отрицания, затем в порядке убывания приоритета - группа операций умножения (*, /, and), группа операций сложения (+,-,or), операции отношения. E ® E1 | E1 [ = | < | > ] E1 E1 ® T {[ + | - | or ] T} T ® F {[ * | / | and ] F} F ® I | N | [ true | false ] | not F | (E)
Именно это свойство грамматики позволит провести синтаксически-управляемый контроль контекстных условий. Замечание: сравните грамматики, описывающие выражения, состоящие из символов +, *, (,), i: G1: E ® E+E | E*E | (E) | i G4: E ® T | E+T G2: E ® E+T | E*T | T T ® F | T*F T ® i | (E) F ® i | (E) G3: E ® T+E | T*E | T G5: E ® T | T+E T ® i |(E) T ® F | F*T F ® i | (E), оцените, насколько они удобны для трансляции выражений.
Правила вывода выражений модельного языка с действиями для контроля контекстных условий:
E ® E1 | E1 [ = | < | > ] < spush(TD[curr_lex.value]) > E1 < checkop() > E1 ® T {[ + | - | or ] < spush(TD[curr_lex.value]) > T < checkop() > } T ® F {[ * | / | and ] < spush(TD[curr_lex.value]) > F < checkop() > } F ® I < checkid() > | N < spush("int") > |[ true | false ] < spush ("bool") | not F < checknot() > | (E) Замечание: TD - это таблица ограничителей, к которым относятся и знаки операций; будем считать, что это массив #define MAXSIZE_TD 50 char * TD[MAXSIZE_TD]; именно из этой таблицы по номеру лексемы в классе выбираем обозначение операции в виде строки.
Дата добавления: 2015-06-27; Просмотров: 355; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |