
- •Предисловие
- •Глава 1 введение в проблематику конструирования компиляторов
- •1.1. Понятие компилятора и его структура
- •1.2. Применение компиляторов и задачи их разработки
- •Глава 2 способы задания формальных языков
- •2.1. Математический аппарат теории
- •Формальных языков, перевода и компиляции
- •1) AR*a для всех aÎa;
- •2.2 Цепочки и языки
- •2.3 Грамматики
- •2.4. Распознаватели
- •2.5 Регулярные выражения и синтаксические диаграммы
- •2.6. Автоматы с магазинной памятью (мп - автоматы )
- •2.7. Соответствия между способами описания языков
- •Глава 3 основы теории перевода
- •3.1. Определение перевода
- •3.2. Модели простейших трансляторов
- •3.2.1. Конечные преобразователи
- •3.2.2. Преобразователи с магазинной памятью
- •Глава 4 конструирование сканеров
- •4.1. Общая характеристика процесса сканирования
- •4.2. Описание лексем в языке расширенных регулярных выражений
- •4.3. Построение недетерминированного конечного автомата по расширенному регулярному выражению
- •4.4. Преобразование недетерминированного конечного автомата в детерминированный
- •Замечание. Среди состояний могут оказаться недостижимые состояния . Состояние р называется достижимым , если существует такая цепочка w , что (q0, w) *(p , e ). ¨
- •4.5. Преобразование синтаксической диаграммы в конечный автомат
- •4.6. Представление результатов сканирования
- •4.7. Методики конструирования сканеров
- •Глава 5 конструирование однопроходных нисходящих анализаторов
- •5.1. Определение синтаксического разбора
- •5.2. Нисходящий и восходящий разборы
- •5.3. Ll(k) - грамматики
- •5.4. Предсказывающие алгоритмы разбора
- •5.5. Алгоритмы построения управляющих таблиц для левых анализаторов
- •5.6. Приведение грамматик к ll - форме
- •Глава 6 основы генерации кода
- •6.1. Перевод и генерация кода
- •6.2. Представления промежуточной программы
- •6.3. Преобразование промежуточной программы в ассемблерный код
4.2. Описание лексем в языке расширенных регулярных выражений
Цепочки символов, образующие лексемы языков программирования, почти всегда оказываются регулярными множествами и представимы в виде соответствующих регулярных выражений . Для некоторых из лексем представление их регулярными выражениями оказывается слишком громоздким. Для более компактного описания лексем обычно используют расширенные регулярные выражения .
Определение. Расширенные регулярные выражения и множества, которые они обозначают определяются рекурсивно следующим образом :
1. Если R - регулярное выражение, то оно является расширенным и будет обозначать множество R .
2. Если R - расширенное регулярное выражение , то:
а) R+ - расширенное регулярное выражение , обозначающее множество RR* (R+ = RR* ) ;
б) R*n
- расширенное регулярное выражение ,
обозначающее множество {e}
È
R È
RR È
... È
Rn
( или R*n
=
);
в)
R+n
- расширенное регулярное выражение ,
обозначающее множество
R È
RR È
... È
Rn
( или R+n
=
).
3. Если R1 и R2 - расширенные регулярные выражения , то R1 - R2 и R1ÇR2 - расширенные регулярные выражения, обозначающие следующие множества: R1 - R2 = { x / xÎR1 и xÏR2 }; R1ÇR2 = { x / xÎR1 и xÎR2 }.
4. Ничто другое не является расширенным регулярным выражением. ¨
Если требуется описать регулярные выражения , построенные из других регулярных выражений , то можно ввести регулярные определения , представляющие собой имена этих выражений . В этом случае алфавит регулярных выражений - å расширяется до
å È <множество имён регулярных выражений > . Этим достигается ещё большая компактность.
Пример 4.1. Пусть требуется описать идентификаторы и константы языка Фортран при помощи регулярных определений: 1. Описание идентификаторов: <буква> = A | B | ... | Z <цифра> = 0 | 1 | ... | 9 < идентификатор> = <буква> ( <буква> / <цифра>)*5
2. Описание констант: <цифра> = 0 | 1 | ... | 9 <знак> = + | - | e <целое> = <знак> <цифра>+ <десятичное> = <знак> ( <цифра>*. <цифра>+ | <цифра>+. <цифра>* ) <константа> = <целое> | <десятичное> | <десятичное> E <целое>
4.3. Построение недетерминированного конечного автомата по расширенному регулярному выражению
Рассмотрим теперь метод получения КА, распознающих лексемы языка, заданные регулярными выражениями. Такой метод изложен в [ 1 ] в форме соответствующего алгоритма. Назовём этот алгоритм А1 и приведём его описание .
Вход А1 : расширенное регулярное выражение R в алфавите å , не содержащее символа Æ и операций « Ç » « - ».
Выход А1 : недетерминированный КА (НКА) - М, для которого L(М)=R.
Описание А1: Получим автомат М0 такой, что L(М0)= R 0 , выполняя рекурсивно следующие действия:
1. Если R0=е, тогда М0=( {q} å , Æ, q, {q} ), где q - новое состояние;
2. Если R 0 =а, где aÎS , тогда М0= ( {q1,q2}, S,d0 , q1, {q2} ), где d0 (q1,a) = {q2}, в остальных случаях d0 не определена; q1 и q2- новые состояния;
3. Если R0=R1| R2, тогда применяем весь алгоритм к R1 и R2 и получаем соответственно М1= ( Q 1,S, d1, q1, F1 ) и
М2=( Q2 , S , d2, q2 , F2 ) , где Q1 и Q2 не пересекаются, а затем построим М0=(Q1ÈQ2 È{q0},S , d 0 ,q0 ,F0), где
а) q0-новый символ;
б) d0 включает d1 и d2, т.е. d0 (q0 ,a)= d1 (q1 ,a) Èd2 (q2 ,a);
в) F0=F1ÈF2 , если q1Ï F1 и q2 ÏF2 , в противном случае F0 =F1ÈF2 È{ q0 }.
4. Если R0=R1 R2 , то применим весь алгоритм к R1 и R2 и получим М1 и М2 , как в п.3 .Построим М0=(Q1 È Q2 , å, d0 , q1, F0 ) , где
а) d0 включает d2 ; d0 (q ,a)= d1 (q ,a) для всех q Î Q и a Î å , если q Ï F1, и d0 (q ,a)= d1 (q ,a) È d2 (q2 ,a) в противном случае;
б) F0=F2 , если q2 Ï F2 , и F0=F1 ÈF2 в противном случае.
5. Если R0=R1* , то применим весь алгоритм к R1 и получим М1=( Q1 ,å, d1 , q1 , F1).
Построим М0=( Q1 È {q0}, å, d0 , q0 , F1 È{q0}), где q0 - новый символ и d0 определяется соотношениями:
а) d0 (q0 ,a)=d1 (q1 , a);
б) если q Ï F1 , то d0 (q ,a)=d1 (q ,a);
в) если q Î F1 , то d0 (q ,a)=d1 (q,a) È d1 (q1 , a).
6. Если R0=R1+ , то применим весь алгоритм к R1 и получим М1, как в п.5. Построим М0=( Q1, å, d0 , q1 ,F1), где d0 (q,a)=d1(q,a), если q Ï F1 , и d0 (q ,a)=d1 (q ,a) Èd1 (q1 ,a), если q Î F1.
7. Если R0=R1*n, то применим весь алгоритм к R1 и получим М1 , как в п.5. Построим М0 =(Q1 ´{1,..., n}, å, d0 , [q1 ,1], F0), где
а) если q Ï F1 или i=n, то d0 ([q ,i], a )={[p , i] |d1 (q ,a) содержит p};
б) если q Î F1 и i<n, то d0 ( [ q , i ] , a)={ [p , i] | d1( q , a) содержит p}U{ [p ,i +1] | d1(q1 ,a) содержит p }
в) F0={ [q , i ] | q Î F1 , 1 £ i £ n } U { [q1 ,1] }.
8. Если R0=R1+n , выполним то же , что и в (7) , но пункт (7,в) заменим на F0={ [q , i ] | q Î F1 , 1£ i £ n }.
Пример 4.2. Пусть R = (0 | 1) , преобразуем его в НКА :
1. R можно представить как R = (R1 | R2) , где R1 = 0 , R2 .
2. Применяя п. 2 для R1 и R2 , получаем :
3. Применяя п. 3 к R = (R1 | R2), объединяем состояния автоматов М1 , М2 и получаем результирующий автомат М
Пример 4.3. Пусть R = (0 | 1)* , преобразуем его в НКА :
1. Используя результаты , полученные в примере 4.2, и применяя п.5 для R , получим автомат М:
2. Согласно п. 5 , объединяем q1 и q2 и получаем
Пример 4.4. Пусть R = (a | b) (a | b |0 | 1)* , выполним его преобразование в НКА :
1. Представим r как R = R1 R2 ,
где
R1
= (R3
| R4)
, R2
= (
)*
, R3
= a , R4
=
b ;
= (R5 | R6 | R7 | R8) , R5 = a , R6 = b , R7 = 0 , R8 = 1 ;
2. Автоматы , соответствующие выражениям R1 и R2 легко получить , используя результаты примеров 4.2 , 4.3. Для R1 получим
для R2
3. Применяем п. 4 к выражению R = R1 R2 и получаем результирующий автомат М:
Пример 4.5. Пусть R = (00 | 11)* , преобразуем его в НКА :
1. Представим R следующим образом :
-
R = R1* , R1 = R2 | R3
R2 = R4 R5 , R3 = R6 R7 ,
R4 = 0 , R5 = 0, R6 = 1 , R7 = 1
2. Для R2 и R3 применяем пп. 2 и 4 ( можно использовать результаты предыдущих примеров ) и получаем автоматы М2 и М3 :
3. Применяя п. 3 к R1 = R2 | R3 , получаем из М2 и М3 результирующий автомат М1 :
4. Применяя п. 5 к R = R1* , получаем из М1 автомат М
Для того, чтобы лучше усвоить и закрепить навыки преобразований, полученные в этих примерах, и использовать их в дальнейшем, приведём соответствия между некоторыми простыми регулярными выражениями и КА:
Рассмотрим теперь практический случай .
Пример 4.6. Построим НКА для регулярного определения, описывающего вещественные константы языка Фортран 77.
Построим вначале КА для отдельных регулярных выражений, входящих в регулярное определение , а затем получим результирующий КА .
1. <цифра>+ =( 0 | 1 | ... | 9) +
2. <знак> = + | - | e
3. <целое> = <знак> <цифра>+
4. <десятичная дробь> = <знак>. <цифра>+ |<целое>.<цифра>* Выражениям, расположенным слева и справа от знака | , соответствуют автоматы М4 и М5.:
Результирующий автомат М6 для выражения <десятичная дробь> имеет вид
5. Регулярное определение для вещественой константы:
<вещественная константа>=<десятичная дробь> |
<десятичная дробь> E<целое>|<целое>Е<целое>
Результирующий автомат М имеет вид