
- •Семестр 1. Операционные системы
- •Введение
- •История развития ОС
- •Классификация ресурсов
- •Понятие операционной системы
- •Понятие процесса и потока
- •Дескриптор процесса
- •Диспетчеризация процессов
- •Механизмы взаимного исключения
- •Алгоритм Деккера
- •Типовые механизмы синхронизации
- •Поддержка механизмов синхронизации в UNIX
- •Механизмы межпроцессного взаимодействия
- •Барьеры
- •Обработка тупиковых ситуаций
- •Предотвращение взаимоблокировок
- •Управление памятью
- •Инвертированные таблицы страниц
- •Алгоритмы замещения страниц
- •Подсистемы ввода-вывода
- •Загрузка ОС
- •Загрузка ОС
- •Понятие файловой системы
- •Реализация каталогов
- •Совместно используемые файлы
- •Непротиворечивость файловой системы
- •Реализации файловых систем
- •HPFS
- •NTFS
- •Семестр 2. Теория компиляторов
- •Современные системы программирования
- •Литература
- •Формальные языки и грамматики
- •Форма Бэкуса-Наура
- •Классификация грамматик
- •Лексический анализ и регулярные грамматики
- •Лексический анализ
- •Конечные автоматы
- •Минимизация КА
- •КС-грамматики. Приведение КС-грамматик
- •НФ Хомского
- •НФ Грейбах
- •Алгоритмы построения синтаксических анализаторов
- •Синтаксический распознаватель с возвратом
- •Распознаватели без возвратов
- •Формальное определение
- •Ситуация
- •Грамматики предшествования
- •Построение матрицы предшествования
- •Построение матрицы предшествования
- •Генерация кода. Распределение памяти
- •Распределение памяти
- •Дисплей памяти процедуры
- •Синтаксическое дерево
- •Верификация и оптимизация кода
- •Ассемблеры и компоновщики

Грамматики предшествования
Грамматики предшествования. Грамматики простого предшествования. Отношения предшествования. Обратимые грамматики. Построение матрицы предшествования. Распознаватель для грамматики простого предшествования. Операторная грамматика. Грамматика операторного предшествования. Построение матрицы предшествования для грамматики операторного предшествования. Распознаватель для грамматик операторного предшествования. Остовная грамматика и остовный вывод
Грамматики предшествования также позволяют построить детерминированный анализатор на базе алгоритма переноссвертка. Для этого для каждой упорядоченной пары символов в грамматике устанавливается отношение, называемое отношением предшествования. В процессе разбора МП-автомат сравнивает текущий символ входной цепочки с одним из символов на вершине стека и проверяет отношение между ними. В зависимости от этого выполняется либо перенос, либо свертка. Если отношение отсутствует, то генерируется ошибка. Различают грамматики простого, расширенного, слабого, операторного предшествования и др.
Приведенная КС-грамматика является грамматикой простого предшествования, если:
1. Для каждой упорядоченной пары терминальных и нетерминальных символов выполняется не более чем одно отношение предшествования:
BiB =. Bj ( BiB ,Bj V) p P : A→αBiB BjB γ , A N, α,γV*
BiB <. Bj ( BiB ,Bj V) p P : A→αBiB Dγ , D * BjB ω, A,D N, α,γ,ωV*
BiB .> Bj ( BiB ,Bj V) p P : A→αCBjγ , C * ωBiB , либо p P : A→αCDγ , C * ωBiB , D * BjB τ, A,C,D N, α,γ,ω,τV*
2. pi P : Ai→αi , αi ≠ αj , i,j=0,1,…,|P|, i ≠ j. Т.е. правила имеют различные правые части. Грамматики, обладающие этим свойством, называют обратимыми.
Любая грамматика простого предшествования является однозначной. Легко проверить, является ли произвольная КСграмматика грамматикой простого предшествования. Однако не существует алгоритма, позволяющего преобразовать произвольную КС-грамматику в грамматику простого предшествования.
Алгоритм основан на том факте, что между двумя соседними символами входной строки возможны следующие варианты отношений предшествования:
BiB <. Bi+1 , если символ Bi+1 крайний левый символ некоторой основы, т.е. Bi предшествует основе BiB .> Bi+1 , если символ Bi крайний правый символ некоторой основы, т.е. Bi следует за основой BiB =. Bi+1 , если символы Bi , Bi+1 принадлежат одной основе
Рассмотрим рисунок. Изображена цепочка αγβδ в момент выполнения свертки подцепочки γ.
Символ a – последний в подцепочке α, b – первый в подстроке β. Если отношения предшествования в грамматике непротиворечивы, то сдвиг можно выполнять всегда, пока между символом на вершине стека и текущим символом входной цепочки существует отношение <. или =. . Как только обнаружено отношение .> , необходимо выполнить свертку, причем из стека выбираются все символы, связанные отношением =. . На основании отношений предшествования строится матрица предшествования. Строкам матрицы соответствует символ i пары (i,j), столбцам – j. Для построения матрицы удобно воспользоваться двумя дополнительными множествами:
L(A) = {X | A * Xω}, A N, X V, ωV* - множество крайних левых символов для нетерминала А R(A) = {X | A * ωX}, A N, X V, ωV* - множество крайних правых символов для нетерминала А Эти множества строятся по следующему алгоритму:
1. |
A N : R0 (A) = {X | A→ωX}, X V, ωV* ; |
L0 (A) = {X | A→Xω}, X V, ωV* ; i=1; |
2. |
A N : Ri (A) = Ri-1 (A) Ri-1 (B), B (Ri-1 (A)∩N); |
Li (A) = Li-1 (A) Li-1 (B), B (Li-1 (A)∩N); |
3. |
Если Ri (A) ≠ Ri-1 (A) или Li (A) ≠ Li-1 (A) i=i+1; повторить п.2. |
Построение матрицы предшествования. Для построения матрицы предшествования B={bij} добавляют символы концевых маркеров (начала строки и конца строки). В качестве этих маркеров можно использовать один и тот же символ (#). Матрица заполняется на основе следующих выражений:
1.p P : A→αijγ , A N, i,j V, α,γV* bij = =.
2.p P : A→αiDγ , j L(D), A,D N, i,j V, α,γV* bij = <.
3.p P : A→αCjγ , i R(C), A,C N, i,j V, α,γV* bij = .>
4.p P : A→αCDγ , i R(C), j L(D), A,C,D N, i,j V, α,γV* bij = .>
5.j L(S) : S-аксиома, A N, j V, b#j = <.
6.i R(S) : S-аксиома, A N, i V, bi# = .>
Пример: G({t, i, ,, ;},{S,N},{S→tN N→i,N N→i;},S) |
|
||||
R0(S)={N}; |
|
R0(N)={N, ;}; |
L0(S)={t}; |
L0(N)={i}; |
|
R1(S)= R0(S) R0(N)={N, ;}; |
R1(N)={N, ;}; |
L1(S)={t}; |
L1(N)={i}; |
||
R2(S)= R1(S) R1(N)={N, ;}; |
R2(N)={N, ;}; |
L2(S)={t}; |
L2(N)={i}; |
||
Рассмотрим заполнение ячеек: |
|
|
|
||
S→tN |
1) b(t,N)= =. |
2) L(N)={i}, b(t,i) = <. |
|
|
|
N→i,N |
1) b(i, ,)= =. b(,, N)= =. |
2) L(N)={i}, b(,, i) = <. |
|
||
N→i; |
1) b(i, ;)= =. |
|
|
|
|
5) L(S)={t}, b(#,t)= <. |
6) R(S)={N, ;}, b(N, #)= .> b(;, #)= .> |
||||||||
Получим таблицу: |
|
|
|
|
|
|
|||
|
|
S |
N |
t |
i |
, |
; |
# |
|
|
S |
|
|
|
|
|
|
|
|
N |
|
|
|
|
|
|
>. |
t |
|
=. |
|
<. |
|
|
|
i |
|
|
|
|
=. |
=. |
|
, |
|
=. |
|
<. |
|
|
|
; |
|
|
|
|
|
|
>. |
# |
|
|
<. |
|
|
|
|
Распознаватель функционирует следующим образом: вначале в стеке = маркер конца, флаг свертки сброшен, далее на каждом такте выполняются следующие действия:
1.При сброшенном флаге свертки: текущий символ – первый символ строки; иначе – первый символ строки для свертки.
2.По таблице определяется отношение между символом на вершине стека и текущим символом; если он отсутствует – выдать ошибку;
3.При сброшенном флаге свертки:
3.1.Для =. : текущий символ помещается в стек, указатель чтения сдвигается;
3.2.Для <. : текущий символ помещается в стек, указатель чтения сдвигается;;
3.3.Для .> : установить флаг свертки, символ с вершины стека вытолкнуть в строку для свертки;
При установленном флаге свертки:
3.4.Для =. : символ с вершины стека вытолкнуть в строку для свертки;
3.5.Для <. : определить правило для свертки, очистить строку свертки, поместить нетерминал из левой части правила в стек, сбросить флаг свертки;
4.Если входная строка содержит только маркер, а стек – только маркер и аксиому, завершить разбор сигналом Успешно. Пример:
Входная строка |
Стек |
Текущ символ |
Отношение |
Строка свертки |
Флаг |
Разбор |
ti,i;# |
# |
t |
<. |
|
0 |
|
i,i;# |
#t |
i |
<. |
|
0 |
|
,i;# |
#ti |
, |
=. |
|
0 |
|
i;# |
#ti, |
i |
<. |
|
0 |
|
;# |
#ti,i |
; |
=. |
|
0 |
|
# |
#ti,i; |
# |
.> |
|
0 |
|
# |
#ti,i |
; |
=. |
; |
1 |
|
# |
#ti, |
i |
<. |
i; |
1 |
|
# |
#ti,N |
# |
.> |
|
0 |
3 |
# |
#ti, |
N |
=. |
N |
1 |
3 |
# |
#ti |
, |
=. |
,N |
1 |
3 |
# |
#t |
i |
<. |
i,N |
1 |
3 |
# |
#tN |
# |
.> |
|
0 |
3 2 |
# |
#t |
N |
=. |
N |
1 |
3 2 |
# |
# |
t |
<. |
tN |
1 |
3 2 |
# |
#S |
# |
|
|
0 |
3 2 1 |
Операторная грамматика – это КС-грамматика без λ правил, в которой правые части всех правил не содержат смежных нетерминальных символов. Для таких грамматик отношения предшествования можно задать на множестве терминальных символов. Грамматикой операторного предшествования называется операторная КС-грамматика, для которой выполняются следующие условия:
1. Для каждой упорядоченной пары терминальных символов выполняется не более чем одно отношение предшествования:
ai =. aj ( ai , aj T) p P : A→αaiajγ , либо A→αaiBajγ A,B N, α,γV*
ai <. aj ( ai , aj T) p P : A→αaiDγ , D * ajω, либо D * Bajω, A,D,B N, α,γ,ωV* ai .> aj ( ai , aj T) p P : A→αCajγ , C * ωai, либо C * ωaiB, A,C,B N, α,γ,ωV*
2.pi P : Ai→αi , αi ≠ αj , i,j=0,1,…,|P|, i ≠ j.
3.В грамматике отсутствуют λ правила.
Любая грамматика операторного предшествования задает детерминированный КС язык. Существует алгоритм проверки, является ли произвольная КС грамматика грамматикой операторного предшествования. Однако не существует алгоритма, позволяющего преобразовать произвольную КС грамматику в грамматику операторного предшествования.
Принцип работы распознавателя аналогичен предыдущему случаю, однако отношения проверяются только между терминальными символами. Матрица предшествования содержит только терминальные символы. Аналогично опрелеляются множества:
Lt(A) = {t | A * tω либо A * Btω }, A,B N, t T, ωV* - множество крайних левых терминальных символов для нетерминала А
Rt(A) = {t | A * ωt либо A * ωtB }, A,B N, t T, ωV* - множество крайних правых терминальных символов для нетерминала А Эти множества строятся по следующему алгоритму:
1. Определяются множества L(A) и R(A) – рассмотрено ранее.
2. A N : Rt0 (A) = {t | A→ωt либо A→ωtX }, t T, X N, ωV* ; Lt0 (A) = {t | A→ tω либо A→ Xtω }, t T, X N,
ωV* ; i=1; Во множество L включаются самые левые терминальные символы правой части правил, во множество R – самые правые.
3. |
A N : Rti (A) = Rti-1 (A) Rti-1 (B), B (R(A)∩N); Lti (A) = Lti-1 (A) Lti-1 (B), B (L(A)∩N); |
4. |
Если Rti (A) ≠ Rti-1 (A) или Lti (A) ≠ Lti-1 (A) i=i+1; повторить п.3. |
Построение матрицы предшествования. Для построения матрицы предшествования B={bij} добавляют символы концевых маркеров (начала строки и конца строки). В качестве этих маркеров можно использовать один и тот же символ (#). Матрица заполняется на основе следующих выражений:
1.p P : A→αijγ либо A→αiBjγ, A,B N, i,j T, α,γV* bij = =.
2.p P : A→αiDγ , j Lt(D), A,D N, i,j T, α,γV* bij = <.
3.p P : A→αCjγ , i Rt(C), A,C N, i,j T, α,γV* bij = .>
5.j Lt(S) : S-аксиома, A N, j T, b#j = <.
6.i Rt(S) : S-аксиома, A N, i T, bi# = .>
Пример: G({t, i, ,, ;},{S,N},{S→tN N→i,N |
N→i;},S) |
||||||||||||
1. R(S)= {N, ;}; |
R(N)={N, ;}; |
L(S)={t}; |
L(N)={i}; |
||||||||||
2. Rt0 (S)={t}; |
|
Rt0(N)={, , ;}; Lt0(S)={t}; |
Lt0(N)={i}; i=1 |
||||||||||
3.1. Rt1 (S)= Rt0 (S) Rt0(N)= {t, , , ;}; |
|
|
Lt1(S)= Lt0 (S) ={t}; |
||||||||||
Rt1(N)= Rt0 (N)={, , ;}; |
|
|
|
|
|
|
Lt1(N)= Lt0 (N)={i}; i=2 |
||||||
3.2. Rt2 (S)= Rt1 (S) Rt1(N)= {t, , , ;}; |
|
|
Lt2(S)= Lt1 (S) ={t}; |
||||||||||
Rt2(N)= Rt2 (N)={, , ;}; |
|
|
|
|
|
|
Lt2(N)= Lt1 (N)={i}; |
||||||
Рассмотрим заполнение ячеек: |
|
|
|
|
|
||||||||
S→tN |
1) Lt |
(N)={i}, b(t,i)= <. |
|
|
N→i,N 1) b(i, ,)= =. 2) Lt(N)={i}, b(,, i) = <. |
||||||||
N→i; |
1) b(i, ;)= =. |
|
|
|
|
|
5) Lt(S)={t}, b(#,t)= <. 6) Rt(S)={t, , , ;}, b(t, #)= .> b(, , #)= .> b(;, #)= .> |
||||||
Получим таблицу: |
|
|
|
|
|
|
|
||||||
|
|
|
t |
|
i |
|
, |
|
; |
|
# |
|
|
|
t |
|
|
|
<. |
|
|
|
|
|
>. |
|
|
|
i |
|
|
|
|
=. |
|
=. |
|
|
|
|
|
|
, |
|
|
|
<. |
|
|
|
|
|
>. |
|
|
|
; |
|
|
|
|
|
|
|
|
|
>. |
|
|
|
# |
|
<. |
|
|
|
|
|
|
|
|
|
|
Как видим, эта таблица не получается простым вычеркивание строк и столбов, соответствующих нетерминалам. Распознаватель функционирует аналогично грамматике простого предшествования. Однако в работе имеются две особенности. При определении отношения между символами, если на вершине стека нетерминал, то для анализа используется следующий за ним символ. При переносе символа в строку для свертки, если символ на вершине стека нетерминал, то в строку для свертки переносится и следующий за ним терминальный символ. В остальном все аналогично.
Пример:
Входная строка |
Стек |
Текущ символ |
Отношение |
Строка свертки |
Флаг |
Разбор |
ti,i;# |
# |
t |
<. |
|
0 |
|
i,i;# |
#t |
i |
<. |
|
0 |
|
,i;# |
#ti |
, |
=. |
|
0 |
|
i;# |
#ti, |
i |
<. |
|
0 |
|
;# |
#ti,i |
; |
=. |
|
0 |
|
# |
#ti,i; |
# |
.> |
|
0 |
|
# |
#ti,i |
; |
=. |
; |
1 |
|
# |
#ti, |
i |
<. |
i; |
1 |
|
# |
#ti,N |
# |
.> |
|
0 |
3 |
# |
#ti |
, |
=. |
,N |
1 |
3 |
# |
#t |
i |
<. |
i,N |
1 |
3 |
# |
#tN |
# |
.> |
|
0 |
3 2 |
# |
# |
t |
<. |
tN |
1 |
3 2 |
# |
#S |
# |
|
|
0 |
3 2 1 |
Управляющая таблица получается компактнее, а обработка строки происходит несколько быстрее. К сожалению, класс языков операторного предшествования уже, чем класс языков простого предшествования, поэтому упростить распознаватель не всегда возможно.
Распознаватель операторного предшествования полностью игнорирует нетерминалы. Поэтому, в принципе, их можно заменить одним и тем же нетерминалом. Грамматика, полученная таким образом, называется остовной грамматикой. Эта грамматика не является эквивалентной исходной и строится исключительно для упрощения алгоритма работы. Более того, она не является и однозначной, однако однозначность в распознаватель закладывается при построении управляющей таблицы. Из нее удаляются правила вида S→S, однако нумерация сохраняется в полном соответствии с исходной грамматикой. Результат разбора на основе остовной грамматики называется остовным выводом. В нем отсутствуют цепные правила и не учитываются типы нетерминалов. Однако компилятору в этом и нет необходимости, более того, это только усложняет обработку. Поэтому остовный вывод для компилятора более результативен.