- •1. Формальные языки и грамматики
- •1.1. Введение
- •1.1.1. Трансляторы , интерпретаторы и компиляторы
- •1.1.2. Стадии работы компилятора
- •1.1.3. Построение компилятора
- •1.2.2. Примеры, иллюстрирующие первичные понятия
- •1.2.3. Пустой язык
- •1.2.4. Резюме
- •1.3. Типы формальных языков и грамматик
- •1.3.1. Грамматики типа 0
- •1.3.2. Грамматики типа 1
- •1.3.3. Грамматики типа 2
- •1.3.4. Грамматики типа 3
- •1.3.5. Вывод в кс-грамматиках и правила построения дерева вывода
- •1.3.6. Синтаксический разбор
- •1.3.7. Левый и правый выводы
- •1.3.8. Неоднозначные и эквивалентные грамматики
- •1.3.9. Резюме
- •1.4. Способы задания схем грамматик
- •1.4.1. Форма Наура-Бэкуса
- •1.4.2. Итерационная форма
- •1.4.3. Синтаксические диаграммы
- •1.4.4. Резюме
- •1.5. Построение грамматик и грамматики, описывающие основные конструкции языков программирования
- •1.5.1. Рекомендации по построению грамматик
- •1.5.2. Описание списков
- •1.5.3. Пример построения грамматик
- •1.5.4. Грамматики, описывающие целые числа без знака и идентификаторы
- •1.5.5. Грамматики для арифметических выражений
- •1.5.6. Грамматика для описаний
- •1.5.7. Грамматика, задающая последовательность операторов присваивания
- •1.5.8. Грамматики, описывающие условные операторы и операторы цикла
- •1.5.9. Резюме
- •2. Контекстно-свободные грамматики и автоматы.
- •2.1 Приведенные грамматики.
- •2.2 Определение непроизводящих символов.
- •2.3 Определения недостижимых символов.
- •2.5 Исключение леворекурсивных правил.
- •2.6 Исключение цепных правил.
- •2.7 Преобразование неукорачивающих грамматик.
- •2.8 Магазинные автоматы.
- •2.9 Работа магазинного автомата.
- •2.10. Язык, допускаемый магазинным автоматом.
- •2.11 Построение магазинного автомата.
- •2.12 Пример построения автомата.
- •2.13 Резюме.
- •3. Нисходящие распознаватели.
- •3.1 Распознаватели и ll(k) - грамматики
- •3.3 Построение детерминированного нисходящего распознавателя.
- •3.4 Множество выбора.
- •3.4.1 Функции перв, след и множество выбор.
- •3.4.4 Построение множества выбор.
- •3.5 Слаборазделенные грамматики
- •3.6 Ll(1) - грамматики.
- •3.7 Построение магазинного автомата.
- •3.8 Преобразование грамматик к виду ll(1).
- •3.8.1 Исключение леворекурсивных правил.
- •3.8.2 Выделение общих частей.
- •3.9. Резюме.
- •3.11. Восходящие распознаватели.
- •3.11.1. Расширенный магазинный автомат
- •3.11.2. Пример работы расширенного магазинный автомат
- •3.12. Lr(k)-грамматики
- •3.12.1. Построение таблиц распознавателя. Алгоритм работы распознавателя.
- •3.12.2. Пример построения lr(0)-распознавателя
- •3.13. Построение slr(1)-распознавателя
- •3.14. Восходящие распознаватели для грамматик с аннулирующими правилами
- •3.15. Резюме.
- •4.3. Магазинные Преобразователи.
- •4.3.1. Определение магазинного преобразователя.
- •4.3.2. Описание работы магазинного преобразователя.
- •4.3.3. Перевод определяемый преобразователем.
- •4.3.4. Построение преобразователя.
- •4.3.5. Пример построения преобразователя.
- •4.3.6. Порядок построения детерминированного магазинного преобразователя.
- •5. Атрибутные транслирующие грамматики
- •5.1. Атрибутные транслирующие грамматики.
- •5.1.1. Атрибутные транслирующие грамматики.
- •5.1.2. Определение ат-грамматик
- •5.1.3. Пример ат-грамматики
- •5.1.4. Демонстрация вычисления значений атрибутов с левым выводом
- •5.1.5. Пример использования ат-грамматики
- •5.2. Cинтаксический анализ, с использованием ат-грамматики
- •5.2.1. Процесс синтаксического анализа
- •5.2.2. Пример использования ат-грамматики.
- •5.3.2. Форма простого присваивания ат-грамматик
- •5.3.3. Преобразование lат-грамматики в lат-грамматику в форме простого присваивания.
- •5.3.4. Расширенный вывод для ат-грамматики
- •5.4. Атрибутные преобразователи ( ап )
- •5.4.1. Представление правил lat-грамматики в магазине.
- •5.4.2. Построение инструкций ап.
- •5.4.3. Описание работы ап
- •5.4.4. Порядок построения ап
- •5.4.5. Пример построения ап
- •5.4.6. Демонстрация работы ап
- •5.4.7. Построение восходящих атрибутных преобразователей
- •9.1 Структурный синтез синхронных автоматов .
- •9.1.1.1 Обобщенная структурная схема автомата.
- •9.1.1.3 Структурная схема на элементах импульсного типа.
- •9.1.2 Основные этапы структурного синтеза.
- •9.1.3 Типы элементов памяти.
- •9.1.4 Построение функций возбуждения.
- •9.1.5 Примеры структурного синтеза.
- •9.1.5.1 Пример 1
- •9.1.6 Кодрование состояний с использованием соседей первого и второго рода.
- •9.1.7 Кодирование с числом элементов памяти, равным числу состояний .
- •9.1.8 Структурные схемы с дешифратором.
- •9.1.10 Структурные схемы, использующие типовые блоки цифровых устройств.
- •9.1.10.1 Структурная схема с запоминанием входного слова.
- •9.1.10.2 Структурная схема на основе счетчика.
- •9.1.10.3 Структурная схема на основе регистра со сдвигом.
- •9. Асинхронные автоматы
- •9.2 Общие положения.
- •9.2.1. Описание работы асинхронного автомата
- •9.2.2. Состязание элементов памяти
- •9.2.3.1 Универсальный способ кодирования
- •9.2.3.2. Эвристический способ кодирования
- •9.2.4. Связь асинхронного автомата с внешней средой
- •9.2.5. Построение элементов памяти
- •9.2.5.1. Асинхронный триггер
- •9.2.5.2. Асинхронный s-триггер
- •9.2.5.3. Триггеры с синхронизацией
- •9.2.6. Триггеры с задержкой
- •9.2.6.2 Асинхронный триггер j-k с задержкой
- •9.2.6.3. Триггер j-k с задержкой и синхронизацией
- •9.2.6.4. Триггер d-V с задержкой и синхронизацией
- •9.2.7. Резюме
3.12. Lr(k)-грамматики
Детерминированные восходящие распознаватели, так же как и нисходящие, могут быть построены не для всякой КС-грамматики, а только для определенных подклассов таких грамматик. Наиболее широким подклассом КС-грамматик являютсяLR(k)-грамматики. Эти грамматики обеспечивают распознавание цепочки при просмотре слева направо, об этом говорит буква L (Left) в названии грамматики, и позволяют выполнить правостороннее сворачивание, это показывает буква R (Right) в названии. Параметрkговорит о том, что для определения того правила грамматики, которое нужно применить для сворачивания цепочки, потребуется просмотреть не болееkеще не прочитанных символов входной цепочки. В общем случае алгоритмы построения распознавателей дл LR(k)-грамматик оказываются достаточно сложными и трудоемкими, поэтому на практике чаще всего используют подклассы LR(k)-грамматик: LR(0), илиSLR(1)—простые (Simple) LR(1)-грамматики, позволяющие относительно просто выполнять построение восходящих распознавателей. При этом для каждого подкласса LR(k)-грамматик используется свой алгоритм построения. Если задана КС-грамматика, то определить ее принадлежность к одному из подклассов грамматик LR(k) можно только путем анализа возможности построения для нее с помощью определенного алгоритма детерминированного распознавателя. Учитывая последнее обстоятельство, условимся называть распознаватели по подклассу соответствующих грамматик: LR(0)-распознаватель или SLR(1)-распознаватель. Прежде чем перейти к рассмотрению правил построения восходящих распознавателей, введем несколько вспомогательных понятий. Условимся называть символы полного словаря грамматикиграмматическими символами. Каждый грамматический символ может входить в разные правила грамматики и, более того, появляться в одном и том же правиле несколько раз. При этом положение символа в правиле грамматики может показывать, какое действие нужно выполнить: перенос или свертку, а также какие грамматические символы могут за ним следовать. Это обстоятельство позволяет связать позицию грамматического символа в правиле грамматики с понятием состояния распознавателя. Для удобства дальнейших рассуждений введем понятиеграмматического вхождения.
Определение.Грамматическое вхождение символа грамматики задается номером правила и номером позиции, которая указывает место символа в правой части правила, полагая, что самый левый символ правой части правила является первым. |
Условимся обозначать грамматические вхождения символов, входящих в правую часть правила только один раз, с помощью одного индекса, равного номеру правила. Примем также, что каждая грамматика содержит грамматическое вхождение, называемое начальным вхождением.Это вхождение задается начальным символом грамматики.
3.12.1. Построение таблиц распознавателя. Алгоритм работы распознавателя.
Для грамматических вхождений определим две функции ВПЕРВиВПОСЛЕ.ФункцияВПЕРВпо аналогии с функциейПЕРВ(Y)определяет множество грамматических вхождений, которые могут стоять на первом месте в цепочках, выводимых изY. Это множество строится следующим образом: в него входит символYи все символы, начинающие промежуточные цепочки, выводимые изYбез применения аннулирующих правил. Формально вторая часть утверждения означает, чтоX ВПЕРВ(Y), если
Y * <L>bXab
и Xявляется самым левым вхождением в правой части правила<L> Xa.
В качестве примера построим функции ВПЕРВдля символов следующей грамматики, не содержащей аннулирующих правил:
Г3. 13:<I> a1<I12><I13>b1<I> с2
Эти функции имеют следующий вид:
ВПЕРВ(a1) = {a1},
ВПЕРВ(<I12>) = {<I12>, a1, с2},
ВПЕРВ(<I13>) = {<I13>, a1, с2},
ВПЕРВ(b1) = {b1},
ВПЕРВ(<C2>) = {с2},
ВПЕРВ(<I0>) = {<I0>, a1, с2}.
Функция ВПОСЛЕ(Y)является аналогом функцииСЛЕД. Она определяет множество грамматических вхождений, которые могут встречаться непосредственно после Y в цепочках, выводимых из начального символа грамматики. Правило вычисления функцииВПОСЛЕ(Y)можно записать так: если в правой части некоторого правила послеYнепосредственно следуетZ, то
ВПОСЛЕ(Y) = ВПЕРВ(Z).
При построении распознавателей необходимо учитывать наличие маркера дна, поэтому, забегая вперед, сформулируем еще одно правило вычисления этой функции: если Yявляется маркером дна магазина, то
ВПОСЛЕ(h0) = ВПЕРВ(<I0>),
где <I0>—начальное вхождение.
Для грамматики Г3. 12функцииВПОСЛЕимеют вид
ВПОСЛЕ(a1) = {<I12>, a1, с2},
ВПОСЛЕ(<I12>) = {<I13>, a1, с2},
ВПОСЛЕ(<I13>) = {b1},
ВПОСЛЕ(b1) =,
ВПОСЛЕ(<C2>) =,
ВПОСЛЕ(<I0>) =,
ВПОСЛЕ(h0) = {<I0>, a1, с2}.
Согласно определению функции ВПОСЛЕ(Y)она определяет грамматические вхождения, которые могут следовать после вхожденияYв выводимых или сворачиваемых цепочках. Например, если очередным грамматическим вхождением является символ a1 и за ним должен следовать грамматический символ I, то по значению функции ВПОСЛЕ( a1) можно определить, что символу I в этом случае соответствует вхождение I12. Таким образом, при сворачивании с помощью функцииВПОСЛЕ(Y)можно определить, какому грамматическому вхождению соответствует очередной грамматический символ сворачиваемой цепочки. Если взять последовательность грамматических символов, то пользуясь функциями ВПОСЛЕ ей можно поставить в соответствие последовательность грамматических вхождений. В этом случае удобно рассматривать грамматические вхождения, как состояни конечного автомата, а грамматические символы, как входные воздействия. Смену состояний этого автомата можно представить в виде таблицы переходов, которая строится следующим образом. Каждому грамматическому вхождению выделим одну строку таблицы, а каждому грамматическому символу—один столбец. Клетки таблицы заполняются элементами функцийВПОСЛЕMтаким образом, что элементXk ВПОСЛЕ(Yj)заносится в клетку, находящуюся на пересечении строкиYjи столбца, отмеченного грамматическим символомX.
Таблица переходов распознавателя, построенная для рассматриваемой грамматики, имеет вид:
Таблица 3.1 | ||||
|
a |
b |
<C> |
<I> |
a1 |
a1 |
|
<C2> |
<I12> |
<I12> |
a1 |
|
<C2> |
<I13> |
<I13> |
|
b1 |
|
|
b1 |
|
|
|
|
<C2> |
|
|
|
|
h0 |
a1 |
|
<C2> |
<I0> |
<I0> |
|
|
|
|
Эта таблица задает функцию
f( Bij, X ) = Xkl, которая для текущего грамматического вхождения Bijи очередного символа грамматики X определяет грпмматическое вхождение очередного символа Xkl. Следует отметить, что при построении таблицы переходов в клетках таблицы могут оказаться по несколько грамматических вхождений соответствующих символов. Такая таблица является недетерминированной, и ее нужно преобразовать в детерминированную таблицу с помощью приемов, использованных для преобразования таблиц конечных автоматов. В результате может получиться таблица, у которой строки отмечены множествами грамматических вхождений.
Построенная таблица переходов описывает смену состояний распознавателя, но она никак не отражет в каких случаея распознаватель должен выполнять действияпереносапрочитанных символов в магазин исворачивания. Если для хранения промежуточных цепочек, полученных в процессе сворачивания, использовать магазин, то таблица переходов может быть использована для определения грамматических вхождений, записываемых в магазин. Для описания порядка действий магазинного распознавателя построим еще одну таблицу. В этой таблице обозначим действие переноса символов из входной цепочки в магазин символом П (Перенос), а действия, связанные со сворачивание цепочек, соответствующих правым частям правил, обозначаим символом С(К), где К—номер использованного правила. Для обозначения действий, осуществляющих передачу на выход результатов работы распознавателя, условимся использовать начальные буквы слов Допустить (Д) и Отвергнуть (О). Учитывая, что действия преобразователя зависят как от символов входной цепочки, так и от символов, находящихся в магазине, обозначим строки таблицы грамматическими вхождениями, а столбцы - терминальными символами грамматики и символом конца цепочкиОснованием для заполнения таблицы являются следующие два положения: 1. Операция сворачивания должна выполняться независимо от входного символа всегда, если в вершине магазина находится самое правое грамматическое вхождение некоторого правила. Для таких грамматических вхождений значением функции ВПОСЛЕ является пустое множество. 2. Если в вершине магазина находится грамматическое вхождение, не являющиеся самым правым вхождением какого-либо правила, то следует выполнить перенос очередного символа входной цепочки в магазин. Следуя эти положениям и учитывая, что прцесс распознавания заканчивается успешно при обнаружении символана входе и символа Iов магазине, и что в оставшихся случаях входная цепочка должна быть отвергнута, получаем таблицу действий в следующем виде:
Таблица 3.2 | ||||
|
a |
b |
<C> |
|
a1 |
П |
П |
П |
О |
<I12> |
П |
П |
П |
О |
<I13> |
П |
П |
П |
О |
b1 |
С(1) |
С(1) |
С(1) |
С(1) |
<C2> |
С(2) |
С(2) |
С(2) |
С(2) |
h0 |
П |
П |
П |
О |
<I0> |
О |
О |
О |
Д |
Эта таблица задает функцию действий f ( Bi j, x ) ( - { Д, О, С (1), С (2), ..., С (N) }, где N - число правил заданной грамматики, которая определяет какое действие должен выполнить распознаватель, находящийся в состоянии Bi jи прочитавший выходной символ x. Для рассматриваемого примера операции свертки определяются следующим образом: C (1) = { a1<I12><I13>b1| => I0}, C (2) = { c2| => I0}. Последняя таблица, которую иногда называют управляющей таблицей распознавателя, и таблица состояний полностью задают работу распознавателя. Алгоритм работы, использующий таблицу состояний и таблицу действий можно описать так:
Прочитать очередной символ входной цепочки—x.
Прочитать символ состояния, находящийся в вершине магазина—YK1.
Прочитать значение элемента таблицы действий, находящегося в строкеYK1и столбце x.
Если прочитанное значение есть 0 или D, то работу следует закончить, поскольку результат получен.
Если прочитанное значение определяет операцию, результатом которой является грамматический символZ, то прочитать в таблице состояний элемент Zi j, находящийся в строкеYK1и столбцеZ. ЗаписатьYK1и прочитанный символ Zi jв магазин и выполнять п.1.
Используя описанный алгоритм, работу распознавателя, заданного таблицами 7.1 и 7.2, можно представить в виде последовательности конфигураций:
Магазин |
Вход |
Действие |
1. h0 |
aaccbcb |
П |
2. h0a1 |
accbcb |
П |
3. h0a1a1 |
ccbcb |
П |
4. h0a1a1c2 |
cbcb |
С(2) |
5. h0a1a1<I12> |
cbcb |
П |
6. h0a1a2<I12>c2 |
bcb |
С(2) |
7. h0a1a2<I12><I13> |
bcb |
П |
8. h0a1a2<I12><I13>b1 |
cb |
С(1) |
9. h0a1<I12> |
cb |
П |
10. h0a1<I12>c2 |
b |
С(2) |
11. h0a1<I12><I13> |
b |
П |
12. h0a1<I12><I13>b1 |
|
С(1) |
13. h0I0 |
|
Д |
В общем случае процедуру построения восходящего распознавателя по заданной грамматике, не содержащей аннулирующих правил, можно описать следующим образом:
Вычислить для данной грамматики функции ВПЕРВиВПОСЛЕ.
Построить недетерминированную таблицу, имеющую по одному столбцу для каждого грамматического символа и по одной строке для каждого грамматического вхождения и маркера дна. Элемент в строкеRjи столбцеСдолжен содержать все грамматические вхожденияCK, такие, чтоCK ВПОСЛЕ(Rj).
Если таблица, построенная на шаге 2, получается недетерминированной, то нужно преобразовать эту таблицу в детерминированную, рассматривая ее как недетерминированную таблицу переходов конечного автомата с начальным состоянием ho.
Состояния, полученные на шаге 3 (кроме состояния, соответствующего пустому множеству), следует использовать в качестве магазинных символов. Полученная таблица переходов может содержать переходы в пустое множество. Такие элементы следует понимать как запрещенные и рассматривать переходы в них как ошибки.
Таблица действий заполняется строка за строкой согласно множествам грамматических вхождений, помечающих строки, следующим образом:
-
а.
Если строка отмечена начальным вхождением I0, то в столбец, соответствующий маркеру конца строки, заносится операция Допустить, а во все остальные строки - операция Отвергнуть.
б.
Если строка отмечена грамматическим вхождением, являющимся самым правым вхождением в правиле с номером k, то во все элементы строки помещается операция Cвертка(k).
в.
Если строка отмечена маркером дна h0или если все грамматические вхождения, входящие во множество, помечающее строку, не являются самыми правыми в своих правилах, то в столбец, отмеченный концевым маркером строки, заносится операция Отвергнуть, а во все остальные столбцы — операция Перенос.
г.
Если множество, помечающее строку после преобразования НКА, содержит начальное вхождение и хотя бы одно вхождение, отличное от начального, но не содержит ни одного самого правого вхождения, то в столбец, помеченный символом конца строки, нужно поместить операцию Допустить, а в остальные столбцы — Перенос.
Приведенная процедура обеспечивает построение распознавателя, только если заданная грамматика принадлежит подклассу LR(0), поскольку действия в каждой строке управляющей таблицы одинаковы, то есть не зависят от входного символа. Если же в процессе построения обнаруживается, что хотя бы один из пунктов (а), (б), (в) или (г) выполнить нельзя, то это означает, что для заданной грамматики нельзя построить LR(0)-распознаватель и что она не является LR(0)-грамматикой.