Реферат: Проектирование трансляторов
Подпрограмма GENERATETEMP(P) заносит в ST элемент для вре-
менной переменной, а адрес этого нового элемента возвращает в P.
Подпрограмма CONVERTRI(P)проверяет тип P-го элемента ST. Если тип
- INT, то ничего не делается, если REAL, то с помощью
GENERATETEMP заводится новая временная переменная типа INT и ге-
нерируется CVRI-тетрада для преобразования заданной переменной в
тип INT и занесения результата в новую временную переменную. Ука-
затель на временную переменную в ST остается в P. Если тип тип
Р-го элемента не INT и не REAL, то выдается сообщение об ошибке.
Перечислим семантическую информацию (в стеках), связанную с
<инд>:
1.<инд>.ENTRY -адрес элемента ST для d1(для di,если сгенери-
рован код i-го индексного выражения)
2.<инд>.ENTRY2 -адрес элемента ST для VARPART
3.<инд>.COUNT -[размерность - i], если сгенерирован код для
i-го индексного выражения
4.<инд>.ARR -адрес описателя имени массива в ST
Теперь для правила <инд1>::=<инд2>,<выр> надо сгенерировать
код, реализующий формулу VARPART:=VARPART*d1+<выр>, если это
второе по счету индексное выражение.
<инд1>::=<инд2>,<выр>
<инд1>.COUNT:=<инд2>.COUNT-1; -подсчет индексов
<инд1>.ARR:=<инд2>.ARR; -эапомнить тип элемента
<инд1>.ENTRY:=<инд2>.ENTRY+1;-в <инд1>.ENTRY занесли ук-ль на эл-тST для di
P1:=<инд2>.ENTRY2; -в P1 и в ENTRY2 адреса элемента ST для VARPART
<инд1>.ENTRY2:=P1;
ENTER(*,P1,<инд>.ENTRY,P1); -генерация тетрады VARPART=VARPART*di
P:=<выр>.ENTRY; -генерация тетрад преобразования R->I(если надо)
ENTER(+,P!,P,P!); -генерация тетрады VARPART=VARPART+индекс
Заметим, что мы всегда имеем дело не с самим выражением, а с
указателем на элемент ST, описывающий результат вычисления этого
выражения. Для правила <пер>::=<инд>) надо проверить (при компи-
ляции) количество индексных выражений и построить элемент STс
описанием элемента массива.
<пер>::=<инд>)
IF <инд>.COUNT!=0
THEN ERROR(6);
GENERATETEMP(P); -генерирование временной переменной для описателя
P.TYPE1%=3; элемента массива
P.TYPE:=<инд>.ARR.TYPE; -занести тип1,адресс эл-та ST дляVARPART,
P.ADRESS:=<инд>.ENTRY2; адрес эл-та ST, содержащего имя массива
P.NUMBER:=<инд>.ARR.NUMBER;
Трансляция описаний массивов
1) В польской записи описание массива
ARRAY A [L1:U1,...Ln:Un] можно представить в виде
L1U1...LnUn A ADEC
2) Для тетрад в виде
BOUNDS L1,U1
...
BOUNDS Ln,Un
ADEC A
Операция ADEC выполняет при семантической обработке следу-
щие действия:
-заносит запись о каждом массиве в ST;
-выделяет для каждого массива две ячейки:одну для хранеия
адреса начала массива, другую - для хранения адреса допвектора;
-формирует в обьектной программе (при генерации кода) коман-
ды, обеспечивающие перед входом в блок:
-вычисление компонент допвектора;
-вычисление адреса хранения массива;
-вычисление адреса хранения допвектора;
-занесение этих адресов в соответствующие ячейки.
Для массивов с постоянными границами компоненты допвектора
вычисляются в ходе трансляции и помещаются среди констант. Чтобы
отличить переменные граничные пары от постоянных нужно ввести до-
полнительный анализ операндов ADEC, являющихся граничными парами.
Допвектора могут располагаться вслед за парой ячеек, выделенной
последнему массиву или среди констант(для массива с постоянными
границами.
ЛЕКЦИЯ 12
СТРУКТУРЫ ДАННЫХ И ОРГАНИЗАЦИЯ ПАМЯТИ
Некоторые применяемые языки требуют динамического распреде-
ления памяти; блоки оперативной памяти при этом выделяются произ-
вольно, а затем освобождаются. Область данных - это блок ОП, вы-
деленный для данных.
Области данных могут принадлежать также к статическому клас-
су. Статическая область данных имеет постоянное число ячеек, а
динамическая область данных не всегда присутствует во время счета.
Если вызов процедуры происходит рекурсивно, то существует
несколько областей данных в ОП, каждая для отдельного вызова про-
цедуры.
Если компилятор знает все характеристики переменных во вре-
мени, то он может сгенерировать полностью команды обращеиня к пе-
ременным, основываясь на этих характеристиках.
Память выделяется компилятором не только для переменных, но
и для описателей, содержащих атрибуты, определяемые во время сче-
та. Этот описатель заполняется и изменяется во время счета. Типы
данных исходной программы должны быть отображены на типы данных
машины. Целые переменные содержатся обычно в одном слове.
Информационные таблицы
При анализе программы из описаний, заголовков процедур, цик-
лов и т.д. извлекается информация и сохраняется для последующего
использования. Эта информация обнаруживается в отдельных точках
программы и организуется так, чтобы к ней можно было обратиться
из любой части компилятора. В каждом компиляторе в той или иной
форме используется таблица символов. Это таблица идентификаторов,
встречающихся в программе, вместе с их атрибутами.
При разборке компилятора невозможно определить вид и содер-
жание информации, которую следует собирать, до тех пор, пока не
будут достаточно обстоятельно продуманы команды обьектной прог-
раммы для каждой инструкции исходной программы и сама синтезирую-
щая часть компилятора.
При проверке правильности семантики и генерации кода тре-
буются знания характеристики идентификатора. Эти характеристики
выясняются из описания и накапливаются в таблице символов. Наип-
ростейшая таблица символов для каждого элемента имеет поле аргу-
мента и значения. Аргументами таблицы являются символы или иден-
тификаторы, а значениями - их характеристики. Так как число ли-
тер в идентификаторе непостоянно, в аргументе часто помещают сим-
волы вместо самого идентификатора. Это позволяет сохранить фикси-
рованный размер аргумента. Идентификаторы хранятся в специальном
списке строк.
При проходе исходной программы через компилятор при встрече
конструкции описания происходит запись идентификатора исходной
программы в таблицу символов вместе с его атрибутами. В результа-
те дальнейшего чтения исходной программы, в компиляторе при на-
хождении любого идентификатора программа обращается к таблице
символов и ищет в ней данный идентификатор. Если идентификатор не
обнаружен, то выдается сообщение, что данный идентификатор не оп-
ределен. Если же он обнаружен, то производится сравнение данного
идентификатора с записанным в таблице символов и производятся
необходимые преобразования.
При работе с таблицей символов нужно разработать правила ор-
ганизации и обращения к таблице символов. Таблицы символов могут
быть как упорядоченными, так и неупорядоченными.
При упорядоченном списке элементов наиболее результативным
является бинарный или логарифмический поиск. Иногда один и тот же
идентификатор может быть описан и использован много раз в различ-
ных блоках и процедурах, и каждое такое описание должно быть
единственным. Соответственно нужно разделять таблицу симводов.
При этом устанавливается правило нахождения соответствующего
идентификатора. Оно состоит в следующем: сначала просматривается
текущий блок, затем обьемлющий блок и т.д., до тех пор, пока не
будет найдено описание данного идентификатора.
При осуществлении поиска все элементы таблицы хранятся для
каждого блока в смежных ячейках и используется список блоков.
Информация об идентификаторе хранится в той части таблицы,
которую мы определили как "значение".
Таблица символов состоит из 5-ти различных списков:
- список меток;
- список арифметических констант;
- список имен общих блоков,имен подпрограмм и имен перемен-
ных;
- список общих блоков;
- список имен подпрограмм.
Элементы всех этих списков помещаются в одной и той же таб-
лице; первые два байта каждого элемента используются для ссылки
на следующий элемент в том же списке.
ЛЕКЦИЯ 13
ВНУТРЕННИЕ ФОРМЫ ИСХОДНОЙ ПРОГРАММЫ
Ввиду сложности реальных языков программирования и предъяв-
ления повышенных требований к эффективности самого процесса ком-
пиляции и к готовым программам, разработчики вынуждены проектиро-
вать многопроходные компиляторы. При этом для связи между прохо-
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40