
- •Теория языков программирования и методы трансляции
- •2.3 Грамматики
- •2.4. Распознаватели
- •2.5 Регулярные выражения и синтаксические диаграммы
- •26. Понятие синтаксического анализа. Левые и правые анализаторы. Реализация левого анализатора на базе к- предсказывающего алгоритма разбора.
- •Ll(k) - грамматики
2.5 Регулярные выражения и синтаксические диаграммы
Многие языковые конструкции удобно описываются регулярными выражениями. Эти выражения вводятся через понятие "регулярное множество".
Определение.
Пусть
- конечный алфавит. Регулярное множество
в алфавите
определяется рекурсивно следующим
образом:
1) - регулярное множество;
2) {e}-регулярное множество;
3) {a}-регулярное
множество для всех
;
4) если P и Q -регулярные множества, то регулярными являются
множества:
(объединение);
PQ (конкатенация);
(итерация),
где итерация множества P определяется
так:
5) ничто другое не является регулярным множеством в алфавите .
Определение. Регулярные выражения в алфавите обозначают регулярные множества и определяются следующим образом:
1) - обозначает пустое множество ;
2) е - обозначает множество {e};
3) если , то а - обозначает {a};
4) если p и q обозначают P и Q соответственно, то
(p+q) - обозначает
,
(pq) - обозначает PQ,
- обозначает
;
5) ничто другое не является регулярным выражением.
Замечания:
1. Можно показать,
что
.
2. Лишние скобки могут устраняться из выражений, если это не приводит к недоразумениям.
3. Приоритеты операций: "*", "конкатенация", "+".
Регулярные
выражения имеют следующие алгебраические
свойства: если
-
регулярные выражения, то:
- играет роль нуля ( свойство 8);
е - играет роль единицы (свойство 7).
Пример 2.16. Рассмотрим примеры регулярных выражений:
1) 01 обозначает {01};
2) 0 обозначает {0 };
3) (0+1) обозначает {0,1};
4)
обозначает множество всех цепочек,
составленных
из 0 и 1 и оканчивающихся цепочкой 011;
5)
обозначает множество всех цепочек,
составленных из 0,1,a,b и начинающихся
с а или b;
6)
- обозначает множество всех цепочек,
содержащих четное число нулей и четное
число единиц.
В практике разработки формальных языков для их описания нередко используют синтаксические диаграммы. Синтаксическая диаграмма является эквивалентным представлением грамматики языка и в ряде случаев она оказывается предпочтительнее в силу своей большей наглядности и компактности. Применение этого способа для описания лексем и конструирования сканеров будет рассмотрено в гл. 3.
3. Общая характеристика процесса сканирования. Методики конструирования сканеров (характеристика каждого этапа построения сканера и применяемые методы).
Представление результатов сканирования.
Лексический анализ ( или сканирование) образует первый этап процесса компиляции. На этом этапе символы, составляющие исходную программу, считываются и группируются в отдельные лексические элементы, называемые лексемами. Лексический анализ важен для процесса компиляции по следующим причинам: - замена в программе идентификаторов и констант лексемами делает представление программы удобнее для дальнейшей обработки; - уменьшается длина программы, т.к. из нее устраняются несущественные пробелы и комментарии. С точки зрения реализации процесса сканирования различают два подхода - прямой и непрямой лексический анализ. При прямом лексическом анализе требуется найти одну из многих лексем, которые заданы в описании данного языка.
Моделью прямого лексического анализатора служит множество работающих параллельно конечных автоматов (КА), каждый из которых распознает лексемы заданного типа. Эти КА можно представить и реализовать как один конечный преобразователь, моделирующий работу всех КА и выдающий сигнал о том, какой из них распознал очередную лексему.
При непрямом лексическом анализе требуется, прочитав цепочку символов, определить, образует ли эта цепочка лексему некоторого конкретного типа. В этом случае сканер работает вместе с синтаксическим анализатором, как некоторая программная процедура SCAN Синтаксический анализатор обращается к SCAN всякий раз, когда ему нужен новый символ при анализе текста программы и построения ее внутреннего представления. В ответ на вызов, SCAN распознает очередную лексему в исходной программе и передает ее анализатору через таблицу лексем.
Непрямой сканер более экономичен ( в смысле экономии памяти), т.к. он не создает полной таблицы лексем для всего исходного текста программы.
Большинство лексем в языках программирования могут быть описаны в виде регулярных выражений, а так же соответствующих регулярных грамматик. Для распознавания лексем, описываемых регулярными выражениями, можно использовать соответствующие КА.
Распознавание лексем выполняется следующим образом:
- входная цепочка считывается до тех пор, пока КА не достигнет заключительного состояния;
- по достижению заключительного состояния КА сигнализирует о нахождению лексемы данного типа и сканер заносит информацию о ней в таблицу имен (символов).
Таким образом, проблему построения непрямого лексического анализатора для данного типа лексем можно представить как проблему построения и реализации КА, который по достижению заключительного состояния, выдает на выходе лексему ( в этом смысле его можно рассматривать и как конечный преобразователь). В общем случае, такой КА является недетерминированным (НКА), однако, как отмечалось в п.2.4 ,НКА можно преобразовать в эквивалентный ему детерминированный КА.
Рассмотрим способы описания лексем.
Представление результатов сканирования
В процессе работы сканера должна быть сформирована таблица имен для хранения информации о лексемах. Эта информация используется в дальнейшем для двух целей.
Во-первых, с целью семантического контроля исходного текста программы. Например, если в программе есть оператор вида go to met,то компилятор должен проверить , что идентификатор met встречается в программе в качестве метки соответствующего оператора ( а не в другом качестве).
Во-вторых, информация в таблице имен используется при генерации кода. Например, если в программе есть оператор вида a:= b+c ,то генерируемый код для операции “+” будет зависеть от атрибутов идентификаторов b и c ( в частности, от типа a,b,c и т.п.)
Таким образом, после распознавания каждой лексемы, сканер должен занести в таблицу имен их характеристики (атрибуты). К этим атрибутам относятся: класс лексемы (обозначаемый обычно во внутреннем представлении целым числом), фактическое значение лексемы (фактическое символическое имя), дополнительная информация. Для внутреннего представления лексем может использоваться табл.4.3.
Класс лексемы |
Внутр-е представление |
Фактическое значение |
Не определен |
0 |
... |
Идентификатор |
1 |
... |
Целое число |
2 |
... |
Действительное число |
3 |
имена лексем |
Метки |
7 |
... |
и т.д. |
и т.д. |
... |
Дополнительная информация о лексеме обычно помещается в отдельную область памяти, на которую делается ссылка. Всякий раз, когда сканер распознает лексему, он проверяет в таблице имен, встречалась ли ранее такая же лексема. Если нет, то сканер заносит в таблицу имен значение этой лексемы вместе с соответствующей информацией. Если же лексема уже есть в некоторой ячейке n таблицы имен, то сканер вырабатывает на выходе пару (имя лексемы, n).
Таким образом, чтобы сконструировать эффективный компилятор, надо уметь по данному имени лексемы быстро определять, отведена ли для нее ячейка в таблице имен, вставлять при необходимости эту лексему, вычислять адреса ячеек в других таблицах, содержащих дополнительную информацию о каждой лексеме.
Методики конструирования сканеров
Методика 1. Эта методика состоит из пяти этапов, на каждом из которых решается одна из задач построения сканера:
1) описание лексем языка при помощи регулярных выражений;
2) преобразование полученных выражений в соответствующие НКА;
3) преобразование НКА в КА для тех лексем, где такое преобразование необходимо (для некоторых лексем соответствующие КА могут быть получены в результате выполнения 2-го этапа);
4) конструирование сканера из полученных КА, работающих последовательно - в случае прямого лексического анализа, или параллельно (по мере вызова) - в случае непрямого лексического анализа;
5) разработка таблицы имен (и других связанных с ней таблиц) и методов работы с таблицами.
Каждый из этих этапов рассмотрен в соответствующем разделе данной главы.
Методика 2. Если некоторые лексемы проще описать синтаксическими диаграммами, то можно воспользоваться соответствием, имеющим место между диаграммой, регулярной грамматикой и КА, о котором шла речь в гл.2. В этом случае первые три этапа методики 1 можно заменить следующими этапами: 1) описание лексем при помощи синтаксических диаграмм (диаграммы должны содержать только терминальные символы);
2) разметка диаграмм нетерминальными символами и получение соответствующих регулярных грамматик (см. п.4.6);
3) преобразование полученных грамматик в соответствующие КА.
Далее следует выполнить этапы 4 и 5 методики 1. Вообще говоря, применение методики2 не гарантирует получение детерминированного КА для любой лексемы.
4. Свойства КС-языков и грамматик. Эквивалентные преобразования КС- грамматик и их применение: устранение недостижимых символов, устранение бесполезных символов, устранение е-правил, устранение цепных правил, устранение левой рекурсии, факторизация.
***********-************----------------------------****************--------*******---------*********-
5. Классы лево- и право- анализируемых грамматик (перечислить). Отношения.
между классами КС-грамматик и языков. Общая характеристика моделей и
методов детерминированного синтаксического анализа. Модель левого LL(k) – анализатора. Алгоритмы построения управляющих таблиц LL(k) – анализатора