Атрибутные МП-автоматы отличаются от обыкновенных МП-автоматов тем, что символы и состояния снабжены атрибутами, которые обрабатываются в процессе его работы. Атрибутный МП-автомат обладает следующими свойствами:
1) Все входные, выходные и магазинные символы, а также состояния имеют конечное число атрибутов.
2) На каждом шаге работы атрибутного МП-автомата значения атрибутов нового состояния, нового верхнего символа магазина (если этот шаг не выталкивание из магазина) и выходных символов вычисляются как функция атрибутов старого состояния, верхнего символа магазина и входного символа (если это не пустой шаг).
Определение 4.3.3. [17]. Атрибутный МП-преобразователь – это система из 11 объектов:
M = <Q, I, Y, Г, , q, Z, A, C, u, v>,
где Q – конечное множество состояний;
I – конечное множество входных символов;
Y – конечное множество выходных символов;
Г – конечное множество магазинных символов;
qQ – начальное состояние;
ZГ – начальный магазинный символ;
A – множество возможных значений атрибутов;
С – функция из QIYГ во множество неотрицательных целых чисел, определяющая, сколько атрибутов имеет каждый символ; посредством будет обозначаться расширение С на множество { QIYГ}*, получаемое, если положить () = и () = С()+С(), где – пустой символ, – символ, – цепочка символов;
uAC(q) – множество значений атрибутов для начального состояния;
v AC(q) – множество значений атрибутов для начального магазинного символа;
– отображение {Qx {I{}}xГ} во множестве конечных множеств четверок, такое, что если (r, , ) содержит (p, , , f), то pQ, Г*, Y* и f – вычислимая функция, кроме того всякие две четверки в (r, , ) отличаются по крайне мере одной из трех своих компонент.
Атрибутный МП-преобразователь называют детерминированным, если:
1) для любых rQ и Г всякий раз, когда (r, , ) не пусто, (r,,) пусто для всех ;
2) отображает аргумент во множество, состоящее не более чем из одного элемента.
Конфигурация атрибутного МП-преобразователя — это четверка (r, х, , у), где r — атрибутное состояние, х — цепочка атрибутных входных символов, — цепочка атрибутных магазинных символов, у — цепочка атрибутных выходных символов. Если конфигурация имеет вид (rg, h, x, , , y), где r — состояние со множеством атрибутов g, I {} имеет множество атрибутов h, — магазинный символ со множеством атрибутов i, и (r, , ) содержит (р, n, , f), то мы пишем:
(rg, h, x, , , y) (, x, ,, y),
где , , – это p, ,, соответственно с атрибутами, вычисленными в результате применения функции f к атрибутам из g, h, i.
Рефлексивное транзитивное замыкание отношения обозначается как *
Если
(qu, x, Zv,) *(p, ,, y),
т.е. цепочку называют трансляцией цепочки х, выполняемой атрибутным МП-преобразователем.
Теорема 4.3.1. [17]. Любую трансляцию, определяемую L-атрибутной трансляционной грамматикой, у которой входная грамматика является LL(1)-грамматикой, можно выполнить на атрибутной детерминированной МП-машине с концевым маркером.
Доказательство данной теоремы [17] является, no-существу, описанием алгоритма построения атрибутного МП-преобразователя по трансляционной LL(K)-грамматике. Воспроизведем основные шаги этого алгоритма.
Пусть I — входное множество трансляционной грамматики, Y — множество операционных символов (символов действий), N — множество нетерминалов. Перенумеруем правила грамматики числами от 1 до га, где m — число правил в грамматике. Пусть в правой части i-го правила содержится ni символов.
Атрибутный МП-преобразователь имеет вид
M = <{q}, I, Y, {z}{(i, j) | 1im, 0jn}, , q, Z, A, C, u, v>,
где q, Z – произвольные новые имена, А – множество значений атрибутов грамматики, u – произвольно, C, v, определяют ниже.
Для IY значение С() равно числу атрибутов, которыми обладает в грамматике. Для Z C(Z) = , для q C(q) = max C(), где . Для каждого магазинного символа вида (i, j) значение C((i, j)) равно сумме числа атрибутов первых j = 1 символов правой части i-го правила и числа унаследованных атрибутов нетерминала, стоящего в левой части правила.
Атрибутный МП-автомат выполняет нисходящий разбор. Когда магазинный символ (i, j) находится наверху магазина, значения унаследованных атрибутов левой части 1-го правила и всех атрибутов первых j символов правой части известны — они равны значениям соответствующих атрибутов состояния (для j-ro символа правой части) и верхнего символа магазина (для первых j = 1 символов его правой части).
Магазинный символ Z используется только лишь для инициализации работы магазина и после первого же такта работы автомата выталкивается из магазина. Символ Z в первом такте заменяется на (i, 0)—это означает, что начальный символ грамматики разворачивается по i-му правилу. При этом символ (i, 0) имеет столько атрибутов, сколько имеется унаследованных атрибутов у начального символа грамматики, а их значения полагаются равными значениям, которые заданы для унаследованных атрибутов в грамматике.
Когда верхний символ магазина имеет вид (i, j), где j = ni, это означает, что i-е правило применилось успешно.
Очередное действие автомата — подмножеству атрибутов состояния присваиваются значения атрибутов левой части правила, а верхний символ выталкивается из магазина. При этом значения унаследованных атрибутов равны значениям соответствующих атрибутов символа (i, j). Значения синтезированных атрибутов вычисляются по значениям атрибутов символа (i, j) и состояния q.
Действия МП-автомата, когда верхним символом магазина является символ (i, j), где j<n, зависят от того, является ли (j+1) символ правой части правила входным, нетерминальным или операционным. Во всех этих случаях символ (i, j) будет замещен символом (i, j+1), а значения атрибутов этого символа будут вычисляться по значениям атрибутов символа (i, j) и состояния q. Действия же автомата для различных типов символа (i, j+1) будут различны. Обозначим (j+1)-й символ 1-го правила через а и рассмотрим основные случаи.
Случай 1. , т.е. а — входной символ. Если совпадает с текущим входным символом, то атрибутам состояния q присваиваются значения атрибутов символа .
Случай 2. Y, т.е. — операционный символ. Унаследованные атрибуты для вычисляются по значениям атрибутов символа (i, j) и состояния q. Синтезированные атрибуты вычисляются после нахождения значений унаследованных. После этого символ вместе со значениями его атрибутов выводится на выходную ленту МП-преобразователя.
Случай 3. , т.е. — нетерминальный символ. МП-преобразователь выбирает k-e правило, левой частью которого является а, и помещает на верх магазина (над символом (i, j+1)) символ (k, 0), присваивая его атрибутам значения унаследованных атрибутов символа. Впоследствии, когда символ (i, j+1) вновь станет верхним символом магазина (после выталкивания символа (k, nk)), значения атрибутов символа будут равны значениям некоторых атрибутов состояния.
Пример 4.3.2. Процесс построения атрибутного МП-преобразователя рассмотрим на примере трансляции оператора описания переменных в некотором гипотетическом языке программирования. Будем полагать, что описание переменных задается, например, в виде:
real i1, i4, i9.
Здесь символ ik является идентификатором, индекс k является атрибутом, причем значением этого атрибута служит указатель на позицию таблицы идентификаторов, сопоставленную данному идентификатору. Для каждого идентификатора во время трансляции необходимо выполнить операцию ALLOCATE. В результате выполнения этой операции в позицию таблицы идентификаторов, соответствующую данному, заносится адрес ячейки памяти, выделяемой этому идентификатору. Будем считать, что для идентификатора выделяется одна ячейка памяти. Выделяются ячейки последовательно, начиная с ячейки с адресом 50. Операция ALLOCATE реализуется одноименной семантической программой, которая имеет два входных параметра: указатель на соответствующую позицию таблицы идентификаторов, а также адрес выделенной для идентификатора ячейки памяти.
Описанный содержательно процесс трансляции (семантика) оператора описания переменных может быть формально задан с помощью L-атрибутной трансляционной грамматики, приведенной на рис. 4.11 [17].
Нижние символы возле символов грамматики — имена атрибутов, верхние — имена магазинных символов для МП-преобразователя, задаваемые в виде пары (i, j), где i — номер правила, j — позиция символа в правиле. Для входной цепочки real i1, i4, i9, данная грамматика порождает следующую активную цепочку:
real i1, {ALLOCATE}1, 50, i4 { ALLOCATE}4, 51, i9 {ALLOCATE}9,52
Для построения атрибутного МП-преобразователя, выполняющего такие трансляции, будем использовать результаты теоремы [17].
Y = {{ALLOCATE}a2,x2} – множество операционных символов;
Sx1, z2 – наследуемый х1, синтезируемый z2
Rx1, x2 – наследуемый х1, синтезируемый х2
{ALLOCATE}a2,x2 – наследуемые а2, х2
Рис. 4.11. L-атрибутная трансляционная грамматика для оператора описания переменных
Имеем:
{q} = {q, ДОПУСТИТЬ, ОТВЕРГНУТЬ} – множество состояний МП-преобразователя;
I = {real, ia1, ,} – множество входных символов;
Г = {#, (1,0), (1,1), (1,2), (1,3), (2,0), (2,1), (2,2), (3,0)) – множество магазинных символов. Отображение зададим в виде равенств вида
(q, x, y) = (q, , ),
где х – входной символ, у – магазинный символ, – новый магазинный символ (или цепочка символов), – выходной символ. Если x = , то это означает — любой входной символ без сдвига входной ленты, если =, то выполняется только выталкивание символа из магазина, если = , — на выходную ленту ничего не записывается. Имеем:
(q, real, (1, 0)) = (q, (1, 3), (1, 2), (1, 1), );
(q, i, (1, 1)) = (q, , );
(q, , (1, 2)) = (q, , (1, 2));
(q, , , (1, 3)) = (q, (2,0), );
(q, , (2, 0)) = (q, (2, 3), (2, 2), (2, 1), );
(q, i, (2, 1)) = (q, , );
(q, , (2, 2)) = (q, , (2, 2));
(q, , , (2, 3)) = (q, (2,0), );
(q, , (2, 3)) = (q, (3,0), );
(q, , (1, 3)) = (q, (3,0), );
(q, , (3, 0)) = (q, , );
(q, , #) = (ДОПУСТИТЬ, , );
Во всех других ситуациях автомат переходит в состояние ОТВЕРГНУТЬ.
Последовательность конфигураций МП-преобразователя при выполнении трансляции входной цепочки real i1, i4 – будет следующей:
(q0,0,0, real i1, i4 , #(1,0)50,0,)
(q50,0,0, i1, i4 , #(1,3)0,0 (1,2)0,0 (1,1)0,)
(q50,1,0, , i4 , #(1,3)51,0 (1,2)1,50)
(q50,1,51, i4 , #(2,0)51,0 (1,2)1,50)
(q50,1,51, , #(2,3)0,0 (2,2)0,0 (2,1)0,0 (1,2)1,50)
(q50,4,51, , #(2,3)52,0 (2,2)4,51 (1,2)1,50)
(q50,4,51, , #(3,0)52,52 (1,2)1,50 (2,2)4,51)
(q50,4,51, , #(1,2)1,50 (2,2)4,51)
(ДОПУСТИТЬ,, #(1,2)1,50 (2,2)4,51)
Таким образом, на выходной ленте атрибутного МП-преобразователя будет сформирована следующая операционная часть активной цепочки:
{ALLOCATE}1,50, {ALLOCATE}4,51.