
- •Федеральное агентство по образованию
- •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. Варианты заданий
- •Библиографический список
- •Содержание
Федеральное агентство по образованию
Государственное образовательное учреждение
высшего профессионального образования
Санкт-Петербургский государственный университет
аэрокосмического приборостроения
ТЕОРИЯ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ И МЕТОДЫ ТРАНСЛЯЦИИ
СРЕДСТВА АВТОМАТИЗАЦИИ ПОСТРОЕНИЯ СИНТАКСИЧЕСКИХ АНАЛИЗАТОРОВ
Методические указания
к выполнению лабораторных работ № 1-2
Санкт-Петербург
2006
Составители: А.В.Бржезовский, Т.М.Максимова, А.А.Янкелевич
Рецензент: А.В.Гордеев
В методические указания включены краткие теоретические сведения об автоматных моделях распознавателей формальных языков, описание возможностей утилит flex и bison по автоматической генерации программного кода лексического и синтаксического анализаторов, варианты индивидуальных заданий на выполнение лабораторных работ.
Предназначены для студентов всех форм обучения, проходящих подготовку по специальностям 230105 и 010503.
Подготовлены кафедрой компьютерной математики и программирования и рекомендованы к изданию редакционно-издательским советом Санкт-Петербургского государственного университета аэрокосмического приборостроения.
© ГОУ ВПО СПбГУАП, 2006
_______________________________________________________________________________
Подписано к печати Формат 60х84 1/16. Бумага офсетная. Печать офсетная
Усл. печ. л Усл. кр.-отт. 0,00. Уч.- изд. л Тираж экз. Заказ №
________________________________________________________
Редакционно-издательский отдел
Отдел электронных публикаций и библиографии библиотеки
Отдел оперативной полиграфии
СПбГУАП
190000, Санкт-Петербург, ул. Б. Морская, 67 Лабораторная работа №1 Сканирование и лексический анализ текстов c применением утилиты flex
1. Лексический анализ и регулярные выражения
Лексический анализ – разбиение последовательности символов входного текста на последовательность слов, или лексем. Выделение лексем из текста обычно предшествует стадии синтаксического анализа, например, при построении компилятора с какого-нибудь языка программирования, хотя может потребоваться и для решения других задач, не связанных с синтаксическим анализом текстов. Обычно все лексемы делятся на классы. Примерами таких классов являются числа (целые, восьмеричные, шестнадцатиричные, действительные и т.д.), идентификаторы, строки. Отдельно выделяются ключевые слова и символы пунктуации (иногда их называют символы-ограничители). Как правило, ключевые слова - это некоторое конечное подмножество идентификаторов. В большинстве случаев лексический анализ выполняется перед синтаксическим. Программный компонент, осуществляющий подобную операцию, называется лексическим анализатором или сканером.
Разделение сканирования текста с целью выделения лексем и дальнейшего синтаксического анализа с генерацией кода либо данных позволяет сделать программу-распознаватель модульной, исключить ненужные зависимости синтаксического и других модулей от особенностей форматирования входных текстов и, в конечном итоге, упростить каждый из компонентов.
Использование специализированных утилит, генерирующих программный код для сканирования текстов, позволяет облегчить процесс создания программного обеспечения для обработки текстовой информации. Генерируемый программный код (на языке С/С++ для случая использования flex), не содержит дополнительных ошибок, которые могут быть внесены при ручной разработке сканера, и может быть включен практически в любой конечный программный продукт без какой бы то ни было модификации.
Утилита генерации сканера использует описание возможных последовательностей входных символов, которые следует распознать как лексемы, в виде регулярных выражений. Набор регулярных выражений, составленный с учетом особенностей анализируемого языка, задается во входном файле для утилиты flex, которая на выходе порождает файлы с исходным кодом сканера.
Пусть T - конечный алфавит. Регулярное множество в алфавите T определяется рекурсивно следующим образом:
1) {} (пустое множество) - регулярное множество в алфавите T;
2) {a} - регулярное множество в алфавите T для каждого a T;
3){е} - регулярное множество в алфавите T (e - пустая цепочка);
4) если P и Q - регулярные множества в алфавите T, то таковы же и множества
- P Q (объединение),
- PQ (конкатенация, т.е. множество {pq}, p P, q Q),
- P* (итерация: P*={e} P PP ...;
- ничто другое не является регулярным множеством в алфавите T.
Итак, множество в алфавите T регулярно тогда и только тогда, когда оно либо {}, либо {e}, либо {a} для некоторого a T, либо его можно получить из этих множеств применением конечного числа операций объединения, конкатенации и итерации.
Приведенное выше определение регулярного множества одновременно определяет и форму его записи, которую будем называть регулярным выражением. Для сокращенного обозначения выражения PP* будем пользоваться записью P+ и там, где это необходимо, будем использовать скобки. В этой записи наивысшим приоритетом обладает операция *, затем - конкатенация и, наконец, операция , для записи которой иногда будем использовать значок '|'. Так, 0|10* означает (0|(1(0*))).
Кроме того, мы будем использовать запись вида d1 = r1 d2 = r2 ....... dn = rn, где di - различные имена, а каждое ri - регулярное выражение над символами T{d1,d2,...,di-1}, т.е. символами основного алфавита и ранее определенными символами. Таким образом, для любого ri можно построить регулярное выражение над Т, повторно заменяя имена регулярных выражений на обозначаемые ими регулярные выражения.
Несколько примеров регулярных выражений и обозначаемых ими множеств. Идентификатор - это регулярное выражение
Идентификатор = Буква (Буква|Цифра)*
Буква = {a,b,...,z} Цифра = {0,1,...,9}
Число в десятичной записи - это регулярное выражение
Целое = Цифра+
Дробная_часть = . Целое | е
Степень = ( Е ( + | - | е ) Целое ) | е
Число = Целое Дробная_часть Степень
Состав набора регулярных выражений зависит от того, какие лексемы ожидается получить на выходе сканера, и, обычно, определяется тем, какого рода синтаксический анализ следует проводить в дальнейшем. Например, для языка basic в качестве лексем могут рассматриваться: десятичное число, идентификатор, ключевое слово IF, ключевое слово THEN и так далее. В то же время, для сканирования и дальнейшей обработки некоего произвольного текста, например, табличной информации в виде ASCII документа, может потребоваться набор лексем, зависящий от того, как и каким образом сканируемая информация будет в дальшейшем использована. Набор лексем может для рассматриваемого примера включать: ключевые слова DATE и AMOUNT, используемые в заголовке таблицы; лексему-разделитель колонок, роль которой играет символ «Табуляция»; лексему- разделитель шапки таблицы от остальной ее части, роль которой играет последовательность символов “=====”; лексему «дата», определяющую дату в формате MM/DD/YYYY; а также лексему - число с фиксированной запятой.
По составленному набору регулярных выражений возможна автоматическая генерация программы-распознавателя.