И.А. Волкова, И.Г. Головин, Л.Е. Карпов - Системы программирования, страница 9
Описание файла
PDF-файл из архива "И.А. Волкова, И.Г. Головин, Л.Е. Карпов - Системы программирования", который расположен в категории "". Всё это находится в предмете "практика расчётов на пэвм" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 9 страницы из PDF
Вторая задача лексического анализатора естьвыполнение действий, связанных с обнаружением и распознаванием той или инойлексемы. Фактически ее решение приводит к тому, что с конечным автоматом,лежащим в основе лексического анализатора, ассоциируют не только входной язык, нои выходной. Автомат должен не только распознать правильную лексему на входе, но ипородить связанную с ней последовательность символов на выходе. Тем самым,конечный автомат превращается в конечный преобразователь. Однако лексическийанализатор не может действовать, как простой преобразователь, его задача шире, чемтолько порождение цепочки символов выходного языка. Он должен уметь выполнятьтакие действия, как запись выделенной лексемы в таблицу лексем, поиск ее в таблице32идентификаторов или в таблице констант, а также запись нового имени или новойконстанты в соответствующую таблицу.
Часто подобные действия выполняютсянепосредственно при обнаружении лексемы в исходном тексте.Выбирая тот или иной способ представления таблиц в программах компилятора,следует руководствоваться следующими требованиями к ним:•••Структура таблиц должна обеспечивать эффективность поиска в таблицах;Структура таблиц должна обеспечивать эффективность вставок в таблицы(имеются в виду, как вставки новых элементов, так и вставки новойинформации в ранее имевшиеся записи);Структура таблиц должна обеспечивать возможность динамического ростаобъемов таблиц.Влияет на программу реального лексического анализатора и необходимостьотслеживать возможные ошибки в тексте исходных программ.
Анализатор долженпринимать меры для максимально более полной локализации ошибок, причем нетолько лексических, но также и синтаксических и семантических.3.3.2. Задачи семантического анализаСемантический анализ пользуется всеми результатами предыдущих стадийкомпиляции. Со стороны лексического анализатора ему передаются все созданныетаблицы (идентификаторов, констант и т. д.), а со стороны синтаксическогоанализатора – результаты синтаксического разбора конструкций языка. Эти результатыпредставляются на выходе синтаксического анализатора в одной из форм внутреннегопредставления программ в компиляторе.
Обычно на этапе семантического анализаиспользуются некоторые варианты синтаксических деревьев, построенных в результатесинтаксического разбора. Такое древовидное представление программы удобно дляпроведения семантического анализа потому, что для анализа семантикикомпилируемой программы важно знать именно общую структуру этой программы.Семантический анализ в свою очередь тоже может разделяться на отдельныестадии. Одна из них вполне может совмещаться с синтаксическим анализом ипроводится параллельно с ним. Другая стадия выполняется позднее, когда завершенсинтаксический анализ последней конструкции программы и начинается подготовка кгенерации объектной программы.
Первая часть выполняется после завершениясинтаксического анализа очередной конструкции входного языка (процедуры,функции, блока операторов и т. п.) на основе имеющихся в информационных таблицахданных. Вторая часть связана с проведением полного семантического анализа всейпрограммы.Независимо от выбранного способа реализации основная работа семантическогоанализатора связана•••с проверкой соблюдения во входной программе семантических соглашений иконтекстных условий входного языка,с включением во внутреннее представление компилируемой программыдополнительных операторов, связанных с семантикой входного языка,с проверкой семантических (смысловых) норм языка, напрямую несвязанных с входным языком и его синтаксисом.33Проверки,выполняемыесемантическиманализатором,называютсястатическими проверками.
Они отличаются от динамических проверок, выполняемых впроцессе работы программы.3.3.2.1. Проверка контекстных условийПо виду (синтаксической записи) большинства операторов нельзя утверждать ихсемантическую правильность или ошибочность. Проверка семантических соглашений иконтекстных условий заключается в сопоставлении входных цепочек исходнойпрограммы с требованиями семантики языка программирования.
Такие соглашенияесть в каждом языке, проверять их на этапе синтаксического анализа невозможно.Обычными видами статических проверок в компиляторах являются1. Проверки типов. Компилятор обязан сообщить об ошибке, если в программепредписано выполнить некоторую операцию с несовместимым с нейоперандом, например, произвести сложение указателей.2. Проверки управления.
Передача управления за пределы синтаксическихконструкций должна производиться только в разрешенные места программы.Например, в языках Си и Си++ оператор выхода из цикла break можетвстречаться только внутри операторов цикла или перебора. Любое другое егоупотребление должно приводить к сообщению об ошибке.3. Проверки единственности. В определенных ситуациях объект можетупотребляться только один раз. Например, во многих языкахпрограммирования, где есть оператор перебора, все метки в конструкцияхописания альтернатив case одного оператора должны быть уникальными,элементы в перечислениях enum также не должны повторяться.4. Проверки, связанные с именами. Иногда одно и то же имя должноиспользоваться дважды или большее число раз.
Компилятор долженпроверять, что во всех местах использовано одинаковое имя. Например, вязыке Ада процедура блок или цикл может иметь имя, которое должнонаходиться и в начале, и в конце синтаксической конструкции.К типичным для многих языков контекстным условиям относятся такиесемантические ограничения:••••••каждое имя, используемое в программе, должно быть описано, причемтолько один раз;в операторе присваивания типы переменной и выражения должны совпадать(либо относиться к некоторым семантически близким типам);в условном операторе и в операторе цикла в качестве условия возможнотолько логическое выражение;операнды операций отношения должны быть целочисленными (либо иметькакие-либо другие, но точно известные типы);тип выражения и совместимость типов операндов в выраженииопределяются по фиксированным для данного языка правилам; старшинствоопераций обычно задано синтаксическими правилами;каждая метка, на которую есть ссылка или переход, должна один разприсутствовать в программе (несколько вхождений одной метки легкопроверяются во время анализа синтаксиса);34•••единственность описаний идентификаторов рассматривается с учетомблочной структуры программы;при вызове функции число фактических параметров и их типы должнысоответствовать числу и типам формальных параметров;обычно в языке накладываются ограничения на типы операндов каждойоперации, определенной в этом языке; на типы левой и правой частей воператоре присваивания; на тип параметра цикла; на тип условия воператорах цикла и условном операторе и т.
п.Конкретный состав подобных требований жестко связан с семантикойкомпилируемогоязыка.Например,требованиеобязательногоописанияидентификаторов в некоторых языках отсутствует. Некоторые языки допускаютавтоматическое преобразование типов несогласованных операндов выражений. Иногдав вызовах процедур и функций допускается указывать не все фактические параметры,остальные параметры получают значения по умолчанию.Семантический анализатор должен фиксировать все случаи нарушениясемантических соглашений и условий, найденные им в программе, и выдаватьсообщения о семантических ошибках в программе.3.3.2.2. Дополнение внутреннего представленияМногие языки запрещают смешивать в выражениях операнды даже “близких”типов, например, использовать рядом операнды вещественных и целочисленных типов,знаковых и беззнаковых типов и т. д.
Однако большинство реальных языковпрограммирования допускает некоторые вольности при записи выражений, гарантируя,что в компиляторах будут предприняты меры по согласованию типов. Абсолютноаналогичная работа выполняется при обработке операций обращения к функциям ипроцедурам с параметрами.Задача семантического анализатора состоит в поиске всех мест, где нужновыполнить подобные преобразования типов и вставить во внутреннее представлениеявные команды преобразования.
Иногда эти преобразования тривиальны и состоят изодной-двух команд, а иногда они выполняются встроенными библиотечнымифункциями.Преобразования типов могут производиться не только по отношению к простымарифметическим данным. Во многих языках существуют данные, позволяющиессылаться на другие данные – указатели и ссылки.
Иногда операция доступа к даннымпо указателю приводит к введению в программу целой серии команд по настройкевнутренних регистров, выделению фрагментов данных, размеры которых не кратныцелому числу машинных слов или байтов и т. д.Все это означает, что действия, выполняемые при семантическом анализекомпилируемой программы, существенным образом влияют на порождаемыекомпилятором объектные программы.3.3.2.3. Проверка правил программированияМногие современные компиляторы не только проверяют ограничения итребования, выставляемые семантикой языка, но также выполняют дополнительныепроверки, способствуя выработке “правильного” стиля программирования.
Во многихязыках программирования действуют правила хорошего программирования.35••••••Каждая переменная или описанная константа программы должна бытьиспользована в программе хотя бы один раз.Каждая переменная программы должна получить значение до своего первогоиспользования (например, до использования в правой части оператораприсваивания).Результат вычисления функции должен быть определен при любом ходе еевыполнения (например, независимо от выбора исполняемых ветвей вусловных операторах).В программе не должно быть невыполняемых в принципе операторов.Каждый оператор программы должен иметь потенциальную возможностьвыполниться хотя бы один раз.Условные операторы (всех разновидностей) должны предусматриватьвозможность хода выполнения программы по любой из своих ветвей.Операторы цикла должны предусматривать возможность завершения цикла.3.3.2.4.