А.В. Ахо, М.С. Лам, Р. Сети, Дж. Д. Ульман - Компиляторы - принципы, технологии и инструментарий (1114947), страница 25
Текст из файла (страница 25)
Псевдоюд на рис. 2.30 считывает цифры целого числа и накапливает его значение в переменной о. И(реей содержит цифру ) ( и=0; по ( о = о *10+ целочисленное значение цифры рве/с, рее1г = следующий входной символ; ) ттЫ)е ( реей содержит цифру ); гетпгп 1о1сеп (пшп, и); Рис. 2.30. Группированне цифр а целые числа 2.6.4 Распознавание ключевых слов и идентификаторов Большинство языков программирования используют фиксированные символьные строки, такие как аког, с)о и хх, в качестве знаков препинания или для идентификации конструкций.
Такие символьные строки называются ключевыми словами. 122 Глава 2. Простой синтаксически управляемый транслятор Символьные строки могут также использоваться в качестве идентификаторов для имен переменных, массивов, функций и т.п. Грамматики обычно трактуют идентификаторы как терминалы для упрощения синтаксического анализатора, который может ожидать один и тот же терминал, скажем,!и, всякий раз, когда во входном потоке оказывается идентификатор.
Например, при входной строке (2.6) социо = соцпг + зпсгевепг; синтаксический анализатор работает с потоком терминалов Ы = Ы + Ы. Токен Ы имеет атрибут, храняший лексему. Записывая токены в виде кортежей, мы получим для входного потока (2.6) токены (Ы,"соцпг")(=) (Ы,"соцпг")(+) (Ы,"зпсгевзепг")(;) Ключевые слова обычно удовлетворяют правилам, по которым формируются идентификаторы, так что необходим механизм, который принимал бы решения, когда лексема образует ключевое слово, а когда — идентификатор. Задача решается существенно легче, если ключевые слова являются зарезервированными, т.е.
если они не могут использоваться в качестве идентификаторов. Тогда символьная строка образует идентификатор только в том случае, если она не является ключевым словом. Лексический анализатор из этого раздела использует таблицу для хранения символьных строк для решения двух задач. ° Единственность предппавления. Таблица строк может отделить остальную часть компилятора от представления строк, поскольку фазы компилятора могут работать со ссылками или указателями на строки таблицы. Работа со ссылками может также оказаться более эффективной, чем работа непосредственно со строками. в Зарезервированные слова. Зарезервированные слова могут быть реализованы путем инициализации таблицы зарезервированными строками и их токенами. Когда лексический анализатор считывает строку или лексему, которая может образовывать идентификатор, он сначала проверяет, нет ли такой лексемы в таблице строк.
Если она имеется в таблице, то лексический анализатор возврашает соответствуюший токен из таблицы; если нет — возврашается токен с терминалом Ы. В 1ана таблица строк может быть реализована как хеш-таблица с использованием класса НазЫаЫе. Объявление НазЫаЫе и оий = петя НазИаЫе(); 12З 2.6. Лексический анализ пиг ( рее/с содержит букву ) ( Собираем буквы или цифры в буфер Ь; к = строка, образованная символами в /э; и = токен, возвращенный вызовом иогс/х.ее/(х); И ( и не равно ппн ) гетпгп и; еие ( Внести пару "ключ-значение" ра(т (еч (Ы, а)) в и огс/з гегпгп со(сеп (Ы, е); Рис. 2.3!.
Различение ключевых слов и идентификаторов делает и огс/х хеш-таблицей по умолчанию, которая отображает ключи на значения. Мы используем ее для отображения лексем на токены. Псевдокод на рис. 2.31 использует операцию де/ для поиска зарезервированных слов. Приведенный псевдокод собирает из букв и цифр входного потока строку а, начинающуюся с буквы. Предполагается, что строка а должна быть максимально возможной длины, т.е. лексический анализатор продолжает чтение входного потока до тех пор, пока из него считываются буквы и цифры.
Когда из входного потока считывается некоторый другой символ, например пробельный, лексема копируется в буфер б. Если в таблице имеется запись для еч то возвращается токен, полученный вызовом и огс/аде/. В этом случае строка е может представлять собой либо ключевое слово из тех, которые были изначально помещены в таблицу и огс/еч либо идентификатор, ранее внесенный в таблицу. В противном случае токен Ы с атрибутом а вносится в таблицу и возвращается лексическим анализатором. 2.6.5 Лексический анализатор Фрагменты псевдокодов из всего раздела можно обьединить в одну функцию хсал, которая возвращает объекты токенов, следующим образом; Точен зсоп() ( Пропуск пробельных символов (раздел 2.6.1); Обработка чисел (раздел 2.6.3); Обработка зарезервированных слов и идентификаторов (раздел 2.6.4); /* Если мы достигли этого места, рассматриваем считанный символ рее/с как токен */ То/сел с = пеи' То/сел(рее/с); реей = пробел /* Инициализация (раздел 2.6.2) */; гетпгп /; 124 Глава 2.
Простой синтаксически управляемый транслятор В оставшейся части этого раздела функция зсап реализована как часть 1атапакета для лексического анализа. Этот пакет под названием 1ехег содержит классы для токенов и класс 1 ехег, содержащий функцию зсап. Классы для токенов н их поля проиллюстрированы на рис. 2.32; методы классов на рисунке не показаны.
Класс То)сеп имеет поле сад, которое используется для принятия решений в процессе анализа. Подкласс 1зпш добавляет поле зга1ие для целого значения. Подкласс Хогг( добавляет поле 1ехезпе, которое используется для зарезервированных слов и идентификаторов. с1а~з ТЫез 1з! е ~~пз зайе с!ззз Ими зшзя тхете Рис. 2.32. Класс То(сел и подклассы Хшп и %огс( Каждый класс находится в собственном файле. Файл для класса То)сеп имеет следующий вид: // Файл То/сеп,уапа 1) рас)саде 1ехег; 2) рцЬ11с с1авв То)сеп ( 3) риЬ11с Т1па1 1пс саде 4) рпЬ11с То)сеп(йпс с) ( сад = Ь; 5) Строка 1 идентифицирует пакет 1ехег.
Поле сад в строке 3 обьявлено как ТТпа1, так что, будучи установленным, оно не может быть изменено, Конструк- тор То)сеп в строке 4 используется для создания объекта токена. Так, пен То1сеп ( '+ ' ) создает новый объект класса То)сеп и устанавливает его поле Шес( равным целочисленному представлению '+'.
(Для краткости мы опускаем обычный метод соЯсгйпд, который должен вернуть строку для вывода на печать.) Там, где в псевдокоде встречаются терминалы наподобие пшп и И, код на языке программирования 1ата использует целые константы. Класс Тад реализует эти константы следующим образом: 1) рас)саде 1ехег; 2) риЬ11с с1авв Тад ( 3) риЬ11с ТТпа1 всасйс Тпс 4) БОМ = 256, 10 = 257, ТВОЕ = 258, сА1ЯЕ = 259г 5) ) // Файл Таял/ага 125 2.6. Лексический анализ В дополнение к целочисленным полям И()М и 1() этот класс определяет два дополнительных поля ТЕПЕ и ГА1 ЯЕ для будущего использования; они будут использованы для иллюстрации работы с ключевыми словами." Поля в классе Тад объявлены как рцЬ11с, т.е. они могут использоваться н вне пакета.
Они имеют спецификатор зсасфс, так что существует только один экземпляр каждого из этих полей. И наконец, они объявлены как Тфпа1, т,е. они могут быть установлены только один раз. В сущности, эти поля являются константами. В С аналогичный эффект достигается при помощи определения макроса ИУМ как символьной константы, например ()с(еТ1пе И()М 256 Код на языке программирования )ача обращается к Тад . И()М и Тад . 1() там, где псевдокод использует терминалы пил и Ы.
Единственное требование заключается в том, что Тад. ИБМ и Тад. 1)3 должны быть инициализированы различными значениями, отличающимися друг от друга и от констант, представляющих односимвольные токены, такие как ' + ' и ' * '. !) рас)саде 1ехег; // Файл Мит./ача 2) риЬ11с с1азя Нцв ехГепс(з То)сеп ( 3) риЬ11с Тфпа1 Тпс ча1це; 4) рпЪ11с Ыцв(фпс и) ( запрег(Тад.БОМ)т ча1ие = ч; 5) 1) рас)саде 1ехег; // Файл Иопт'./ача 2) рцЬ11с с1азя Иогс( ехсепс(з То)сеп ( 3) рпЬ11с ТТпа1 Ясгфпд 1ехеве; 4) рцЬ11с Иогс((фпГ Г, ЯГгфпд я) ( 5) зирег(с)з 1ехеве = пеы Ясг1пд(я); 6) ) 7) ) Рис. 2.33. Подклассы Хпв и Чз'отд класса Тоиеп На рис. 2.33 показаны классы Жив и Иогс1 Класс Иив расширяет класс Тойеп путем объявления целочисленного поля ча1це в строке 3.
Конструктор Ицв в строке 4 делает вызов яцрег(Тад. ИПМ), который устанавливает поле сад в суперклассе То1сеп равным Тад. ИПМ. Класс Иогс( используется и для зарезервированных слов, и для идентификаторов, так что конструктор Иогс) в строке 4 получает два параметра: лексему "Обычно АБС[1-символы преобразуются я целые числа от О до 255. Поэтому для терминалов мы используем целые числя„преяышяющие 255.
126 Глава 2. Простой синтаксически управляемый транслятор и соответствующее целочисленное значение для гад. Обьект для зарезервиро- ванного слова сгие может быть создан путем выполнения кода пеи (яогс)(Тад.сгие, "сгие") Он создает новый объект с полем гад, установленным равным Тад. ггие, и полем 1ехесае, равным строке "ггие". 1) рас)саде 1ехег; // Файл Аехег/ага 2) 1врогГ 3ача.йо.*; ыпрогГ 3ача.иГ11.*; 3) рцЬ11с с1азя )ехег 4) рцЬ11с ТпГ 11пе = 1; 5) ргфчаГе сЬаг рее)с = 6) ргфчасе Наз)зсаЬ1е иогс(я = пем НавпгаЬ1е(); 7) чо1с( гевегче(Хогс) с) ( иогс(в.рис(г.1ехесае, с); 8) рцЬ11с Еехег() ( 9) гевегче( пем Хогс((Тад.ТН(ЛЕ, "сгие") ); 10) гевегче( пеи Хогс)(Тад.ЕА1 ЯЕ, "Ра1ве") ); 1!) 12) 13) 14) 15) 16) 17) риЬ11с То)сеп всап() сЬгомз 10Ехсерсфоп аког( ; ; рее)с = (с)заг)Яувсеаз.фп.геас)() ) ( Тй( рее)с == ' ' !! рее)с == '~М' ) сопГТпие е1зе Н( рее)с == '~п' ) 11пе = 11пе + 1; е1ве Ьгеа1с; ) /* Продолжение на рис.