Скачиваний:
279
Добавлен:
15.06.2014
Размер:
3.05 Mб
Скачать

КС-грамматики. Приведение КС-грамматик

Контекстно-свободные языки. Лемма о разрастании КС-языка. Дерево синтаксического разбора. Однозначность и рекурсивность грамматики. Нормальные формы Хомского и Грейбах. Преобразование грамматики в нормальную форму Хомского. Преобразование грамматики в нормальную форму Грейбах. Приведение КС-грамматик (устранение недостижимых и бесполезных символов, устранение λ-правил, устранение цепных правил). Устранение левой рекурсии

Синтаксический анализатор – это часть компилятора, которая отвечает за выявление и проверку синтаксических конструкций входного языка. СА выполняет:

-Поиск и выделение синтаксических конструкций в тексте исходной программы

-Установку типа и проверку правильности синтаксической конструкции

-Представление синтаксических конструкций в виде, удобном для генерации результирующего кода.

СА – основная часть компилятора на этапе анализа. На вход СА поступает таблица лексем, сформированная ЛА. СА разбирает ее в соответствии с грамматикой входного языка.

Лемма о разрастании КС-языка. ) Пусть L – КС-язык: α L, δ,β1,ϕ,β2,γ V*, р Ν>0 | α=δβ1ϕβ2γ, |α|p, 0<|β1β2|p, α’ =

δβ1iϕβ2iγ, i Ν≥0, α’ L. В достаточно длинной строке КС языка всегда можно найти две подстроки с ненулевой суммарной длиной, одновременное повторение которых произвольное кол-во раз порождает новые строки того же языка. Например,

язык L={0n1n| m,n1} КС, а язык L={0n1n2n| n1} не КС.

Деревом вывода грамматики G(T,N,P,S) называется дерево (граф), которое соответствует некоторой цепочке вывода и удовлетворяет следующим условиям:

-каждая вершина обозначается символом грамматики V (T N {λ})

-корнем дерева является вершина, обозначенная аксиомой S

-листьями являются вершины, обозначенные символом t (T {λ})

-если некоторый узел обозначен символом A N, а связанные с ним узлы символами V1,V2,…,Vn,

n>0, Vi (T N {λ}), то в грамматике G существует правило AV1,V2,…,Vn P

В таком виде дерево вывода всегда можно построить для КС и регулярных грамматик. Для других типов – только частные случаи.. Пример.

G({/,*,a,,},{S,C,K},P,{S}), P:{S C*/ | K↓←; C /* | C/ | C* | Ca | C↓←; K // | K/ | K* | Ka}

Для цепочки //a↓← дерево вывода будет иметь следующий вид: Для построения дерева достаточно иметь цепочку вывода. Левосторонний вывод имеет место, когда правило применяется всегда к самому левому нетерминалу, правосторонний – к самому правому. Грамматика называется однозначной, если для каждой цепочки символов языка, заданного этой грамматикой можно построить единственный левосторонний и единственный правосторонний вывод, т.е. для каждой цепочки символов языка существует единственное дерево вывода. Однако иногда одна и та же цепочка может иметь разные деревья вывода, например: G({(,a,)},{S},P,{S}), P:{S S+S | S*S | (S) | a | b}, цепочка a*b+a.

Возможные варианты вывода: SS+SS*S+Sa*S+Sa*b+Sa*b+a или SS*Sa*Sa*S+Sa*b+Sa*b+a для левостороннего вывода.

Имеется неоднозначность. Для построения компиляторов грамматики не должны допускать подобного. Неоднозначность может устраняться заданием приоритетов. Однозначность – это свойство грамматики, а не языка. Т.е. для языка, заданного неоднозначной грамматикой, может найтись однозначная грамматика, задающая тот же самый язык. Если в грамматике имеются правила вида:

SSS | α

SSαS | β S→αS | Sβ | γ

S→αS | αSβS | γ , то она является неоднозначной. Это необходимое, но не достаточное условие однозначности, т.е. отсутствие правил такого вида еще не гарантирует однозначности.

Рекурсия может быть явной, когда символ определяется сам через себя (пример) и неявной (косвенной), тогда тоже самой происходит черезцепочку правил (пример).

Грамматика называется леворекурсивной, если в ней имеются выводы вида: A N: A *Aα, α V+.

Праворекурсивной: A N: A *αА, α V+. Самовставляющей (самовложенной) A N: A * αAβ, α,β V+.

В грамматике G(N,T,P,S) символ A N называется бесполезным (бесплодным), если не существует вывода вида: S *αAβ αbβ, α,b,β T*. Т.е. из него нельзя вывести ни одной цепочки терминальных символов.

Символ A называется недостижимым, если AS и не существует вывода вида: S *αAβ, α,β V*. Т.е. при любом выводе этот нетерминал не может появиться в цепочке.

Грамматика G(N,T,P,S) называется грамматикой без λ-правил, (λ-свободной) если множество Р не содержит правил вида A→λ, A N, либо есть ровно одно правило S→λ, и аксиома S не встречается в правых частях других правил.

КС Грамматика G(N,T,P,S) называется грамматикой без циклов, если в ней нет выводов вида A *A, A N. Циклы возможны в грамматике только если в ней присутствуют цепные правила вида AB, A,B N.

С одной стороны при описании грамматики естественно желание ее максимально упростить. Устранение недостижимых и бесполезных символов направлены именно на это. С другой стороны, хотелось бы, чтобы СА строился максимально просто.

Устранение цепных правил (как следствие циклов) и λ-правил упрощают построение распознавателя, хотя эти методы могут несколько усложнить грамматику. Грамматика называется приведенной, если она не имеет бесполезных и недостижимых символов, λ-правил, цепных правил. Любая приведенная КС-грамматика, не содержащая самовложений, эквивалентна регулярной грамматике. Алгоритмы выполняются в следующем порядке: удаление бесполезных символов, удаление недостижимых символов, удаление λ-правил, удаление цепных правил.

Для КС грамматик существует несколько стандартных способов задания, т.н. нормальных форм. Каждая КС грамматика G(N,T,P,S) эквивалентна КС грамматике G’=(N’,T,P’,S) в НФ Хомского, все порождающие правила из множества P’ имеют вид: ABC | Aa, A,B,C N’, a T; либо S→λ, если λ L(G) и аксиома S не встречается в правых частях правил. Существует алгоритм перевода приведенной КС грамматики в НФ Хомского:

1.T’=T, N’=N, S’=S;

2.pi P: ABC, Aa, S→λ, A,B,C N, a T P’=P’ {ABC | Aa | S→λ};

3.pi P: ABa, A,B N, a T N’=N’ {A’}, P’=P’ {ABA’, A’a};

4.pi P: AaB, A,B N, a T N’=N’ {A’}, P’=P’ {AA’B, A’a};

5.pi P: AA1A2…Ak, k>2 N’=N’ {B1, B2,…,Bk-2, A1’, A2’,…Ak’}, P’=P’ {Bi-1Ai’Bi}, i=1,2,…,k-1, B0=A, Bk-1 =Ak‘,

если Ak N, Ak’=Ak, если Ak Т, P’=P’ {AkAk} где Ak’– новый нетерминал

Пример. G=({a,q,w},{X,D,E},{XDaqEw},X).

1. T’={a,q,w}, N’={X,D,E}, S’=X; 5. K=5, N’=N’ {B1, B2, B3, A1’, A2’, A3’, A4’, A5’}={B1, B2, B3, D, A2’, A3’, E, A5’};

P’=P’ {B0A1’B1, B1A2’B2, B2A3’B3, B3A4’B4}={XA1’B1, B1A2’B2, B2A3’B3, B3A4’A5’}=

{ XDB1, B1A2’B2, B2A3’B3, B3EA5’}, P’=P’ { A2A2, A3A3, A5A5}={ A2a, A3q, A5w} G’=({a,q,w},{X,D,E, B1, B2, B3, A2’, A3’, A5’},{ XDB1, B1A2’B2, B2A3’B3, B3EA5’, A2a, A3q, A5w },X)

Другой нормальной формой является НФ Грейбах. Все порождающие правила в ней имеют вид: Abα, A N, b T, α N* либо S→λ, если λ L(G) и аксиома S не встречается в правых частях правил. Алгоритм перевода приведенной КСграмматики без левой рекурсии:

1.G’=G;

2.Нетерминалы упорядочиваются N’={A1,A2,…,An} таким образом, что p P’: AiAjα, Ai,Aj N, α V* , i<j; k=|N’|-1;

3.AkAjα, Aj→β1|β2|…|βm Aj N’, βd V* Ai→β1α|β2α|…|βmα; правило заменяется для всех Aj, где βd , d=1,2,…m – весь набор правил для Aj. k--; если k!=0, повторить п.3

4.pi P: Abγ1γ2γm , A N’, b T’, γi V AbY1Y2…Ym , γi T’, N’=N’ {Yi}, P’=P’ {Yi→γi}; γi N’, Yi=γi , Пример. G={{*,n},{S,A,B},{SB*A, Bn | A*B, An},S}

2.S1B2*A3, B2n | A3*B2, A3n; k=3-1=2;

3.B2n | A3*B2 B2n | n* B2; k=1

3.S1B2*A3 S1n* A3 | n* B2*A3; k=0;

4.A3n; B2n; B2n*B2 B2nY1B2, N’=N’ {Y1},P’=P’ {Y1*}; S1n*A3 S1nY1A3; S1n*B2*A3 S1nY1B2Y1A3 G’=({*,n},{S,A,B,Y},{ An; Bn | nYB; Y*; SnYA | nYBYA}, S)

Алгоритм удаления бесполезных символов. Алгоритм работает со специальным множеством нетерминальных символов Yi. Вначале в него попадают только те нетерминалы, из которых можно непосредственно вывести терминальные цепочки. Далее оно итерационно пополняется.

1.Y0= ; i=1;

2.A N: (A→α) P, α (Yi-1 T)* Yi = Yi {A}; т.е. на каждом шаге включаются все нетерминалы из левых частей правил, в правых частях которых только терминалы или нетерминалы, включенные на предыдущем шаге;

3.Если YiYi-1, то i=i+1 и перейти к шагу 2

4.N’=Yi; T’=T; S’=S;

5.P’=P’ {pi}, pi: A→α, A,α (T Yi)*; остаются только правила, которые содержат используемые нетерминалы

Алгоритм удаления недостижимых символов. Алгоритм работает с множеством достижимых символов Yi. Вначале это аксиома грамматики, затем множество итерационно пополняется. Все символы, которые в итоге не войдут в это множество, являются недостижимыми и могут быть удалены.

1.Y0={S}; i=1;

2.A Yi-1: (A→αxβ) P, α,β V* , x V Yi = Yi {x} Yi-1; т.е на каждом шаге включаются терминалы и нетерминалы из правых частей правил, в левых частях которых только нетерминалы, включенные на предыдущем шаге;

3.Если YiYi-1, то i=i+1 и перейти к шагу 2

4.N’=NYi; T’=TYi; S’=S;

5.P’=P’ {pi}, pi: A→α, A,α Yi; остаются только правила, которые содержат используемые символы

Пример. G({a,b,c},{A,B,C,D,E,F,G,S},P,S); P: { SaAB | E; AaA | bB; BACb | b; CA | bA | cC | aE; EcE | aE | Eb | ED | FG; Da | c | Fb; FBC | EC | AС; GGa | Gb;}

Удаляем бесполезные символы:

1. Y0= ; i=1;

2-3.1. A→α, α (Y0 T)* = {a,b,c} Y1 = Y1 {B,D}; Y1Y0; i=2;

2-3.2. A→α, α (Y1 T)* = {B,D,a,b,c} Y2 = Y2 {A,B,D}; Y2Y1; i=3; 2-3.3. A→α, α (Y2 T)* = {A,B,D,a,b,c} Y3 = Y3 {S,A,B,C,D}; Y3Y2; i=4;

2-3.4. A→α, α (Y3 T)* = {S,A,B,C,D,a,b,c} Y4 = Y4 {S,A,B,C,D,F}; Y3Y2; i=5; 2-3.5. A→α, α (Y4 T)* = {S,A,B,C,D,F,a,b,c} Y5 = Y5 {S,A,B,C,D,F}; Y4=Y5;

4.N’=Y5={S,A,B,C,D,F}; T’=T={a,b,c}; S’=S={S};

5.P’={ SaAB; AaA | bB; BACb | b; CA | bA | cC; Da | c | Fb; FBC | AС;}

Удаляем недостижимые символы:

1.Y0={S}; i=1;

2-3.1. A Y0={S}: A→αxβ, α,β V*, x V Y1 = Y1 {a,A,B} {S}={a,A,B,S}; Y1Y0; i=2;

2-3.2. A Y1={a,A,B,S}: A→αxβ, α,β V*, x V Y2 = Y2 {a,A,B,b,C} {a,A,B,S}={a,b,A,B,C,S}; Y2Y1; i=3;

2-3.3. A Y2={a,b,A,B,C,S}: A→αxβ, α,β V*, x V Y3 = Y3 {a,A,B,b,C,c} {a,b,A,B,C,S}={a,b,c,A,B,C,S}; Y3Y2; i=4; 2-3.4. A Y3={a,b,c,A,B,C,S}: A→αxβ, α,β V*, x V Y4 = Y4 {a,A,B,b,C,c} {a,b,c,A,B,C,S}={a,b,c,A,B,C,S}; Y4=Y3;

4.N’=NYi={A,B,C,S}; T’=TYi= {a,b,c}; S’=S={S}

5.pi: A→α, A,α Yi; P’={ SaAB; AaA | bB; BACb | b; CA | bA | cC; }

Алгоритм устранения λ-правил. Алгоритм работает со специальным множеством нетерминальных символов Yi. Вначале это нетерминалы, допускающие λ-правила. Затем оно итерационно пополняется, после чего изменяется набор правил грамматики для нетерминалов этого множества.

1.Y0 ={ A: (A→λ)}; i=1;

2.A: (A→α) P, α Yi-1* Yi = Yi-1 {A}; т.е на каждом шаге включаются нетерминалы из левых частей правил, в правых частях которых только нетерминалы, включенные на предыдущем шаге;

3.Если YiYi-1, то i=i+1 и перейти к шагу 2

4.N’=N; T’=T; S’=S; P’=P\{A→λ};

5.pi P: AX1β1X2β2…Xnβn, Xj Yi P=P {AW1β1W2β2…Wnβn: Wk={{Xk либо λ, если Xk Yi}{Xk, если Xk Yi}}\ {A→λ, AA;}}. Т.е. для всех правил, в правых частях которых встречаются нетерминалы из множества Yi к правилам добавляется множество, в котором правые части представляют собой все возможные комбинации, в которых эти нетерминалы заменяются на λ.

6.Если S Yi N’=N’ {S’}, P’=P’ {S’→λ | S}, S’={S’}; т.е если λ L(G), то вводится новый нетерминал, который становится аксиомой и два новых правила

Пример. G({a,b,c},{A,B,C,S},P,S); P:{SAaB | aB | cC; AAB | a | b | B; BBa | λ; CAB | c;} 1. Y0 ={B}; i=1;

2-3.1. (AB), B Y0* Y1 = Y0 {A}={A,B}; Y1Y0; i=2;

2-3.2. (CAB; AAB; AB), A,B Y1* Y2 = Y1 {A,B,C}={A,B,C}; Y2Y1; i=3; 2-3.2. ( CAB; AAB; AB), A,B Y2* Y3 = Y2 {A,B,C}={A,B,C}; Y3=Y2;

4. N’=N={A,B,C,S}; T’=T={a,b,c}; P’={SAaB | aB | cC; AAB | a | b | B; BBa; CAB | c;}

5.1.SAaB, A,B Y3; P=P {SAaB | Aa | aB | a};

5.2.SaB; B Y3; P=P {SaB | a};

5.3.ScC; C Y3; P=P {ScC | c};

5.4.AAB; A,B Y3; P=P {AAB | A | B}\{AA};

5.5.AB; B Y3; P=P {AB};

5.6.BBa; B Y3; P=P { BBa | a};

5.7.CAB; A,B Y3; P=P { CAB | A | B};

6. S Y3 P’={ SAaB | aB | cC | Aa | a | c; AAB | a | b | B; BBa | a; CAB | c | A | B;}

Алгоритм устранения цепных правил. Для каждого нетерминала X строится специальное множество цепных символов Yx, на основе которых выполняется преобразование правил грамматики.

1.X N:

2.Yx0={X}; i=1;

3.pk P: AB, A Yxi-1 Yxi= Yxi-1 {B}; т.е. включаются все нетерминалы, которые непосредственно выводятся из нетерминалов множества, полученного на предыдущем шаге;

4.Если Yxi Yxi-1, то i=i+1, и перейти к шагу 3;

5.Yx=Yxi\{X};

6.N’=N; T’=T; P’=P\{AB}; S’=S;

7.pi P’: A→α P’=P’ {B→α}, A YB, BA; Идет замена цепных правил непосредственно на нетерминал-источник.

Пример. G=({+,-,/,*,a,b},{S,T,E},P,S); P={SS+T | S-T | T; TT*E | T/E | E; E(S) | a | b};

1.1.Ys:

2.1.Ys0={S}; i=1;

3-4.1.1. ST, S Ys0 Ys1= Ys0 {T}={S,T}; Ys1Ys0; i=2;

3-4.1.2. ST, TE, S,T Ys1 Ys2= Ys1 {T,E}={S,T,E}; Ys2Ys1; i=3; 3-4.1.3. ST, TE, S,T Ys2 Ys3= Ys2 {T,E}={S,T,E}; Ys3=Ys2;

5.1.Ys= Ys3\{S}={T,E};

1.2.YT:

2.2.YT0={T}; i=1;

3-4.2.1. TE, T YT0 YT1= YT0 {E}={T,E}; YT1YT0; i=2;

3-4.2.2. TE, T YT1 YT2= YT1 {E}={T,E}; YT2=YT1; 5.2. YT= YT2\{T}={E};

1.3. YE:

2.2. YE0={E}; i=1; 3-4.2.1. YE1= YE0 5.2. YE= YE1\{E}= ;

6. N’=N={S,T,E}; T’=T={+,-,/,*,a,b}; P’={SS+T | S-T; TT*E | T/E; E(S) | a | b}; S’=S={S};

7.1.SS+T | S-T; S YS, S YT S YE;

7.2.TT*E | T/E; T YS; P’=P’ { ST*E | T/E};

7.3.E(S) | a | b; E YS, E YT; P’=P’ { S(S) | a | b; T(S) | a | b };

P’={ SS+T | S-T | T*E | T/E | (S) | a | b; TT*E | T/E | (S) | a | b ; E(S) | a | b }

Устранение левой рекурсии. Любая КС-грамматика может быть как леворекурсивной, так и праворекурсивной, а также одновременно и право- и леворекурсивной. Полностью исключить рекурсию невозможно, однако один вид рекурсии можно заменить на другой. Значительные неудобства чаще всего создает левая рекурсия. Рассмотрим алгоритм ее устранения.

1.Ai N, i=1,2… |N|: т.е. для каждого нетерминального символа выполняются действия

2.pk P: AiBβ, B V, β V*, Ai B P’=P’ pk; N’=N’ Ai; т.е. если все правила для Ai не содержат левой рекурсии, они переносятся без изменений;

3.pk P: AiAiβ, β V* : Ai=Aiα1 | Aiα2 |…| Aiαm | β1 | β2 | βp, где j, 1jp, не βj=Akγ, ki P’=P’ {Ai→β1 | β2 |…|

βp | β1Ai’ | β2Ai’ |…| βpAi’; Ai→α1 | α2 |…| αm | α1Ai’ | α2Ai’ |…| αmAi’;}; N’=N’ {Ai, Ai’}; т.е. если есть хотя бы одно ле-

ворекурсивное правило для Ai все правила для Ai переписываются с добавлением нового нетерминала

4.Если i=|N|, то все нетерминалы рассмотрены, перейти к п.9;

5.i=i+1; j=1;

6.pk P: AiAjγ, γ V* P=P {Ai→ω1γ | ω2γ |…| ωqγ: {Aj→ω1 | ω2 |…| ωq} P’}\pk; т.е. для правил данного вида каж-

дое из них меняется на множество правил;

7.Если j=i-1, то перейти к п.2;

8.j=j+1; перейти к п.6

9.S’=S;

Пример G({a,b,c,d,z},{S,A,B,C},P,S); P:{ SAa; ABb; BCc | d; CAz | a;}

1. i=1; Ai=S;

2-3.1. SAa P’=P’ {SAa}; N’=N’ {S}; P’={ SAa } 4.1. i4

5.1. i=2; Ai=A; j=1; Aj=S;

6.1.1. правил в P вида ASγ нет

7.1.1. j=i-1, переход к п.2

2-3.2. ABb P’=P’ {ABb}; N’=N’ {A}; P’={ SAa; ABb } 4.2. i4

5.2. i=3; Ai=B; j=1; Aj=S;

6.2.1.правил в P вида BSγ нет

7.2.1.ji-1

8.2.1.j=2; Aj=A переход к п.6.

6.2.2.правил в P вида BAγ нет

7.2.2.j=i-1; переход к п.2

2-3.3. BCc | d P’=P’ { BCc | d }; N’=N’ {B};

P’={ SAa; ABb; BCc | d }

4.3. i4

 

 

5.3. i=4; Ai=C; j=1; Aj=S;

 

 

6.3.1. правил в P вида CSγ нет

 

 

7.3.1. ji-1

 

 

8.3.1. j=2; Aj=A переход к п.6.

 

 

6.3.2. {CAz} P, {ABb} P’ P=P {CBbz}\{CAz}

P={ SAa; ABb; BCc | d; CBbz | a}

7.3.2. ji-1

 

 

8.3.2. j=3; Aj=B переход к п.6.

6.3.3. {СBbz} P, {BCc | d} P’ P=P { C{Cc | d}bz = Ccbz | dbz}\{ СBbz }

7.3.3. j=i-1; переход к п.2

P={ SAa; ABb; BCc | d; CCcbz | dbz | a }

 

2-3.4. CCcbz | dbz | a P’=P’ { Cdbz | a | dbzD | aD; Dcbz | cbzD }; N’=N’ {C,D};

4.4. i=4; переход к п.9

P’={ SAa; ABb; BCc | d; Cdbz | a | dbzD | aD; Dcbz | cbzD }

9. S’=S;

N’={S,A,B,C,D}