
- •Выпускная квалификационная работа бакалавра
- •Задание на выпускную квалификационную работу бакалавра
- •План-график выполнения работы
- •Реферат
- •Введение
- •1 Языковые процессоры
- •1.1 Практическое применениеискусственных языков
- •1.2 Практический пример
- •1.3 Понятие и структура языкового процессора
- •2Обзор существующих систем и обоснование выбора инструментальных средств и класса грамматики
- •2.1 Обзор существующей символьной спецификации моделей гс в среде исма
- •2.1.1 Лексемы языка исма
- •2.1.2 Грамматика языка исма
- •2.1.3 Семантические действия в языковом процессоре исма
- •2.1.4 Заключение
- •2.2 Обоснование выбора инструментальных средств и класса грамматики
- •3 Постановка задачи исследования
- •3.1 Характеристика задачи исследования
- •3.2 Входная информация
- •3.3 Выходная информация
- •3.4 Архитектура среды исма с расширенным языком описания гс
- •4 Программно-математическое обеспечение
- •4.1Лексический анализатор
- •4.1.1 Функции лексического анализатора
- •4.1.2 Спецификация токенови входного алфавита символов
- •4.1.3 Распознавание токенов
- •4.1.4 Иерархия классов модуля
- •4.2 Синтаксический анализатор
- •4.2.1 Функции синтаксического анализатора
- •4.2.2 Спецификация грамматики
- •4.2.3 Метод разбора
- •4.2.4 Восстановление после ошибок
- •4.2.5 Иерархия классов модуля
- •4.3 Семантический анализ
- •4.3.1 Промежуточное представление программы
- •4.3.2 Грамматика с семантическими правилами
- •4.3.3 Модифицированныйметодразбора
- •4.3.4 Семантический анализ. Таблица символов
- •4.3.5 Семантический анализ. Проверка корректности типа
- •4.4 Генерация кода
- •4.5 Система сбора диагностических сообщений
- •5 Тестирование
- •5.1 Лексический анализатор
- •5.2 Синтаксическийанализатор
- •5.3 Семантический анализатор
- •Заключение
- •Список использованных источников
- •ПриложениеA Диагностические сообщения
- •Диагностические сообщения сканера
- •Диагностические сообщения парсера
- •Диагностические сообщения семантического анализатора
- •ПриложениеБ
- •Б.1.3 Установка системы
- •Б.2 Работа с системой б.2.1 Запуск системы и начало работы
- •Б.2.2Ввод программной модели
- •Б.2.3Трансляция модели и просмотр результата
- •Б.2.4Сохранение программной модели
- •Б.2.6Завершение работы с системой
- •Приложение в
- •Листинг программы
- •В.1 Модуль лексического анализатора
- •Файл abstractLexer.H
- •Файл lexer.H
- •Файл lexer.Cpp
- •В.2 Модуль синтаксического анализатора Файл abstractParser.H
- •Файлparser_ll1.H
- •Файл parser_ll1.Cpp
- •В.3 Модуль семантического анализатора Файл symbolTable.H
- •Файл SymbolTableFactory.H
- •Файл checker.H
- •В.4 Модулькодогенератора ФайлastVisitor.H
- •Файл astCodeGen.H
4.4 Генерация кода
Последней стадией языкового процессора является генерация выходной программы, используя абстрактное синтаксическое дерево.
На этом этапе происходит раскрытие всех конструкции с индексами, все остальные выводятся в выходной файл без изменений.
Опишем подробнее механизм раскрытия конструкций с индексами. К конструкциям с индексами относится задание ГНУ, ЛНУ и уравнений. Известно также, что индексы используется либо для явного задания, либодля неявного задания.
Первый способ подразумевает, что индексом является конкретное число ипри генерации выходной программы из конструкции с индексом будет получена одна конструкция без индекса. При этом все идентификаторы с индексом будут преобразованы в идентификаторы, полученные путём конкатенации имени массива с индексом, например переменная “A[1]” преобразуется в “A1”.
Второй способ подразумевает, что индексом является арифметическое выражение с переменной-счётчиком, которая пробегает целочисленные значения из заданных интервалов. Такая конструкция при генерации выходной программы размножится для каждого значения счётчика. Поэтому необходимо вычислить значение индексов для каждого значения счётчика.
Так как в промежуточном представлении программы каждая языковаяконструкцию представлена конкретным узлом синтаксического дерева, то удобно написать для каждого вида узла метод, который будет непосредственно генерировать код этой конструкции. Т.е. присутствуют объекты многих классов с различными интерфейсами, и мы хотим выполнять над ними операции, зависящие от конкретных классов. Для такой ситуации подходит паттерн посетитель (visitor). Он описывает операцию, выполняемую с каждым объектом из некоторой структуры, такжепозволяет определить новую операцию, не изменяя этих объектов. Дизайн паттерна приведен на рис. 4.13.
Рисунок 4.13 – Диаграмма паттерна “посетитель”
КлассVisitor – посетитель, объявляетоперациюVisitConcreateNodeдлякаждогоузлаConcreateNode. КлассAstCodGenVisitor – конкретныйпосетитель, реализует все операциикода генерации, объявленные в классе Visitor. КлассNode– узел, определяет операцию Accept, которая принимает посетителя в качестве аргумента. Класс ConcreateNode – конкретный узел, реализует операцию Accept, которая принимает посетителя в качестве аргумента. За обход дерева ответствененпосетитель, т.е. в методеVisitConcreateNode вызываются методы Acceptдля потомков текущего узла. Таким образом, реализовав все необходимые методы для посещения узлов, мы получим генератор кода по синтаксическому дереву.
Приведём показательный пример функции Visitдля узла операции вычитания (MinusExp)на псевдо коде:
Вызвать функцию Accept правого операнда
Вывести в выходной файлстроку “-”
Вызвать функцию Acceptлевого операнда
Аналогичный вид имеют функции для всех конструкций, не требующих преобразовании.
Более сложными являются функции для конструкций с индексами, например уравнения. На рис. 4.14 приведён алгоритм этой функции.
Рисунок 4.14 – Алгоритм генерации кода уравнения с индексом
Входными данными алгоритма является указатель на узел уравнения с индексами (EquationIndex), выходными является сгенерированный код конструкции, иначе сообщение об ошибке. При выполнении данной функции также выполняются проверки на выход значения индекса за границу массива. Вычисление значения индексного выражения осуществляется применением семантических правил к атрибутам узлов дерева этого выражения, т.е. проходом в топологическом порядке по дереву выражения и выполнением арифметических действий с атрибутами узлов.
Проверка на полноту системы уравнений осуществляется с помощью массива битов, размер которого равен количеству уравнений. Пригенерации кода уравнения в ячейку массива с индексом равным индексу левой части уравнения записывается единица, если к концу обработки классической части программы в массиве битов есть ячейка с нулём, то выдаётся сообщение обошибке.
Листинг этой фазы языкового процессора представлен в Приложении В в разделе кодогенератор.