CodeNet / Приложения / Алгоритмы / Разбор выражений. Компиляторы и интерпретаторы. / Лекции по конструированию компиляторов
Лекции по конструированию компиляторов - Глава 5. Элементы теории перевода
5.1. Преобразователи с магазинной памятью Преобразователем с магазинной памятью (МП-преобразователем) называется восьмерка P=(Q,T,Г,П,Ф,q0,Z0,F), где Q - множество состояний, T - конечный входной алфавит, Г - конечный алфавит магазинных символов, П - конечный выходной алфавит, Ф - отображение множества Qx(T U {e})xГ в множество конечных подмножеств множества QxГ*xП*, q0u, A1=v1, A2=v2, ... , Am=vm, удовлетворяющих следующим условиям: - каждый символ, входящий в v1, ..., vm, либо принадлежит П, либо является Bk для Bu называют входным правилом вывода, Ai - переводом нетерминала A и Ai=vi - элементом перевода, связанным с этим правилом перевода. Если через P обозначить множество входных правил вывода всех правил перевода, то G=(N,T,P,S) будет входной грамматикой для Tr. Если в СУ-схеме Tr нет двух правил перевода с одинаковым входным правилом вывода, то ее называют семантически однозначной. Выход СУ-схемы определим снизу вверх. С каждой внутренней вершиной n дерева разбора (во входной грамматике), помеченной A, свяжем одну цепочку для каждого Ai. Эта цепочка называется значением (или переводом) символа Ai в вершине n. Каждое значение вычисляется подстановкой значений символов перевода данного элемента перевода Ai=vi, определенных в прямых потомках вершины n. Переводом t(Tr), определяемым СУ-схемой Tr, назовем множество {(x,y)|x имеет дерево разбора во входной грамматике для Tr и y - значение выделенного символа перевода S в корне этого дерева}. Если Tr=(N,T,П,R,S) - СУ-схема, то т(Tr) называется синтаксически управляемым переводом (СУ-переводом). Пример 5.2. Рассмотрим формальное дифференцирование выражений, включающих константы 0 и 1, переменную x и функции sin, cos, + и *. Такие выражения порождает грамматика E -> E+T | T T -> T*F | F F -> (E) | sin(E) | cos(E) | x | 0 | 1 Свяжем с каждым из E, T и F два перевода, обозначенных индексом 1 и 2. Индекс 1 указывает на то, что выражение не дифференцировано, 2 - что выражение продифференцировано. Формальная производная - это E2. Законы дифференцирования таковы: d(f(x)+g(x))=df(x)+dg(x) dx=1 d(f(x)*g(x))=f(x)*dg(x)+g(x)*df(x) d0=0 dsin(f(x))=cos(f(x))*df(x) d1=0 dcos(f(x))=-sin(f(x))df(x) Эти законы реализуются СУ-схемой: E -> E+T E1=E1+T1 F -> cos(E) F1=cos(E1) E2=E2+T2 F2=-sin(E1)*(E2) E -> T E1=T1 F -> x F1=x E2=T2 F2=1 T -> T*F T1=T1*F1 F -> 0 F1=0 T2=T1*F2+T2*F1 F2=0 F -> ( E ) F1=(E1) F -> 1 F1=1 F2=(E2) F2=0 F -> sin(E) F1=sin(E1) F2=cos(E1)*(E2) Дерево вывода для sin(cos(x))+x приведено на рис. 5.3. Теорема 5.1. Если число вхождений каждого нетерминала в слове v не превосходит 1, то t(Tr) является КС-языком. Обратное не всегда верно [5]. Пример 5.2. T=({S,A},{a},{a,b},{S->A,AbAbA;A->a,a;A->aA,aA}. Здесь входной язык {an|n>=1}, выходной {anbanban}. Выходной язык не КС. Теорема 5.2. Для каждого магазинного преобразователя существует эквивалентная СУ-схема [5]. Обратное, вообще говоря, не верно. Определение. Семантически однозначная СУ-схема Tr=(N,T,П,R,S) называется простой, если для каждого правила A->u,v из R соответствующие друг другу вхождения нетерминалов встречаются в u и v в одном и том же порядке. E E1=sin(cos(x))+x / \ E2=cos(cos(x)) E1=sin(cos(x)) / + \ *(-sin(x)*(1))+1 E2=cos(cos(x)) E T *(-sin(x)*(1)) | | T2=1 | | T1=x T1=sin(cos(x)) | | T2=cos(cos(x)) T F F1=x *(-sin(x)*(1)) | | F2=1 | | F1=sin(cos(x)) | | F2=cos(cos(x)) F x *(-sin(x)*(1)) | | sin ( E ) E1=cos(x) | E2=-sin(x)*(1) | T T1=cos(x) | T2=-sin(x)*(1) | F F1=cos(x) | F2=-sin(x)*(1) | cos ( E ) E1=x E2=1 | T T1=x T2=1 | F F1=x F2=1 | x Рис. 5.3 Перевод, определяемый простой СУ-схемой, называется простым синтаксически управляемым переводом (простым СУ-переводом). Теорема 5.3. Пусть Tr=(N,T,П,R,S) - простая СУ-схема. Существует такой МП-преобразователь P, что t(P)=t(Tr) [5]. Таким образом, класс трансляций, определяемых магазинными преобразователями, совпадает с классом простых СУ-переводов. Теорема 5.4. Пусть Tr=(N,T,П,R,S) - семантически однозначная простая СУ-схема, входной грамматикой которой служит LL(k)- грамматика. Тогда перевод {x$,y)|(x,y) Sa, aSa S -> Sb, bSb S -> e, e Входная грамматика является LR(1) грамматикой, но не существует ДМП-преобразователя, определяющего перевод {(x$,y)|(x,y)u,v, где v X1 ... Xn и будем предполагать, что G - редуцированная КС-грамматика, т.е. в ней нет нетерминальных символов, для которых не существует полного дерева вывода , в которое входит этот нетерминал. С каждым символом X X1 ... Xnp сопоставлено семантическое правило a=fa(...). Назовем атрибут a(Xi) наследуемым, если одному из правил вывода p:X0 -> X1 ... Xi ... Xnp сопоставлено семантическое правило a=fa(...), i ' ГлобальныйАтрибут ::= ИмяАтрибута '' Метка ::= Целое ':' | Целое 'Е' ':' | Целое 'А' ':' Оператор ::= Условный | ОператорПроцедуры | ЦиклПоМножеству | ПростойЦикл | ЦиклСУсловиемОкончания Описание атрибутной грамматики состоит из раздела описания атрибутов и раздела правил. Раздел описания атрибутов определяет состав атрибутов для каждого символа грамматики и тип каждого атрибута. Правила состоят из синтаксической и семантической части. В синтаксической части используется расширенная БНФ. Семантическая часть правила состоит из локальных объявлений и семантических действий. В качестве семантических действий допускаются как атрибутные присваивания, так и составные операторы. Метка в семантической части правила привязывает выполнение оператора к обходу дерева разбора сверху-вниз слева направо. Конструкция "i : оператор" означает, что оператор должен быть выполнен сразу после обхода i-й компоненты правой части. Конструкция "i E : оператор" означает, что оператор должен быть выполнен, только если порождение i-й компоненты правой части пусто. Конструкция "i A : оператор" означает, что оператор должен быть выполнен после разбора каждого повторения i-й компоненты правой части (имеется в виду конструкция повторения). Каждое правило может иметь локальные определения (типов и переменных). В формулах используются как атрибуты символов данного правила (локальные атрибуты) и в этом случае соответствующие символы указываются номерами в правиле (0 для символа левой части, 1 для символа правой части и т.д.), так и атрибуты символов предков левой части правила (глобальные атрибуты). В этом случае соответствующий символ указывается именем нетерминала. Таким образом, на дереве образуются области видимости атрибутов: атрибут символа имеет область видимости, состоящую из правила, в которое символ входит в правую часть, плюс все поддерево, корнем которого является символ, за исключением поддеревьев - потомков того же символа в этом поддереве (рис. 5.4). | ... . N . . / \ . . / \ . . /\ /\ . . / /\ /\ \ . . / -- -- \ . ...N...........N... /\ /\ -- -- Рис. 5.4 Значение терминального символа доступно через атрибут VAL соответствующего типа.