Каким образом таблица символов управляется в компиляторе

Интересно, есть ли только одна таблица символов, в которой хранится вся информация об исходном файле, или есть несколько таблиц символов, которые накладываются друг на друга и выбираются только тогда, когда текущая область видимости связана с таблицей.

Например, скажем, у меня есть два метода

int foo(int a){
    int b;

    bar(b);
    ...
}

double bar (int a){
   int b;
   ...
}

здесь a и b в двух не имеют одинаковой области видимости, поэтому, если таблица символов сложена, таблица символов, связанная с foo, выбирается первой при выполнении foo. Однако при выполнении bar таблица символов bar накладывается на foo, так что текущая таблица символов содержит информацию для bar a и b.

если таблица символов централизована, информация foo и информация bar находятся в одной таблице символов, но могут быть записи, в которых a, b в foo принадлежит области foo, а a, b в bar принадлежит bar. Нет другой таблицы символов, на которую можно было бы ссылаться

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

Спасибо


person Daniel    schedule 05.01.2014    source источник
comment
Думаю, это зависит от реализуемого языка. Например, в C вызовы функций не приводят к таким вложенным областям действия.   -  person Oliver Charlesworth    schedule 05.01.2014
comment
так что в c есть одна центральная таблица?   -  person Daniel    schedule 05.01.2014
comment
Что ж, это зависит от компилятора. Язык не требует конкретной реализации компилятора.   -  person Oliver Charlesworth    schedule 05.01.2014
comment
эм, есть ли какой-нибудь компилятор с открытым исходным кодом мини-размера, для которого я мог бы взглянуть на его реализацию?   -  person Daniel    schedule 05.01.2014
comment
Компилятор Google mini C.   -  person NPE    schedule 05.01.2014


Ответы (1)


Вам необходимо сопоставление идентификаторов типу / значению для каждого экземпляра области, найденного в исходном коде, в соответствии с определением языка. Некоторые люди назвали бы одно такое отдельное отображение «таблицей символов», но я думаю, что это злоупотребление этим термином; Я предпочитаю термин «пространство символов» для таких отдельных карт видимости. Для меня набор отображений областей видимости - это таблица символов.

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

Для классических языков, подобных Паскалю, области видимости могут быть вложены таким образом, чтобы соответствовать синтаксису вложенности программ («лексическая область видимости»). Для таких языков можно создавать пространства символов в виде стека, обрабатывая программу сверху вниз (от наименьшего номера строки до наибольшего номера строки). Когда встречается каждая новая граница области видимости, новое пространство символов помещается в стек. Поиск идентификатора происходит путем поиска в текущем пространстве символов (том, что находится наверху стека), и, если идентификатор не найден, поиск в пространствах символов дальше вниз по стеку. При выходе из области действия это пространство символов может быть удалено (например, вытеснено). Эта схема работает только в том случае, если компилятор обрабатывает программу за один проход. Иногда вы хотите сохранить все пространства символов, чтобы разрешить сложную обработку программы за несколько проходов; в этом случае вы можете создать пробелы символов в том виде, в каком они встречаются, но не можете их удалить.

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

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

Схема на самом деле немного умнее; с каждым пространством символов связана последовательность родительских связей пространства символов; стандартный лексический поиск обращается к родителям (рекурсивно), когда символ не найден в текущей области. При наличии только одной родительской ссылки это то же самое, что и лексическая область видимости. С несколькими родительскими ссылками он прекрасно обрабатывает множественное наследование. Пространства имен обрабатываются с использованием «хорошо известного» пространства символов верхнего уровня, которое содержит символы для пространств имен верхнего уровня и т. Д. Вы можете увидеть, как это выглядит для C ++, в этом ответе SO: https://stackoverflow.com/a/32012786/120163

Пользовательское действие («процедурное вложение») вызывается перед посещением ссылок лексической области видимости; это позволяет действию решить сначала посетить произвольные другие пространства символов. В частности, это позволяет поиску в пространстве символов для Java извлекать исходные файлы / файлы классов из файловой системы, извлекать их символы, а затем продолжать поиск по мере необходимости.

person Ira Baxter    schedule 05.01.2014