Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Дерево разбора. Преобразование дерева разбора в дерево операций




Синтаксические деревья

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

 

 

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

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

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

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

Алгоритм преобразования дерева вывода в дерево операций:

1). Если в дереве больше не содержится узлов, помеченных нетерминальны­ми символами, то выполнение алгоритма завершено, иначе — перейти к шагу 2.

2). Выбрать крайний левый узел дерева, помеченный нетерминальным символом грамматики и сделать его текущим. Перейти к шагу 3.

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

иначе — перейти к шагу 4.

4). Если текущий узел имеет нижележащий узел (лист дерева), помеченный терминальным символом, который не несет семантической нагрузки, тогда этот лист нужно удалить из дерева и вернуться к шагу 3; иначе — перейти к шагу 5.

5). Если текущий узел имеет один нижележащий узел (лист дерева), помеченный терминальным символом, обозначающим знак операции, а остальные узлы помечены как операнды, то узел, помеченный знаком операции, надо уда­лить из дерева, текущий узел пометить этим знаком операции и перейти к шагу 1; иначе — перейти к шагу 6.

6). Если среди нижележащих узлов для текущего узла есть узлы, помечен­ные нетерминальными символами грамматики то необходимо выбрать крайний левый среди этих узлов, сделать его текущим узлом перейти к шагу 3; иначе — выполнение алгоритма завершено.

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

Пример синтаксического дерева, построенного для цепочки (а+а)*b из языка, заданного различными вариантами грамматики арифметиче­ских выражений представлен на рис. 42.

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

 

Рис. 42. Пример дерева операций для языка арифметических выражений

 

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

Преимущества внутреннего представления в виде дерева операций:

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

2) синтаксические деревья – это машинно-независимая форма внутреннего представления программы.

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

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

 

8.5 Трехадресный код. Типы трехадресных инструкций

 

Трехадресный код представляет собой последовательность инструкций вида

х:= у op z

где х, у и z — имена, константы или временные переменные, генерируемые компилято­ром; ор означает некоторый оператор, например арифметический оператор для работы с числами с фиксированной или плавающей точкой или оператор для работы с логически­ми значениями. Например, вы­ражение исходного языка наподобие х+у*z может быть транслировано в следующую последовательность.

t1:= у * z

t2:= х + t1

Здесь t1 и t2— сгенерированные компилятором временные имена. Использование имен для вычисленных программой промежуточных значений обеспечивает трехадресному коду, в отличие от постфиксной записи, возможность легкого переупорядочения.

Термин "трехадресный код" отражает тот факт, что каждая инст­рукция обычно содержит три адреса — два для операндов и один для результата.

Список некоторых основных трехадресных инструкций, используемых в большинстве языков программирования:

1. Инструкции присвоения вида х:= у op z, где ор— бинарная арифметическая или логическая операция.

2. Инструкция присвоения вида х:= ор у, где ор — унарная операция. Основные унарные операции включают унарный минус, логическое отрицание, операторы сдвига и операторы преобразования, которые, например, преобразуют число с фик­сированной точкой в число с плавающей точкой.

3. Инструкции копирования вида х: = у, в которых значение у присваивается х.

4. Безусловный переход goto L. После этой инструкции будет выполнена трехадресная инструкция с меткой L.

5. Условный переход типа if х relop у goto L. Эта инструкция применяет опе­ратор отношения relop (<, >= и т.п.) к х и у, и следующей выполняется инструк­ция с меткой L, если соотношение х relop у верно. В противном случае выпол­няется следующая за условным переходом инструкция.

7. Индексированные присвоения типа х:= y[i] x[i]:= у. Первая инструкция присваивает х значение, находящееся в i-й ячейке памяти по отношению к у. Инст­рукция х[i]: = у заносит в i-ю ячейку памяти по отношению к х значение у. В обеих инструкциях х, у и i ссылаются на объекты данных.

8. Присвоение адресов и указателей вида х: = &у, х: = *у и *х: = у. Первая ин­струкция устанавливает значение х равным положению у в памяти. Предположи­тельно, у представляет собой имя, возможно временное, обозначающее выражение с l-значением типа А [i,j ], а х — имя указателя или временное имя. Таким образом, r-значение х представляет собой значение некоторого объекта. Во второй инструк­ции под у подразумевается указатель или временная переменная, l-значение которой представляет собой местоположение ячейки памяти. В результате l-значение х ста­новится равным содержимому этой ячейки. И наконец, инструкция *х:= у уста­навливает l-значение объекта, указываемого х, равным l-значению у.

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




Поделиться с друзьями:


Дата добавления: 2014-12-27; Просмотров: 5863; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.009 сек.