- •1. Языки, грамматики и их классификация. Примеры контекстно-свободных грамматик.
- •2 Трансляция арифметических выражений.
- •3 Классы. Свойства и методы, защита элементов классов. Создание и уничтожение объектов.
- •4 Управление динамической памятью
- •5 Технология создания программ и комплексов. Визуальное программирование.
- •6 Препроцессор и его основные возможности.
- •7 Адреса, указатели, ссылки. Адресная арифметика.
2 Трансляция арифметических выражений.
Бесскобочная форма записи выражений (ПОЛИЗ)
Представление выражения в виде дерева
Вычисление выражения по ПОЛИЗ
Алгоритм перевода выражения из инфиксной формы в ПОЛИЗ
Стек операций и приоритеты
Арифметические выражения являются одной из основных конструкций в большинстве современных языков программирования, поэтому их трансляция является очень распространенной задачей, решаемой компиляторами.
Для облегчения решения этой задачи используют способ записи выражений, не содержащей скобок, который был предложен польским математиком Лукасевичем. Вычисление таких выражений выполняется за один проход слева направо, т.к. непосредственно перед каждой операцией в тексте находятся все ее операнды. Например,
выражение (a + b)*(c + d) можно записать в форме a b + c d + *
При вычислении выражения в бесскобочной форме результат каждой выполненной операции заменяет саму операцию и ее операнды в выражении. Такие выражения легко транслировать в машинные команды. Эта форма называется польской обратной записью (ПОЛИЗ) или префиксной формой в отличие от обычной, инфиксной формы.
Для перевода из инфиксной формы в префиксную форму используется алгоритм, в котором операции помещаются в специальный стек (магазинная память) и выталкиваются из него в порядке их приоритетов. В простейшем варианте этот алгоритм можно описать следующим образом:
- каждый операнд со входа поступает на выход
- открывающая скобка помещается в стек
- знак операции попадает в стек, но предварительно выталкивает из него на выход все одинаковые по приоритету и более приоритетные операции в обратном порядке
- закрывающая скобка выталкивает из стека на выход все операции в обратном порядке до соответствующей открывающей скобки; сами скобки на выход не попадают
Этот алгоритм расширяется и для случая использования элементов массивов и функций за счет использования соответствующих приоритетов. Кроме того, он естественным способом распространяется и на другие типы выражений – логические, символьные и другие.
Процесс вычисления арифметических выражений наглядно представляется в виде дерева, где в концевых узлах находятся терминальные операнды, т.е. переменные и константы; в промежуточных узлах – знаки операций, а поддеревьями у этих операций являются выражения, задающие их операнды. Их количество зависит от арности самой операции. Вычисление выражения, заданного деревом начинается с любой операции, у которой уже вычислены все ее операнды. Функции можно считать разновидностью операций, возможно с большим числом параметров. Вычисленное значение элементарного подвыражения (поддерево), определенного операцией и ее операндами, заменяет в дереве саму операцию.
Этот алгоритм можно очевидно записать в рекурсивной форме, также как само выражение легко определяется с помощью рекурсивных правил подстановок:
для вычисления выражения надо вычислить все операнды (более элементарные выражения) и выполнить операцию.
Этот алгоритм аналогичен рекурсивному алгоритму концевого обхода дерева, в котором сначала обходятся поддеревья (в любом порядке), потом проходится его корень.
КС-грамматика, описывающая простые арифметические выражения, может выглядеть следующим образом:
<Выр-е> -> <Переменная>
<Выр-е> -> <Константа>
<Выр-е> -> <Выр-е> + <Выр-е>
<Выр-е> -> <Выр-е> - <Выр-е>
<Выр-е> -> <Выр-е> * <Выр-е>
<Выр-е> -> <Выр-е> / <Выр-е>
<Выр-е> -> ( <Выр-е> )
