- •Содержание
- •1 Формальные языки и грамматики
- •1.1 Основные понятия теории формальных языков
- •Определение Цепочка, которая не содержит ни одного символа, называется пустой цепочкой и обозначается .
- •1.2 Способы задания языков
- •1.2.1 Формальные грамматики
- •1.2.1.1 Определение формальной грамматики
- •Определение Цепочка (vtvn)* выводима из цепочки в грамматике(обозначается*), если существует последовательность цепочек (n0) такая, что .
- •1.2.1.3 Эквивалентность грамматик
- •1.2.2 Формы Бэкуса - Наура
- •1.2.3 Диаграммы Вирта
- •1.2.5 Механизмы распознавания языков
- •1.2.5.1 Определение распознавателя
- •1.2.5.2 Схема работы распознавателя
- •1.2.5.3 Классификация распознавателей
- •2 Регулярные грамматики и языки
- •2.1 Регулярные выражения
- •2.2 Лемма о разрастании языка
- •2.3 Конечные автоматы
- •2.3.1 Определение конечного автомата
- •2.3.2 Распознавание строк конечным автоматом
- •Существуют следующие способы представления функции переходов: - командный способ.Каждую команду ка записывают в форме , где.
- •2.3.3 Преобразование конечных автоматов
- •2.3.3.1 Преобразование конечного автомата к детерминированному виду
- •Алгоритм Преобразование нка в дка
- •2.3.3.2 Минимизация конечного автомата
- •2.3.3.2.1 Устранение недостижимых состояний ка
- •2.3.3.2.2 Объединение эквивалентных состояний ка Алгоритм Объединение эквивалентных состояний ка
- •2.4 Взаимосвязь способов определения грамматик
- •2.4.1 Построение ка по регулярной грамматике
- •Выход:ка.
- •3 Контекстно-свободные языки и грамматики
- •3.1 Задача разбора
- •3.1.1 Вывод цепочек
- •Определение Цепочка (vtvn)* выводима из цепочки в грамматике(обозначается*), если существует последовательность цепочек (n0) такая, что .
- •3.1.2 Дерево разбора
- •3.1.2.1 Нисходящее дерево разбора
- •3.1.2.2 Восходящее дерево разбора
- •3.1.3 Однозначность грамматик
- •3.2 Преобразование кс-грамматик
- •3.2.1 Проверка существования языка грамматики
- •3.2.2 Устранение недостижимых символов
- •Алгоритм Устранение нетерминалов, не порождающих терминальных строк Вход: кс-грамматика.
- •Алгоритм Устранение недостижимых символов Вход: кс-грамматика.
- •Определим множество достижимых символов z грамматики g, т.Е. Множество
- •3.2.3 Устранение -правил Алгоритм Устранение -правил Вход: кс-грамматика.
- •3.2.4 Устранение цепных правил Алгоритм Устранение цепных правил Вход: кс-грамматика.
- •3.2.5 Левая факторизация правил Алгоритм Устранение левой факторизации правил Вход: кс-грамматика.
- •3.2.6 Устранение прямой левой рекурсии Алгоритм Устранение прямой левой рекурсии Вход: кс-грамматика.
- •3.3 Автомат с магазинной памятью
- •3.3.1 Определение мп-автомата
- •3.3.2 Разновидности мп-автоматов
- •3.3.3 Взаимосвязь мп-автоматов и кс-грамматик
- •3.3.3.1 Построение мп-автомата по кс-грамматике
- •3.3.3.2 Построение расширенного мп-автомата по кс-грамматике
- •3.4 Нисходящие распознаватели языков
- •3.4.1 Рекурсивный спуск
- •3.4.1.1 Сущность метода
- •3.4.1.2 Достаточные условия применимости метода рекурсивного спуска
- •3.4.2 Распознаватели ll(k)-грамматик
- •3.4.2.1 Определение ll(k)-грамматики
- •3.4.2.2 Необходимое и достаточное условие ll(1)-грамматики
- •3.4.2.3 Построение множества first(1, a)
- •3.4.2.4 Построение множества follow(1, a)
- •3.4.2.5 Алгоритм «сдвиг-свертка» для ll(1)-грамматик
- •Шаг 6. Получили следующую цепочку вывода:
- •3.5.1.1.2 Поиск основы сентенции грамматики
- •3.5.1.1.3 Построение множеств l(a) и r(a)
- •3.5.1.1.5 Алгоритм «сдвиг - свертка» для грамматик простого предшествования
- •Шаг 3. Функционирование распознавателя для цепочки (((aa)a)a) показано в таблице 3.9.
- •3.5.1.2 Грамматика операторного предшествования
- •3.5.1.2.1 Определение грамматики операторного предшествования
- •3.5.1.2.2 Построение множеств Lt(a) и Rt(a)
- •3.5.1.2.4 Алгоритм «сдвиг-свертка» для грамматики операторного предшествования
- •3.5.2 Распознаватели lr(k)-грамматик
- •3.6 Соотношение классов кс-грамматик и кс-языков
- •3.6.1 Соотношение классов кс-грамматик
- •3.6.2 Соотношение классов кс-языков
- •4 Принципы построения языка
- •4.1 Лексика, синтаксис и семантика языка
- •4.2 Определение транслятора, компилятора, интерпретатора и ассемблера.
- •4.3 Общая схема работы компилятора
- •4.4 Лексический анализ
- •4.4.1 Задачи лексического анализа
- •4.4.2 Диаграмма состояний с действиями
- •4.4.3 Функция scanner
- •4.5 Синтаксический анализатор программы
- •4.5.1 Задача синтаксического анализатора
- •4.5.2 Нисходящий синтаксический анализ
- •Теорема Достаточные условия применимости метода рекурсивного спуска
- •4.6 Семантический анализ программы
- •4.6.1 Обработка описаний
- •4.6.2 Анализ выражений
- •4.6.3 Проверка правильности операторов
- •4.7 Генерация кода
- •4.7.1 Формы внутреннего представления программы
- •4.7.1.1 Тетрады
- •4.7.1.2 Триады
- •4.7.1.3 Синтаксические деревья
- •4.7.1.4 Польская инверсная запись
- •Составной оператор begin s1; s2;...; Sn end в полиЗе записывается как s1 s2... Sn.
- •4.7.1.5 Ассемблерный код и машинные команды
- •4.7.2 Преобразование дерева операций в код на языке ассемблера
- •4.8 Оптимизация кода
- •4.8.1 Сущность оптимизации кода
- •4.8.2 Критерии эффективности результирующей программы
- •4.8.3 Методы оптимизации кода
- •4.8.4 Оптимизация линейных участков программ
- •4.8.4.1 Свертка объектного кода
- •4.8.4.2 Исключение лишних операций
- •4.8.5 Оптимизация логических выражений
- •4.8.6 Оптимизация циклов
- •4.8.7 Оптимизация вызовов процедур и функций
- •4.8.9 Машинно-зависимые методы оптимизации
- •4.8.9.1 Распределение регистров процессора
- •4.8.9.2 Оптимизация кода для процессоров, допускающих распараллеливание вычислений
- •5 Формальные методы описания перевода
- •5.1 Синтаксически управляемый перевод
- •5.1.1 Схемы компиляции
- •5.1.4 Практическое применение су-схем
- •5.2 Транслирующие грамматики
- •5.2.1 Понятие т-грамматики
- •5.3 Атрибутные транслирующие грамматики
- •5.3.1 Синтезируемые и наследуемые атрибуты
- •5.3.2 Определение и свойства ат-грамматики
- •5.3.3 Формирование ат-грамматики
- •Решение
3.5.2 Распознаватели lr(k)-грамматик
Распознаватели LR(k)-грамматик основаны на построении дерева разбора снизу вверх и правостороннем выводе цепочек.
Определение КС-грамматика обладает свойством LR(k), k>0, если на каждом шаге вывода для однозначного решения вопроса о выполняемом действии в алгоритме «сдвиг-свертка» расширенному МП-автомату достаточно знать содержимое верхней части стека и рассмотреть первые k символов от текущего положения считывающей головки автомата во входной цепочке символов.
Определение Грамматика называется LR(k)-грамматикой, если она обладает свойством LR(k) для некоторого к>0.
Первая литера «L» обозначает порядок чтения входной цепочки символов: слева— направо. Вторая литера «R» происходит от слова «right» и означает, что в результате работы распознавателя получается правосторонний вывод.
Для того чтобы формально определить LR(k) свойство для КС-грамматик, введем понятие пополненной КС-грамматики.
Определение Грамматика G' является пополненной грамматикой, построенной на основании исходной грамматики G(VT,VN,P,S), если выполняются следующие условия:
1) грамматика G' совпадает с грамматикой G, если целевой символ S не встречается нигде в правых частях правил грамматики G;
2) грамматика G' строится как грамматика G(VT,VN{S’},P{S’→S},S’), если целевой символ S встречается в правой части хотя бы одного правила из множества Р в исходной грамматике G.
Понятие «пополненной грамматики» введено исключительно с той целью, чтобы в процессе работы алгоритма «сдвиг-свертка» выполнение свертки к целевому символу пополненной грамматики S' служило сигналом к завершению алгоритма (поскольку в пополненной грамматике символ S' в правых частях правил нигде не встречается).
Теперь рассмотрим формальное определение LR(k) свойства.
Если для произвольной КС-грамматики G в ее пополненной грамматике G1 для двух произвольных цепочек вывода из условий:
1) S' =>* αAω => aβω
2) S' =>* γВх => αβу
3) FIRST(k.ω) = FIRST(k.y)
следует, что αAω = γВх (то есть α = γ, А = В и ω = у), то доказано, что грамматика G обладает LR(k) свойством. Очевидно, что тогда и пополненная грамматика G' также обладает LR(k) свойством.
Распознаватель для LR(k)-грамматик функционирует на основе управляющей таблицы Т. Эта таблица состоит из двух частей, называемых «действия» и «переходы». По строкам таблицы распределены все цепочки символов на верхушке стека, которые могут приниматься во внимание в процессе работы распознавателя. По столбцам в части «действия» распределены все части входной цепочки символов длиной не более k (аванцепочки), которые могут следовать за считывающей головкой автомата в процессе выполнения разбора; а в части «переходы» — все терминальные и нетерминальные символы грамматики, которые могут появляться на верхушке стека автомата при выполнении действий (сдвигов или сверток).
Клетки управляющей таблицы Т в части «действия» содержат следующие данные:
«сдвиг» — если в данной ситуации требуется выполнение сдвига (переноса текущего символа из входной цепочки в стек);
«успех» — если возможна свертка к целевому символу грамматики S и разбор входной цепочки завершен;
целое число («свертка») — если возможно выполнение свертки (число обозначает номер правила грамматики, по которому должна выполняться свертка);
«ошибка» — во всех других ситуациях.
Действия, выполняемые распознавателем, можно вычислять всякий раз на основе состояния стека и текущей аванцепочки. Однако этого вычисления можно избежать, если после выполнения действия сразу же определять, какая строка таблицы Т будет использована для выбора следующего действия. Тогда эту строку можно поместить в стек вместе с очередным символом и выбирать затем в момент, когда она понадобится. Таким образом, автомат будет хранить в стеке не только символы алфавита, но и связанные с ними строки управляющей таблицы Т.
Клетки управляющей таблицы Т в части «переходы» как раз и служат для выяснения номера строки таблицы, которая будет использована для определения выполняемого действия на очередном шаге. Эти клетки содержат следующие данные:
целое число — номер строки таблицы Т;
«ошибка» — во всех других ситуациях.
Для удобства работы распознаватель LR(k)-грамматики использует также два специальных символа , и . Считается, что входная цепочка символов всегда начинается символом и завершается символом . Тогда в начальном состоянии работы распознавателя символ находится на верхушке стека, а считывающая головка обозревает первый символ входной цепочки. В конечном состоянии в стеке должны находиться символы S (целевой символ) и , а считывающая головка автомата должна обозревать символ .
Алгоритм функционирования распознавателя LR(k)-грамматики можно описать следующим образом:
Шаг 1. Поместить в стек символ и начальную (нулевую) строку управляющей таблицы Т. В конец входной цепочки поместить символ . Перейти к шагу 2.
Шаг 2. Прочитать с вершины стека строку управляющей таблицы Т. Выбрать из этой строки часть «действие» в соответствии с аванцепочкой, обозреваемой считывающей головкой автомата. Перейти к шагу 3.
Шаг 3. В соответствии с типом действия выполнить выбор из четырех вариантов:
«сдвиг» — если входная цепочка не прочитана до конца, прочитать и запомнить как «новый символ» очередной символ из входной цепочки, сдвинуть считывающую головку на одну позицию вправо, иначе прервать выполнение алгоритма и сообщить об ошибке;
целое число {«свертка») - выбрать правило в соответствии с номером, удалить из стека цепочку символов, составляющую правую часть выбранного правила, взять символ из левой части правила и запомнить его как «новый символ»;
«ошибка» — прервать выполнение алгоритма, сообщить об ошибке;
«успех» — выполнить свертку к целевому символу S, прервать выполнение алгоритма, сообщить об успешном разборе входной цепочки символов, если входная цепочка прочитана до конца, иначе сообщить об ошибке.
Конец выбора. Перейти к шагу 4.
Шаг 4. Прочитать с вершины стека строку управляющей таблицы Т. Выбрать из этой строки часть «переход» в соответствии с символом, который был запомнен как «новый символ» на предыдущем шаге. Перейти к шагу 5.
Шаг 5. Если часть «переход» содержит вариант «ошибка», тогда прервать выполнение алгоритма и сообщить об ошибке, иначе (если там содержится номер строки управляющей таблицы Т) положить в стек «новый символ» и строку таблицы Т с выбранным номером. Вернуться к шагу 2.
Рассмотрим примеры применения конкретных управляющих таблиц.
Пример Распознаватель для грамматики LR(0)
При k=0 распознающий расширенный МП-автомат совсем не принимает во внимание текущий символ, обозреваемый его считывающей головкой. Решение о выполняемом действии принимается только на основании содержимого стека автомата. При этом не должно возникать конфликтов между выполняемым действием (сдвиг или свертка), а также между различными вариантами при выполнении свертки.
Управляющая таблица для LR(0)-грамматики строится на основании понятия «левых контекстов» для нетерминальных символов: очевидно, что после выполнения свертки для нетерминального символа А в стеке МП-автомата ниже этого символа будут располагаться только те символы, которые могут встречаться в цепочке вывода слева от А. Эти символы и составляют «левый контекст» для А. Поскольку выбор между сдвигом или сверткой, а также между типом свертки в LR(0)-грамматиках выполняется только на основании содержимого стека, то LR(0)-грамматика должна допускать однозначный выбор на основе левого контекста для каждого символа.
Рассмотрим простую КС-грамматику G({a,b}, {S}, {S→aSS|b}, S). Пополненная грамматика для нее будет иметь вид G ({a,b}, {S, S’}, {S' →S, S→aSS|b}, S’). Эта грамматика является LR(0)-грамматикой. Управляющая таблица для нее приведена в табл. 3.13
Таблица 3.13 Управляющая таблица для LR(0)-грамматики
Стек |
Действие |
Переход | ||
S |
a |
b | ||
|
Сдвиг |
1 |
2 |
3 |
S |
Успех, 1 |
|
|
|
a |
Сдвиг |
4 |
2 |
3 |
b |
Свертка, 3 |
|
|
|
aS |
Сдвиг |
5 |
2 |
3 |
aSS |
Свертка, 2 |
|
|
|
Колонка «Стек», присутствующая в таблице, в принципе не нужна для распознавателя. Она введена исключительно для пояснения каждого состояния стека автомата. Пустые клетки в таблице соответствуют состоянию «ошибка». Правила в грамматике пронумерованы от 1 до 3 (при этом будем считать, что состоянию «успех» — свертке к нулевому символу — в пополненной грамматике всегда соответствует первое правило). Распознаватель работает, невзирая на текущий символ, обозреваемый считывающей головкой расширенного МП-автомата, поэтому колонка «Действие» в таблице имеет только один столбец, не помеченный никаким символом, — указанное в ней данное действие выполняется всегда для каждой строки таблицы.
Конфигурацию расширенного МП-автомата будем отображать в виде трех компонентов: не прочитанная еще часть входной цепочки символов, содержимое стека МП-автомата, последовательность номеров примененных правил грамматики (поскольку автомат имеет только одно состояние, его можно не учитывать). В стеке МП-автомата вместе с помещенными туда символами показаны и номера строк управляющей таблицы, соответствующие этим символам в формате {символ, номер строки}.
Разбор цепочки aabbb.
1 (aabbb, {,0}, ε)
2 (abbb, {,0}{а,2}, ε)
3 (bbb, {,0}{а,2}{а,2}, ε)
4 (bb, {,0}{a,2}{a,2}{b,3}, ε)
5 (bb, {,0}{a,2}{a,2}{S,4}, 3)
6 (b, {,0}{a,2}{a,2}{S,4}{b,3}, 3)
7 (b, {,0}{a,2}{a,2}{S,4}{S,5}, 3,3)
8 (b, {,0}{a,2}{S,4}, 3,3,2)
9 (, {,0}{a,2}{S,4}{b,3}, 3,3,2)
10 (, {,0}{a,2}{S,4}{S,5}, 3,3,2,3)
11 (, { ,0}{S,l}, 3,3,2,3,2)
12 (, {,0}{S',*}, 3,3,2,3,2,1) - разбор завершен.
Соответствующая цепочка вывода будет иметь вид (используется правосторонний вывод): S’ => S => aSS => aSb => aaSSb => aaSbb => aabbb.
Пример Распознаватель для грамматики LR(1)
Рассмотрим простую КС-грамматику G({а,b}, {S}, {S→SaSb|ε}, S). Пополненная грамматика для нее будет иметь вид G({a,b}, {S, S1}, {S'→S, S→SaSb|ε}. S'). Эта грамматика является LR(1)-грамматикой. Управляющая таблица для нее приведена в табл. 3.14
Таблица 3.14 Управляющая таблица для LR(1)-грамматики
Стек |
Действие |
Переход | ||||
a |
b |
|
a |
b |
S | |
|
свертка, 3 |
|
свертка, 3 |
|
|
1 |
S |
сдвиг |
|
успех,1 |
2 |
|
|
Sa |
свертка, 3 |
свертка, 3 |
|
|
|
3 |
SaS |
сдвиг |
сдвиг |
|
4 |
5 |
|
SaSa |
свертка, 3 |
свертка, 3 |
|
|
|
6 |
SaSb |
свертка, 2 |
|
свертка, 2 |
|
|
|
SaSaS |
сдвиг |
сдвиг |
|
4 |
7 |
|
SaSaSb |
свертка, 2 |
свертка, 2 |
|
|
|
|
Разбор цепочки abababb.
1 (abababb, {,0}, ε)
2 (abababb, {,0}{S,1}, 3)
3 (bababb, {,0}{S,l}{a,2}, 3)
4 (bababb, {,0}{S,l}{a,2}{S3h 3,3)
5 (ababb, {,0}{S,l}{a,2}{S,3}{b,5}, 3,3)
6 (ababb, {,0}{S,1}, 3,3,2)
7 (babb, {,0}{S,l}{a,2}, 3,3,2)
8 (babb, {,0}{S,l}{a,2}{S,3}, 3,3,2,3)
9 (abb, {,0}{S,l}{a,2}{S,3}{b,5}, 3,3,2,3)
10 (abb, {,0}{S,l}, 3,3,2,3,2)
11 (bb, {,0}{S,l}{a,2}, 3,3,2,3,2)
12 (bb, {,0}{S,l}{a,2}{S,3}, 3,3,2,3,2,3)
13 (b, {,0}{S,l}{a,2}{S,3}{b,5}, 3,3,2,3,2,3)
14 Ошибка, нет данных для «b» в строке 5.
На практике LR (k)-грамматики при k > 1 не применяются. На это имеются две причины. Во-первых, управляющая таблица дляLR(k)-грамматики приk> 1 будет содержать очень большое число состояний, и распознаватель будет достаточно сложным и не столь эффективным. Во-вторых, для любого языка, определяемогоLR(k)-грамматикой, существуетLR(1)-грамматика, определяющая тот же язык. То есть для любойLR(k)-грамматики сk> 1 всегда существует эквивалентная ей LR(1)-грамматика. Более того, для любого детерминированного КС-языка существуетLR(1)-грамматика (другое дело, что далеко не всегда такую грамматику можно легко построить).