Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Виды семантических действий и способы их реализации в компиляторах.




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

· таблица идентификаторов;

· результаты разбора синтаксических конструкций входного языка.

Результаты выполнения синтаксического анализа могут быть представлены в од­ной из форм внутреннего представления программы в компиляторе. Как правило, на этапе семантического анализа используются различные варианты синтаксиче­ских деревьев, построенных в результате синтаксического разбора, поскольку се­мантический анализатор интересует прежде всего структура исходной программы. Семантический анализ обычно выполняется на двух этапах компиляции: на этапе синтаксического разбора и в начале этапа подготовки к генерации кода. В первом случае всякий раз по завершении анализа определенной синтаксической конструк­ции входного языка выполняется ее семантическая проверка на основе имеющихся в таблице идентификаторов данных (такими конструкциями, как правило, явля­ются процедуры, функции и блоки операторов входного языка). Во втором слу­чае, после завершения всей фазы синтаксического анализа, выполняется полный семантический анализ программы на основании данных в таблице идентифика­торов (сюда попадает, например, поиск неописанных идентификаторов). Иногда семантический анализ выделяют в отдельный этап (фазу) компиляции. В каждом компиляторе обычно присутствуют оба варианта семантического ана­лизатора. Конкретная их реализация зависит от версии компилятора и семанти­ки входного языка.

 

Этапы семантического анализа

Семантический анализатор выполняет следующие основные действия:

· проверку соблюдения во входной программе семантических соглашений входного языка;

· дополнение внутреннего представления программы в компиляторе операто­рами и действиями, неявно предусмотренными семантикой входного языка;

· проверку элементарных семантических (смысловых) норм языков програм­мирования, напрямую не связанных со входным языком.

Проверка соблюдения во входной программе семантических соглашений

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

· каждая метка, на которую есть ссылка, должна один раз присутствовать в про­грамме;

· каждый идентификатор должен быть описан один раз и ни один идентификатор не может быть описан более одного раза (с учетом блочной структуры описаний);

· все операнды в выражениях и операциях должны иметь типы, допустимые для данного выражения или операции;

· типы переменных в выражениях должны быть согласованы между собой;

· при вызове процедур и функций число и типы фактических параметров долж­ны быть согласованы с числом и типами формальных параметров.

Это только примерный перечень такого рода требований. Конкретный состав требований, которые должен проверять семантический анализатор, жестко свя­зан с семантикой входного языка (например, некоторые языки допускают не описывать идентификаторы определенных типов).

Дополнение внутреннего представления программы

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

Таким образом, и в этом случае действия, выполняемые семантическим анали­затором, существенным образом влияют на порождаемый компилятором код результирующей программы.

 

Проверка смысловых норм языков программирования

Проверка элементарных смысловых норм языков программирования, напрямую не связанных со входным языком, — это сервисная функция, которую предо­ставляют разработчикам большинство современных компиляторов. Эта функция обеспечивает проверку компилятором соглашений, выполнение которых связано со смыслом как всей исходной программы в целом, так и отдельных ее фрагмен­тов. Эти соглашения применимы к большинству современных языков программирования.
Примерами таких соглашений являются следующие требования:

· каждая переменная или константа должна хотя бы один раз использоваться в программе;

· каждая переменная должна быть определена до ее первого использования при любом ходе выполнения программы (первому использованию перемен­ной должно всегда предшествовать присвоение ей какого-либо значения);

· результат функции должен быть определен при любом ходе ее выполнения;

· каждый оператор в исходной программе должен иметь возможность хотя бы один раз выполниться;

· операторы условия и выбора должны предусматривать возможность хода вы­полнения программы по каждой из своих ветвей;

· операторы цикла должны предусматривать возможность завершения цикла.

 

Конечно, это только примерный перечень основных соглашений. Конкретный состав проверяемых оглашений зависит от семантики языка.

 

Идентификация лексических единиц языков программирования

Идентификация переменных, типов, процедур, функций и других лексических единиц языков программирования — это установление однозначного соответст­вия между лексическими единицами и их именами в тексте исходной програм­мы. Идентификация лексических единиц языка чаще всего выполняется на эта­пе семантического анализа.

Как правило, большинство языков программирования требуют, чтобы в ис­ходной программе имена лексических единиц не совпадали как между собой, так и с ключевыми словами синтаксических конструкций языка. Но чаще всего этого бывает недостаточно, чтобы установить однозначное соответствие между, лексическими единицами и их именами, поскольку существуют дополнительные смысловые (семантические) ограничения, накладываемые языком на употреб­ление этих имен.

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

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

Можно дать примерный перечень действий компиляторов для идентификации переменных, констант, функций, процедур и других лексических единиц языка:

· имена локальных переменных дополняются именами тех блоков (функций, процедур), в которых эти переменные описаны;

· имена внутренних переменных и функций модулей исходной программы до­полняются именами самих модулей (это касается только внутренних имен);

· имена процедур и функций, принадлежащих объектам (классам) в объектно-ориентированных языках программирования дополняются наименованиями типов объектов (классов), которым они принадлежат;

· имена процедур и функций модифицируются в зависимости от типов их фор­мальных аргументов.

Конечно, это далеко не полный перечень возможных действий компилятора, каждая реализация компилятора может предполагать свой набор действий.

 


 


Поделиться:

Дата добавления: 2015-04-18; просмотров: 192; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты