
- •Федеральное агентство по образованию
- •190000, Санкт-Петербург, ул. Б. Морская, 67 Лабораторная работа №1 Сканирование и лексический анализ текстов c применением утилиты flex
- •1. Лексический анализ и регулярные выражения
- •2. Структура сканера текстов, создаваемого утилитой flex
- •3. Файл описания сканера
- •4. Параметры flex
- •5. Пример описания сканера
- •6. Использование синтезированного программного кода
- •7. Задание на выполнение лабораторной работы
- •8. Варианты заданий
- •Лабораторная работа №2 Синтаксический анализ текстов c применением утилиты bison
- •1. Синтаксический анализ и магазинные автоматы
- •2. Построение набора правил для описания формального языка
- •3. Структура анализатора, создаваемого утилитой bison
- •4. Файл описания синтаксического анализатора
- •5. Параметры утилиты bison
- •6. Типичные ошибки при составлении грамматики
- •7. Пример описания синтаксического анализатора
- •8. Использование синтезированного программного кода
- •9. Задание на лабораторную работу
- •10. Варианты заданий
- •Библиографический список
- •Содержание
2. Построение набора правил для описания формального языка
Основной задачей по разработке анализатора является составление набора правил (продукций), определяющих язык, которые затем преобразуются в магазинный автомат.
При составлении правил отправной точкой служит набор лексем, которыми оперирует сканер текстов. Они образуют множество терминальных символов. Например, множество может включать ключевые слова IF, THEN ELSE, а также идентификатор (id) и целое число (int) для случая простейшего языка программирования. При необходимости разбора текстовой информации в виде некоторой таблицы данных набор нетерминалов может, например, включать ключевые слова DATE, и AMOUNT, используемые в заголовке таблицы, разделитель «Табуляция» (tab), разделитель шапки таблицы “=====” (eq), дату в формате MM/DD/YYYY (date), число с фиксированной запятой (num) и т.д.
Далее вводятся обобщенные понятия, описывающие некоторые смысловые фрагменты цепочек языка. Например, “Выражение” (Expr), которое для простейшего языка программирования может быть определено: Expr -> id, а также Expr -> int. В данном случае приведены две продукции, описывающие возможные способы образования выражения в языке программирования. Для сокращения записи часто применяют символ | и объединяют продукции, в левых частях которых стоит один и тот же нетерминальный символ, записывая их следующим образом: Expr -> id | int.
Аналогично рассуждая, можно вывести продукцию для понятия «условный оператор» (CondStatment), используя при этом как множество исходных лексем, так и понятий (нетерминалов), выведенных на предыдущем шаге : CondStatment-> IF Expr THEN Expr ELSE Expr. Процесс продолжается вплоть до определения исходного понятия, например «Программа» (Prog) через ранее определенные понятия: Prog-> CondStatment. При составлении правил разбора для случая синтаксического анализа табличной информации, могут быть введены следующие понятия: «Элемент таблицы» (Cell) , «Шапка таблицы» (Header), «Строка таблицы» (Row): Cell->date | num; Row-> Cell tab Cell; Header-> DATE tab AMOUNT eq;
В процессе составления продукций может потребоваться использование рекурсии или пустой продукции. В первом случае результирующая продукция включает имя понятия как в левой части, так и в правой. Например, «Множество строк таблицы» (Rows): Rows -> Row | Rows Row, задает одну или несколько строк. Если требуется также указать факт возможного отсутствия строк в таблице, то правило записывается как: Rows -> |Row | Rows Row с использованием пустой продукции, не содержашей никаких символов (отделенной от других первым разделителем | )
3. Структура анализатора, создаваемого утилитой bison
Утилита bison предназначена для генерации программного кода синтаксического анализатора на основе заданой грамматики (набора продукций). Утилита создает программный код на языке С/C++, доступный для встраивания в программу на C или С++. Синтаксический анализатор содержится в одном файле исходного кода и имеет процедурный API (программный интерфейс), структура анализатора представлена на Рис. 3. Помимо файла с программным кодом, утилита также может создавать включаемый файл, в котором через директиву #define объявлены коды лексем, описанных как входные в файле с заданной грамматикой. Этот включаемый файл может быть использован для согласования кодировки лексем между анализатором и сканером тестов.
Рис. 3. Структура создаваемого файла анализатора
Утилита bison создает лишь процедурную реализацию синтаксического анализатора, объектная реализация является экспериментальной и содержит большое количество ошибок.
Как следует из структуры создаваемого файла, bison-анализатор предполагает наличие в результирующией программе нескольких функций, на которые ссылается создаваемый программный код. Это функции int yylex() и void yyerror (char const* msg). Первая из них должна возвращать код лексемы. Эта функция может быть реализована путем создания лексического анализатора с использованием flex, как описано в предыдущей лабораторной работе. При генерации процедурного сканера текстов yylex() создается автоматически и является доступной. В случае, когда сканер текстов реализован в виде C++ класса, потребуется создание глобальной функции-заместителя, которую будет вызывать анализатор и которая, в свою очередь, выполняет вызов метода yylex() у объекта класса yyFlexLexer. Функция сканирования возвращает либо код лексемы, либо 0 по завершении работы. Внешняя функция yyerror должна быть реализована в основной программе. Возвращаемое значение не анализируется, а основная задача данной функции – печать сообщения об ошибке. Дальнейшее поведение анализатора зависит от того, были при его генерации указаны правила восстановления после ошибок или нет; в последнем случае анализатор завершает работу при обнаружении ошибки.
Основной точкой входа в анализатор служит функция yyparse. Функция выполняет синтаксический анализ путем чтения лексем, анализа и выполнения заданных пользователем действий при обнаружении фрагментов текста, соответствующих правилам; возврашает код 0 при завершении чтения всех лексем, если анализ успешен, или 1 в случае обнаружения синтаксической ошибки.