Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория языков программирования и методы трансляции..pdf
Скачиваний:
28
Добавлен:
05.02.2023
Размер:
3.41 Mб
Скачать

236

8.3.6 ПРИКЛАДНЫЕ РЕАЛИЗАЦИИ

Во время компиляции в соответствии с прикладной реализацией иден-

тификатора, например x в x + 4, необходимо:

1)найти в таблице символов запись, соответствующую определяющей реализации (int x) идентификатора;

2)поместить в нижний стек статические характеристики, соответству-

ющие идентификатору.

Подразумевается, что в нижний стек также помещаются статические характеристики констант и т.д.

8.4 ПРОБЛЕМЫ, СВЯЗАННЫЕ С ТИПАМИ

Основной проблемой для трансляторов с языков высокого уровня явля-

ется приведение (автоматическое изменение) типов. Здесь можно выделить,

как минимум, шесть задач [2]:

1)Распроцедуривание, например переход от procedure real к real.

2)Разыменование, например переход от pointer real к real.

3)Объединение, например переход от real к struct(real, char).

4)Векторизация, например переход от real к real [ ].

5)Обобщение, например переход от int к real.

6)Чистка, например переход от real к void.

Возможность осуществления приведения зависит от синтаксической позиции. Например, в левой части присвоения может иметь место только распроцедуривание (вызов процедур без параметров), а в правой части – лю-

бое из шести приведений. Иногда возникает необходимость нескольких при-

ведений. Например, если x имеет вид pointer real и a pointer int, то прежде чем производить присвоение x := a, необходимо сначала разыменовать, а за-

тем обобщить.

237

В зависимости от того, какие приведения могут выполняться в синтак-

сических позициях, последние называются мягкими, слабыми, раскрытыми,

крепкими и сильными. Например, левая часть присвоения называется мягкой

(допускает только распроцедуривание), а правая часть – сильной (допускает любое приведение). Кроме ограничений типов приведений, разрешаемых в заданной синтаксической позиции, существуют правила, определяющие по-

рядок осуществления различных приведений. Например, объединение может произойти только один раз и не должно следовать за векторизацией. Можно определить грамматику, которая генерирует все допустимые последователь-

ности приведений в заданной синтаксической позиции, например:

SOFT deprocedure | deprocedure SOFT

Любое предложение, генерированное посредством SOFT, представляет собой допустимую последовательность приведений в мягкой синтаксической позиции (т.е. в левой части присвоения).

Для раскрытия позиции (например, индекса в a[i]) справедливы следу-

ющие правила:

MEEK deprocedure | deprocedure MEEK | dereference | dereference MEEK

Другими словами, в раскрытой позиции можно выполнять распроцедуривание и разыменование любое число раз и в любом порядке,

например pointer procedure poiter int в вид int.

Для сильной позиции (например, правая часть присвоения или пара-

метр в вызове процедуры) правила таковы:

STRONG dereference STRONG | deprocedure STRONG |

238

unit |

unit ROW | widen | widen widen | widen ROW |

widen widen ROW | ROW

ROW row | row ROW

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Вид данных до выполнения приведений называется априор-

ным, а после выполнения – апостериорным.

·· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Вслучае сильных и раскрытых синтаксических позиций известны и априорный, и апостериорный виды. Для других позиций известен лишь априорный вид и некоторая информация об апостериорном виде, например о том, что он должен начинаться со struct или pointer struct, или о том, что он не должен начинаться с proc, как в левой части присвоения.

Компилятор, применяя соответствующую грамматику, генерирует по-

следовательность приведений из априорного вида к известному либо подхо-

дящему апостериорному виду. Если нельзя найти никакой последовательно-

сти приведений, программа синтаксически неправильная.

С другой стороны, если подходящая последовательность существует,

компилятор, применяя приведения по порядку, генерирует код времени про-

гона.

Еще один вид приведения – чистка. Чистка представляет собой особую форму приведения и происходит в тех местах, где стоит точка с запятой:

x := y;

239

Еще одна сложность связана с выбирающим предложением. В предло-

жении

x + if b then 1 else 2.3

во время компиляции необходимо знать тип (вид) правого операнда знака

«+». Все варианты выбирающего предложения должны приводить к общему виду, называемому объектным. Этот процесс называется уравнением, и его правила подразумевают, что последовательность сильных приведений можно применять во всех вариантах, кроме одного, в котором используется лишь последовательность приведений, уместных лишь для синтаксической пози-

ции выбирающего предложения. В вышеприведенном примере выбирающее предложение находится в крепкой синтаксической позиции, которая не до-

пускает расширения. Однако внутри выбирающего предложения один вари-

ант допускает сильное приведение, что может повлечь за собой расширение.

В этом случае объектным видом окажется real, и первый вариант следует расширить, а второй нежелательно подвергать приведению.

Действия компилятора при обращении с выбирающими предложения-

ми заключаются в том, что статические характеристики всех вариантов вы-

бирающего предложения помещаются в нижний стек, а затем выводятся объ-

ектный вид и различные последовательности приведения для каждого вари-

анта. Если какая-либо последовательность вызывает необходимость генера-

ции кода во время прогона, ее можно выделить в отдельный поток, и между двумя этими потоками ввести указатели, чтобы во время следующего прохо-

да код можно было соединить в нужном порядке.

8.5 ВРЕМЯ КОМПИЛЯЦИИ И ВРЕМЯ ПРОГОНА

Как отмечалось ранее, генератор кода во время компиляции обращает-

ся к нижнему стеку и генерирует код операций, которые будут выполняться во время прогона. Что именно должно быть сделано во время компиляции, а

что во время прогона, существенно зависит от языка программирования [2].

240

Тем не менее, разработчик компилятора имеет возможность разделять функ-

ции компиляции и прогона. Например, не вполне ясно, повлечет ли разыме-

нование за собой какие-либо действия при прогоне или нет. На первый взгляд может показаться, что нет, так как это просто замена в памяти одного значения другим и изменение адреса времени прогона. Новым адресом будет тот, на который указывает первоначальный адрес. Однако значение указателя может быть неизвестным при компиляции, новый адрес можно обозначить,

изменив первоначальный адрес так, чтобы в нем указывался дополнительный косвенный уровень. То есть в некоторых случаях требуется выполнить дей-

ствие (переслать значение по новому адресу).

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Для повышения эффективности выдаваемого кода при компиляции можно проделать дополнительную работу, которую называют оптимизацией.

·· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Воптимизацию входит удаление кодов из циклов там, где это не влияет на значение программы, исключение возможности вычисления идентичных выражений более одного раза и т.д. Особое внимание уделяется возможности избежать перезаписи сложных структур данных во время прогона.

· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

Контрольные вопросы по главе 8

·· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·

1.Технология создания промежуточного кода. Виды промежуточного кода.

2.Алгоритм преобразования арифметического выражения в префикс-

ную и постфиксную формы.

3.Формализация записи промежуточного кода.

4.Структуры данных для генерации промежуточного кода.

241

5.Алгоритм генерации промежуточного кода для арифметических вы-

ражений.

6.Таблица блоков, ее назначение.

7.Генерация кода для присвоения.

8.Генерация кода для условных зависимостей.

9.Генерация кода для описания идентификаторов.

10.Генерация кода для циклов.

11.Генерация кода для входа и выхода из блока.

12.Генерация кода для прикладной реализации.

13.Проблемы генерации кода, связанные с типами.

14.Работа генератора кода во время компиляции и во время прогона.