- •Министерство образования и науки рф
- •Основы построения трансляторов Курс лекций по дисциплине «Системное программное обеспечение» Красноярск 2010 г.
- •1. Место трансляторов в системном программном обеспечении. Основные фазы процесса трансляции
- •Генерация промежуточного представления
- •Генерация кода
- •Контрольные вопросы
- •2. Базовые понятия теории формальных языков и грамматик
- •2.1. Алфавиты, цепочки и языки. Основные понятия и определения
- •2.2. Представление языков
- •2.3. Грамматики
- •2.3.1. Формальное определение грамматики
- •2.3.2. Классификация грамматик и языков по Хомскому
- •2.3.3. Разбор цепочек
- •2.3.4. Преобразования грамматик
- •2.4. Задачи
- •3. Лексический анализ
- •Описание модельного языка
- •3.1. Сущность и задачи лексического анализа
- •3.2. Способы организации таблиц идентификаторов
- •Организация таблицы идентификаторов в виде неупорядоченного массива записей. Метод линейного поиска.
- •Организация таблицы идентификаторов в виде упорядоченного массива записей. Метод бинарного поиска.
- •Использование бинарного дерева поиска для построения таблицы идентификаторов.
- •Построение таблиц идентификаторов с использованием методов хеширования.
- •3.3. Методы и средства лексического анализа
- •3.4. Недетерминированный разбор
- •3.5 Разработка лексического анализатора для модельного языка Описание модельного паскалеподобного языка (м-языка):
- •Контрольные вопросы
- •4. Синтаксический и семантический анализ
- •4.1. Задачи и методы синтаксического анализа
- •4.2 Сущность метода рекурсивного спуска
- •Void error(); / функция обработки ошибок /
- •4.3. Условия применимости метода рекурсивного спуска
- •4.4. Синтаксический анализатор для м-языка
- •4.5. Семантический анализ
- •4.6. Семантический анализатор для м-языка
- •4.6.1. Обработка описаний
- •Int declare; / описан ? 1-"да", 0-"нет" /
- •Void ipush (int I); / значение I - в стек /
- •Int ipop (void); / из стека - целое /
- •4.6.2. Контроль контекстных условий в выражении
- •Void spush (char s); / значение s - в стек /
- •If (tid [I].Declare) / описан? /
- •4.6.3. Контроль контекстных условий в операторах
- •4.7. Задачи
- •5. Генерация внутреннего представления программ
- •5.1. Язык внутреннего представления программы
- •5.2 Синтаксически управляемый перевод
- •5.3 Генератор внутреннего представления программы на м-языке
- •5.4 Интерпретатор полиЗа для модельного языка
- •5.5 Задачи
- •Литература
5.4 Интерпретатор полиЗа для модельного языка
Польская инверсная запись была выбрана нами в качестве языка внутреннего представления программы, в частности, потому, что записанная таким образом программа может быть легко проинтерпретирована.
Идея алгоритма очень проста: просматриваем ПОЛИЗ слева направо; если встречаем операнд, то записываем его в стек; если встретили знак операции, то извлекаем из стека нужное количество операндов и выполняем операцию, результат (если он есть) заносим в стек и т.д.
Итак, программа на ПОЛИЗе записана в массиве P; пусть она состоит из N элементов-лексем. Каждая лексема - это структура
struct lex {int class; int value;},
возможные значения поля class:
- лексемы-метки (номера элементов в ПОЛИЗе)
- логические константы true либо false (других лексем - служебных слов в ПОЛИЗе нет)
- операции (других лексем-ограничителей в ПОЛИЗе нет)
- целые константы
- лексемы-идентификаторы (во время интерпретации будет использоваться значение)
- лексемы-идентификаторы (во время интерпретации будет использоваться адрес).
Считаем, что к моменту интерпретации распределена память под константы и переменные, адреса занесены в поле address таблиц TID и TNUM, значения констант размещены в памяти.
В программе-интерпретаторе будем использовать некоторые переменные и функции, введенные нами ранее.
void interpreter(void) {
int ip;
int i, j, arg;
for (i = 0; i<=N; i++)
{curr_lex = P[i];
switch (curr_lex.class) {
case 0: ipush (curr_lex.value); break;
/ метку ПОЛИЗ - в стек /
case 1: if (eq ("true")) ipush (1);
else ipush (0); break;
/ логическое значение - в стек /
case 2: if(eq ("+")){ipush (ipop() + ipop()); break};
/выполнили операцию сложения, результат - в стек/
if (eq ("-"))
{arg = ipop(); ipush (ipop() - arg); break;}
/аналогично для других двухместных арифметических и логических операций /
if (eq ("not")) {ipush (!ipop()); break;};
if (eq ("!")) {j = ipop(); i = j-1; break;};
/ интерпретация будет продолжена с j-го элемента ПОЛИЗа /
if (eq ("!F")) {j = ipop(); arg = ipop();
if (!arg) {i = j-1}; break;};
/если значение arg ложно, то интерпретация будет продолжена с j -го элемента ПОЛИЗа, иначе порядок не изменится /
if (eq (":=")) {arg = ipop(); ip = (int)ipop();
ip = arg; break;};
if (eq ("R")) {ip = (int) ipop();
scanf("%d", ip); break;};
/ "R" - обозначение операции ввода /
if (eq ("W")) {arg = ipop();
printf ("%d", arg); break;};
/ "W" - обозначение операции вывода /
case 3: ip = TNUM [curr_lex.value].address;
ipush(ip); break;
/ значение константы - в стек /
case 4: ip = TID [curr_lex.value].address;
ipush(ip); break;
/ значение переменной - в стек /
case 5: ip = TID [curr_lex.value}.address;
ipush((int)ip); break;
/ адрес переменной - в стек /
} / конец switch /
} / конец for /
}
