- •Теория автоматов и формальных языков
- •Введение
- •1 Нормативные ссылки
- •2 Требования к курсовой работе
- •3 Примерный перечень тем курсовых работ
- •4 Пример выполнения курсовой работы
- •5 Общие сведения о трансляции
- •6 Синтез транслятора
- •6.1 Лексический блок
- •6.2 Синтаксический блок
- •Список литературы
- •Приложение а
- •Приложение б
- •Приложение в
6 Синтез транслятора
6.1 Лексический блок
Входом транслятора служит набор двоичных символов (цепочка). Лексический блок предназначен для того, чтобы разбивать цепочку символов на слова, из которых она состоит. В общем виде работа лексического блока выглядит следующим образом:
1. Входная строка анализируется посимвольно до разделителя, которым могут быть или символ пробел, или символ конца строки.
2. Если лексема распознана (является ключевым словом или специальным символом), то она заносится в таблицу лексем, а иначе мы предполагаем, что данная лексема является идентификатором.
3. Если лексема не является идентификатором, то выдается сообщение об ошибке и работа программы прекращается.
6.2 Синтаксический блок
Этот блок переводит последовательность лексем, построенную лексическим блоком, в другую последовательность, которая более непосредственно отражает порядок, в котором должны выполняться операции в программе.
Для построения управляющей таблицы МПА необходимо нахождение множества ВЫБОР. Исходной для нахождения множества ВЫБОР принята грамматика арифметических выражений, дополненная оператором присваивания:
1. <S>→ <Tip>< iD >=< E >;
2. < E > → < T > <E-список>;
3. <E-список> → + < T > <E-список>;
4. <E-список> → ε;
5. < T > → < P > <T-список>;
6. <T-список> → * < P > <T-список>;
7. <T-список> → ε;
8. < P > → (< E >);
9. < P > → i;
10. <Tip > → int;
11. < iD > → i.
ШАГ 1 процедуры определяет аннулирующие нетерминалы и правила .
4. <E-список> → ε
7. <T-список> → ε
ШАГ 2 процедуры состоит в нахождении отношения, называемого НАЧИНАЕТСЯ ПРЯМО С (НПС).
Эти отношения определяются на множестве символов грамматики и означают, что если применив к нетерминалу <A> точно одно правило и, возможно, заменив в нем некоторые аннулирующие нетерминалы на ε , можно получить цепочку, начинающуюся, например, с <B>. В этом случае пишут <A>НПС<B>.
На рисунке 2 показан фрагмент полученных отношений.
ШАГ 3 процедуры – это вычисление отношения НАЧИНАЕТСЯ С (НС).
В общем случае матрица отношений НС определяется рефлексивно-транзитивным замыканием матрицы НПС. Признак рефлексивности определяется тем, что любой символ всегда начинается с самого себя (1 на главной диагонали). Транзитивные отношения характеризуются всеми возможными подстановками при осуществлении вывода.
Формальный алгоритм транзитивного замыкания включает в себя следующие шаги:
1) для каждого единичного элемента aij исходной матрицы в строку i дописать единичные элементы из строки j;
2) пункт 1 повторять сверху вниз и слева направо для всех элементов матрицы.
На рисунке 2 показан фрагмент полученного отношения.
Рисунок 2 – Фрагмент полученного отношения для шагов 1, 2, 3
ШАГ 4 вычисляет множество ПЕРВЫЙ.
Для каждой строки матрицы отношения НС – отмеченные столбцы, соответствующие терминальным символам. Они указывают терминалы, составляющие множество ПЕРВЫЙ для символа, которым помечена данная строка. Так, в нашем примере:
ПЕРВЫЙ (<S>) = { int}
ПЕРВЫЙ (<E>) = { (, i}
ПЕРВЫЙ (Tip) = { int } и.т.д.
ШАГ 5 – вычисление множества ПЕРВЫЙ для правой части каждого правила. Имея информацию, полученную на шаге 4, эти вычисления проделать очень просто.
ПЕРВЫЙ (1) = { int}
ПЕРВЫЙ (2) = { (, i }
ПЕРВЫЙ (3) = {int} и.т.д.
Рисунок 3 – Фрагмент полученного отношения
для шагов 4, 5, 6
ШАГ 6 – это построение отношения, нызываемого ПРЯМО - ПЕРЕД (ПП):
Эти отношения определяются следующим образом: мы пишем А ПП В тогда и только тогда, когда существуют правила вида: <D> → <A> <B> ,
<D> → <A> β <B> , где <А>, <В> - НТ символы, β – аннулирующая цепочка.
На рисунке 3 показан фрагмент полученного отношения.
ШАГ 7 – это построение отношения ПРЯМО-НА-КОНЦЕ (ПНК).
Отношение определяется следующим образом: если <А> и <В> – это символы грамматики, то <А> ПНК <В> тогда и только тогда, когда есть правила вида <B> →α <A>, <B> →α <A> β, где β – аннулирующая цепочка, α – произвольная цепочка. Это отношение является инверсией отношения НПС, если правую часть правила рассматривать "справа - налево".
На рисунке 4 показан фрагмент полученного отношения.
Рисунок 4 – Фрагмент полученного отношения
для шагов 7, 8
ШАГ 8 - построение отношения НА-КОНЦЕ (НК).
Отношение НК – это рефлексивно-транзитивное замыкание отношения ПНК.
ШАГ 9 – это вычисление отношения, называемого ПЕРЕД (П):
Мы пишем <А> П <В> тогда и только тогда, когда из начального символа можно вывести цепочку, в которой за вхождением <А> сразу же следует вхождение <В>. Можно записать без вывода, что отношение П является произведением отношений НК, ПП и НС. Это отношение также соответствует тем символам, которые находятся НА КОНЦЕ начального нетерминала для всех выводимых из него цепочек.
ШАГ 10 заключается в расширении отношения ПЕРЕД (П+) за счет включения в него концевого маркера (последний столбец).
Это отношение соответствует тем терминальным символам, которые находятся НА КОНЦЕ начального нетерминала для всех выводимых из него цепочек (первый столбец матрицы НК).
На рисунке 5 показан фрагмент полученных отношений для шагов 9 и 10.
Рисунок 5 – Фрагмент полученного отношения
для шагов 9, 10
ШАГ 11 – это вычисление множества СЛЕД для каждого аннулирующего нетерминала. Множество СЛЕД будет содержать все терминальные символы, для которых аннулирующие нетерминалы расположены ПЕРЕД.
Из рисунка 5 следует, что
СЛЕД(<Е-список>)={ ), L },а СЛЕД(<T-список>)={+, ), L}.
ШАГ 12 – вычисление множеств ВЫБОР, которые можно получить из уже вычисленных значений множеств ПЕРВЫЙ и СЛЕД.
Ниже показан фрагмент множества ВЫБОР, из которого видно, что множества ВЫБОР правил, имеющих одинаковые левые части, не пересекаются.
ВЫБОР(1) = ПЕРВ( <Tip>< iD >=< E > )={int};
ВЫБОР(2) = ПЕРВ( < T > <E-список>) = {I, ( };
ВЫБОР(3) = ПЕРВ(+< T > <E-список>) = {+};
ВЫБОР(4) = СЛЕД(<E-список>) = { ), ┤};
ВЫБОР(5) = ПЕРВ(< P > <T-список>) = { I, ( };
ВЫБОР(6) = ПЕРВ(* < P > <T-список>) = { * };
ВЫБОР(7) = СЛЕД(<T-список>) = {+, ), ┤};
ВЫБОР(8) = ПЕРВ((< E >)) = { ( };
ВЫБОР(9) = ПЕРВ( <P> ) = { i };
ВЫБОР(10) = ПЕРВ( <Tip> ) = { int };
ВЫБОР(11) = ПЕРВ( <iD> ) = { i }.
Грамматика, порождающая рассматриваемый язык, является LL(1)-грамматикой и для неё можно построить МП-распознаватель.
Управляющая таблица МПА представлена на рисунке 6, а ниже правила его работы.
|
int |
I |
+ |
* |
( |
) |
--| |
< S > |
1 |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
< E > |
ОТВ |
2 |
ОТВ |
ОТВ |
2 |
ОТВ |
ОТВ |
< T > |
ОТВ |
4 |
ОТВ |
ОТВ |
4 |
ОТВ |
ОТВ |
< P > |
ОТВ |
8 |
ОТВ |
ОТВ |
7 |
ОТВ |
ОТВ |
< E-спис> |
ОТВ |
ОТВ |
2 |
ОТВ |
ОТВ |
3 |
3 |
< T-спис>
|
ОТВ |
ОТВ |
6 |
5 |
ОТВ |
6 |
6 |
< Tip>
|
9 |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
) |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ВЫТОЛ.СДВ |
ОТВ |
|
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ОТВ |
ДОП |
Рисунок 6 – Управляющая таблица МПА
Процедуры обработки, содержащиеся в ячейках, имеют вид:
1 ЗАМЕНИТЬ <Tip>< iD >=< E > ), ДЕРЖАТЬ,
2 ЗАМЕНИТЬ (<E-список> < T >), ДЕРЖАТЬ,
3 ВЫТОЛКНУТЬ, ДЕРЖАТЬ,
4 ЗАМЕНИТЬ (<T-список> < P >), ДЕРЖАТЬ,
5 ЗАМЕНИТЬ (<T-список> < P >), СДВИГ,
6 ВЫТОЛКНУТЬ, ДЕРЖАТЬ,
7 ЗАМЕНИТЬ ( ) < E > ), СДВИГ ,
8 ВЫТОЛКНУТЬ. СДВИГ.
9 ВЫТОЛКНУТЬ. СДВИГ.
Работа синтаксического блока:
1. Начальное состояние магазина – нетерминал <S>.
2. Автомат считывает очередную лексему и верхний символ из магазина.
3. Автомат обращается к управляющей таблице по двум значениям и получает управляющее правило – выход таблицы.
4. Автомат действует согласно управляющему правилу.
Пример программы синтаксического анализатора арифметических выражений приведен в Приложении В.