Для более удобного выполнения
семантических проверок и генерации объектного кода используется ещё одна
промежуточная форма представления программы — последовательность пентад. Пентада
представляет собой машинную команду, состоящую из пяти полей: наименования
метки перехода, наименования кода операции, наименования двух операндов и
наименования результата. Удобство использования пентад для семантического
анализа состоит в том, что наименования всех необходимых для выполнения
проверок объектов программы локализованы в пределах одной пентады. Последовательность
пентад текущего блока формируется после получения постфиксной записи этого
блока. Рассмотрим подробно алгоритм формирования последовательности пентад:
- Создание переменной для
хранения текущей метки и сброс её значения. Запуск цикла для прохождения
по словам постфиксной записи данного блока. Установка первого слова в
качестве текущего.
- Текущее слово заносится в
стек и производится анализ его назначения.
- Если текущее слово – «let»,
происходит формирование пентады для операции присваивания. В пентаду
помещается текущая метка, знак операции («let»),
операнды (первый операнд берётся из стека, в качестве второго операнда
используется значение «null», так как второй операнд при этой операции не
используется), наименование результата также извлекается из стека.
Происходит сброс значения текущей метки.
- Если текущее слово является
знаком операции, происходит формирование пентады для текущей операции. В
пентаду помещается текущая метка, знак операции (извлекается из стека),
операнды (извлекаются из стека). После этого происходит формирование идентификатора
для промежуточного результата вычислений. Имя идентификатора получается в
результате конкатенации строки «tmpValue» и следующего номера
идентификатора в таблице. Созданный идентификатор помещается в
соответствующую таблицу, а также в пентаду в качестве результата. Происходит
сброс значения текущей метки.
- Если текущее слово является
меткой, а также является предпоследним или следующим слово тоже является
метка, то происходит формирование пентады для пустой метки. Все поля метки
кроме её наименования заполняются значениями «null».
- Если текущим слово является
метка, и предыдущее условие не выполнилось, то наименование данной метки
сохраняется в переменной для хранения текущей метки и происходит переход к
следующему шагу цикла.
- Если текущим словом
является служебное слово «JmpF», то происходит формирование пентады для
перехода по лжи. В пентаду помещаются: текущая метка, код операции («JmpF»), операнды (извлекаются из стека), в качестве результата
заносится значение «null». Происходит сброс значения текущей метки.
- Если текущим словом
является служебное слово «Jmp», то происходит формирование пентады для
перехода по истине. В пентаду помещаются: текущая метка, код операции («Jmp»),
первый операнд (извлекается из стека), в качестве второго операнда и результата
заносятся значения «null». Происходит сброс значения текущей метки.
- Переход к следующему шагу
цикла.
- После окончания цикла, сформированная
последовательность пентад заносится в вектор для хранения
последовательности пентад всей программы с индексом, соответствующим
индексу текущего блока.
- Происходит очистка вектора
для хранения последовательности пентад текущего блока и вектор для
хранения знаков операций, используемых в текущем блоке. Завершение
процедуры.
Для выполнения алгоритма определяются
следующие объекты:
final Vector VectPentadTotal
= new Vector(); //вектор для хранения последовательности пентад всей
//программы
final Vector VectPentadBlock
= new Vector(); //вектор для хранения последовательности пентад
//программного кода текущего блока
final Vector VectPentadString
= new Vector(); //вектор для хранения последовательности пентад
//текущего выражения