Россия, Челябинск, Южно-Уральский Государственный Университет (НИУ) |
Семантический анализ. Внутреннее представление
Структура таблиц
Наша задача - разработать такую структуру таблицы идентификаторов, чтобы минимизировать поиск в ней. При этом следует помнить о том, что каждый идентификатор мы заносим в таблицу представлений, поэтому желательно иметь прямой доступ из таблицы представлений в таблицу идентификаторов для каждого идентификатора. Добавим к элементу таблицы представлений поле, которое будет содержать ссылку в таблицу идентификаторов, если находящаяся в этом элементе сущность является идентификатором. Элемент таблицы идентификаторов организуем так:
struct IdItem { ReprInd toRepr; /* ссылка в ReprTab на представление */ TypeInd toMode; /* тип идентификатора */ IdInd toId; /* ссылка на элемент таблицы идентификаторов с таким же значением поля toRepr */ }
Расширим структуру таблицы внешних представлений следующим образом:
struct ReprItem { HashInd toHash; /* значение hash-функции для лексемы */ unsigned short LexClass; /* лексический класс */ unsigned short LexMark; /* лексическая марка */ IdInd toId; /*ссылка в IdTab на доступное определение идентификатора */ }
Перейдем к формулировке алгоритма идентификации, который состоит из двух частей:
- первая часть алгоритма обрабатывает определяющие вхождения идентификаторов
- вторая часть алгоритма обрабатывает использующие вхождения идентификаторов
Обработка определяющего вхождения идентификатора
Обработка определяющего вхождения идентификатора происходит на фазе синтаксического анализа. Пусть лексический анализатор обработал очередную лексему, которая оказалась идентификатором. Лексический анализатор сформировал структуру типа LEXEME, которая содержит атрибуты выделенной лексемы, такие как ссылка в таблицу внешних представлений, лексический класс и лексическая марка. Далее вся эта информация передается синтаксическому анализатору. Предположим, что в данный момент синтаксический анализатор обрабатывает определяющее вхождение идентификатора. Таким образом, он знает ссылку в таблицу внешних представлений на обрабатываемый идентификатор и тип идентификатора. Основное семантическое действие, которое должен выполнить анализатор, заключается в занесении информации об идентификаторе в таблицу идентификаторов. Это происходит следующим образом:
- Создаем новый элемент таблицы идентификаторов
- В поле toRepr таблицы идентификаторов помещаем rpr .
- Поле toId элемента таблицы представлений помещаем в поле toId нового элемента таблицы идентификаторов. В поле toId элемента таблицы представлений помещаем ссылку на новый элемент таблицы идентификаторов
Отметим, что такая организация таблицы идентификаторов почти полностью исключает поиск в этой таблице, поскольку в нужный элемент таблицы мы попадаем по прямой ссылке из таблицы представлений.
Теперь обсудим обработку использующего вхождения идентификатора, которая происходит на фазе идентификации идентификаторов. Предположим, что уже построена (полностью или частично) таблица идентификаторов. Пусть лексический анализатор обработал очередную лексему, которая оказалась идентификатором. Лексический анализатор сформировал структуру типа LEXEME , которая содержит атрибуты выделенной лексемы, такие как ссылка в таблицу внешних представлений, лексический класс и лексическая марка. Далее вся эта информация передается фазе идентификации идентификаторов. Таким образом, эта фаза знает, что она обрабатывает использующее вхождение идентификатора, причем ей известна помимо прочего ссылка в таблицу внешних представлений на обрабатываемый идентификатор. Теперь для того, чтобы получить информацию о типе идентификатора нам достаточно просто взять ее из того элемента таблицы идентификаторов, на который указывает поле toId текущего элемента таблицы представлений.
Пример
Рассмотрим программу следующей структуры:
{int n; …; n++; .. {float n; … n = 3.14; … } …n--; … }
При входе во внешний блок идентификатор n будет занесен в таблицу представлений, кроме того, будет создан элемент таблицы идентификаторов.
После входа во внутренний блок будет добавлен еще один элемент в таблицу идентификаторов, соответствующий идентификатору n .
После выхода из внутреннего блока таблицы будут выглядеть следующим образом.