Ниже рассмотрены некоторые основные технические вопросы, позволяющие реализовать схемы СУ-перевода для данной лабораторной работы. Более подробно с механизмами СУ-перевода и СУ-компиляции можно ознакомиться в [1, 2, 7].
Способы внутреннего представления программ
Результатом работы синтаксического анализатора на основе КС-грамматики входного языка является последовательность правил грамматики, примененных для построения входной цепочки. По найденной последовательности, зная тип распознавателя, можно построить цепочку вывода или дерево вывода. В этом случае дерево вывода выступает в качестве дерева синтаксического разбора и представляет собой результат работы синтаксического анализатора в компиляторе.
Однако ни цепочка вывода, ни дерево синтаксического разбора не являются целью работы компилятора. Для полного представления о структуре разобранной синтаксической конструкции входного языка в принципе достаточно знать последовательность номеров правил грамматики, примененных для ее построения. Однако форма представления этой информации может быть различной в зависимости как от реализации самого компилятора, так и от фазы компиляции. Эта форма называется внутренним представлением программы (иногда используются также термины промежуточное представление или промежуточная программа).
Все внутренние представления программы обычно содержат в себе два принципиально различных элемента – операторы и операнды. Различия между формами внутреннего представления заключаются лишь в том, как операторы и операнды соединяются между собой. Также операторы и операнды должны отличаться друг от друга, если они встречаются в любом порядке. За различение операндов и операторов, как уже было сказано выше, отвечает разработчик компилятора, который руководствуется семантикой входного языка.
Известны следующие формы внутреннего представления программ:
[5]
• структуры связных списков, представляющие синтаксические деревья;
• многоадресный код с явно именуемым результатом (тетрады);
• многоадресный код с неявно именуемым результатом (триады);
• обратная (постфиксная) польская запись операций;
• ассемблерный код или машинные команды.
В каждом конкретном компиляторе может использоваться одна из этих форм, выбранная разработчиками. Но чаще всего компилятор не ограничивается использованием только одной формы для внутреннего представления программы.
На различных фазах компиляции могут использоваться различные формы, которые по мере выполнения проходов компилятора преобразуются одна в другую.
Некоторые компиляторы, незначительно оптимизирующие результирующий код, генерируют объектный код по мере разбора исходной программы. В этом случае применяется схема СУ-компиляции, когда фазы синтаксического разбора, семантического анализа, подготовки и генерации объектного кода совмещены в одном проходе компилятора. Тогда внутреннее представление программы существует только условно в виде последовательности шагов алгоритма разбора.
Алгоритмы, предложенные для выполнения данной лабораторной работы, построены на основе использования формы внутреннего представления программы в виде триад. Поэтому далее будет рассмотрена именно эта форма внутреннего представления программы. С остальными формами можно более подробно познакомиться в [1–3, 7].
Многоадресный код с неявно именуемым результатом (триады)
Триады представляют собой запись операций в форме из трех составляющих: операция и два операнда. Например, в строковой записи триады могут иметь вид: <���операция>(<���операнд1>,<���операнд2>). Особенностью триад является то, что один или оба операнда могут быть ссылками на другую триаду в том случае, если в качестве операнда данной триады выступает результат выполнения другой триады. Поэтому триады при записи последовательно нумеруют для удобства указания ссылок одних триад на другие (в реализации компилятора в качестве ссылок можно использовать не номера триад, а непосредственно ссылки в виде указателей – тогда при изменении нумерации и порядка следования триад менять ссылки не требуется).
Например, выражение A:=B-C+D-B-10, записанное в виде триад, будет иметь вид:
1: * (B, C)
2: + (^1, D)
3: * (B, 10)
4: – (^2, ^3)
5::= (A, ^4)
Здесь операции обозначены соответствующими знаками (при этом присваивание также является операцией), а знак ^ означает ссылку операнда одной триады на результат другой.
Читать дальше
Конец ознакомительного отрывка
Купить книгу