Повторное использование таблицы символов из фазы семантического анализа для генерации кода
В настоящее время я создаю компилятор для языка, который имеет глобальную переменную и функцию вложенных подпрограмм. Раньше я только когда-либо создавал компилятор для языков, в котором есть только локальная переменная без вложенной подпрограммы.
У меня проблема с тем, как повторно использовать таблицу символов, заполненную на этапе семантического анализа на этапе генерации кода. Я делаю таблицу символов как стек связанного списка, где каждый связанный список представляет идентификаторы, объявленные в определенной области видимости. Каждый раз, когда он входит в область действия, создается новый список и помещается в стек, и он становится текущей областью действия. Аналогично, каждый раз, когда он покидает область видимости, список на вершине стека выталкивается. В конце концов, после того, как семантический анализ закончится, у меня практически будет пустая таблица символов, как и при ее запуске. Однако для правильной генерации кода генератору кода требуется полностью заполненная таблица символов. Как это можно сделать без повторного выполнения того, что было сделано во время семантического анализа (т.е. ввода идентификаторов в таблицу символов)?
2 ответа
Это будет немного абстрактно - как ваш вопрос - поскольку я не знаю ничего конкретного о внутренних структурах данных вашего компилятора.
Когда вы выдвигаете свою область вместо того, чтобы удалить ее, как я полагаю, вы делаете это сейчас, назначьте указатель на данные области для элемента данных, на котором вы основываете код для этой области видимости, чтобы генератор кода мог получить к нему доступ.,
Вы должны решить, какой контекст будет сохранять ваш компилятор для поддержки оптимизации и генерации кода.
Вы можете создать генератор кода "на лету", который выбрасывает информацию таблицы символов при выходе из области, если он сгенерировал весь код (или IR), который он собирается сгенерировать для этой области. Это может работать, если вы создаете быстрый и грязный компилятор, и это полезно, когда на вашем компьютере недостаточно памяти. (На современных ПК вы не можете сделать последний аргумент).
Если вы не будете выполнять анализ / оптимизацию кода /IR или генерацию кода до тех пор, пока не достигнете конца процесса синтаксического анализа, вам придется дольше держаться за информацию о таблицах символов для каждой области. В этом случае вы обнаружите, что вам тоже придется зависать на AST, или вам нечем будет генерировать код. (На современных ПК это не проблема).
Чтобы создать компилятор с простой архитектурой, вы, возможно, захотите в любом случае изолировать парсинг, семантический анализ и генерацию кода. В этом случае ваш анализатор запускается и просто создает AST; не беспокойтесь о создании таблицы символов. Пройдите два обхода дерева и создайте таблицы символов, которые соответствуют частям AST, и сохраните эту связь; теперь у вас есть AST и связанные таблицы символов. Проход 3 теперь может проходить AST и использовать информацию о символах для генерации и IR. Pass 4 оптимизирует ИК; он все еще может ссылаться на записи таблицы символов, украшенные информацией о типе и возможными назначениями мест хранения. После этого вы можете выполнить оптимизацию и финальную генерацию кода.
Главное в этом - не выбрасывать таблицы символов. Сохраните их и свяжите с теми структурами кода, которые необходимы для генерации кода. У вас много памяти, чтобы сохранить их.