Gramática indexada

Uma gramática indexada é uma gramática formal que descreve linguagens indexadas. Elas têm três conjuntos disjuntos de símbolos: os terminais e não-terminais comuns, assim como símbolos de indexação, que aparecem apenas em passos de derivação intermediários de numa pilha associada com os não-terminais daquele passo.


Definição

Formalmente, uma gramática indexada é uma 5-tupla ( N , T , F , P , S ) {\displaystyle (N,T,F,P,S)} onde

  1. N {\displaystyle N} é um alfabeto finito de variáveis ou símbolos não-terminais
  2. T {\displaystyle T} é um alfabeto finito de símbolos terminais
  3. F 2 N × ( N T ) {\displaystyle F\subseteq 2^{N\times (N\cup T)^{\ast }}} é o conjunto finito dos chamados bandeiras(ou mais conhecidos como flags) (cada flag é por si só um conjunto do que chamamos de produções de índice)
  4. P N × ( N F T ) {\displaystyle P\subseteq N\times (NF^{\ast }\cup T)^{\ast }} é o conjunto finito de produções
  5. S N {\displaystyle S\in N} é o símbolo da sentença

Derivações diretas são como se segue:

  • Uma produção p = ( A , X 1 η 1 X k η k ) {\displaystyle p=(A,X_{1}\eta _{1}\dots X_{k}\eta _{k})} de P {\displaystyle P} corresponde a um não-terminal A N {\displaystyle A\in N} seguida por sua (possivelmente vazia) cadeia de flags ζ F {\displaystyle \zeta \in F^{\ast }} . No contexto, γ A ζ δ {\displaystyle \gamma A\zeta \delta } , via P {\displaystyle P} , deriva para γ X 1 θ 1 X k θ k δ {\displaystyle \gamma X_{1}\theta _{1}\dots X_{k}\theta _{k}\delta } , onde where θ i = η i ζ {\displaystyle \theta _{i}=\eta _{i}\zeta } se X i {\displaystyle X_{i}} fosse um não-terminal e a palavra vazia, caso contrário. As flags velhas de A {\displaystyle A} são, portanto, copiadas para cada não-terminal novo produzido por P {\displaystyle P}
  • Uma produção de índice p = ( A , X 1 X k ) f {\displaystyle p=(A,X_{1}\dots X_{k})\in f} corresponde a A f ζ {\displaystyle Af\zeta } (a flag de onde ela se origina deve corresponder ao primeiro símbolo seguindo o não-terminal) e copia o restante da cadeira de índices ζ {\displaystyle \zeta } para cada novo terminal: γ A f ζ δ {\displaystyle \gamma Af\zeta \delta } deriva para γ X 1 θ 1 ζ X k θ k ζ δ {\displaystyle \gamma X_{1}\theta _{1}\zeta \dots X_{k}\theta _{k}\zeta \delta } , onde θ i {\displaystyle \theta _{i}} é a palavra vazia quando X i {\displaystyle X_{i}} é um não-terminal e ζ {\displaystyle \zeta } caso contrário.

Descrição

Uma cadeia com um símbolo não-terminal X {\displaystyle X} com alguns símbolos de indexação a b c {\displaystyle abc} na sua pilha pode ser denotada como α X [ a b c ] β {\displaystyle \alpha X[abc]\beta } (usando [ e ] como metassímbolos para denotar a pilha). Numa gramática indexada, a aplicação de uma regra de produção como X [ σ ] γ Y [ σ ] δ Z [ σ ] η {\displaystyle X[\sigma ]\to \gamma Y[\sigma ]\delta Z[\sigma ]\eta } reescreveria a cadeia por trocar X [ a b c ] {\displaystyle X[abc]} por γ Y [ a b c ] δ Z [ a b c ] η {\displaystyle \gamma Y[abc]\delta Z[abc]\eta } , que copia os símbolos da pilha a b c {\displaystyle abc} de X {\displaystyle X} para cada não-terminal em seu lugar - Y {\displaystyle Y} e Z {\displaystyle Z} neste caso. No processo, um símbolo pode ser empilhado, ou retirado, da pilha, antes dela ser copiada para os não-terminais introduzidos, que poderiam ser especificados na regra para a operação de reescrita.

Exemplo

Na prática, pilhas de índices podem contar e lembrar quais regras foram aplicadas e em que ordem. Por exemplo, gramáticas indexadas podem descrever a linguagem sensível ao contexto de triplas de palavras { w w w : w { a , b } } {\displaystyle \{www:w\in \{a,b\}^{*}\}} :

S [ σ ] S [ σ f ]   |   S [ σ g ] {\displaystyle S[\sigma ]\to S[\sigma f]~|~S[\sigma g]}

S [ σ ] T [ σ ] T [ σ ] T [ σ ] {\displaystyle S[\sigma ]\to T[\sigma ]T[\sigma ]T[\sigma ]}

T [ σ f ] T [ σ ] a {\displaystyle T[\sigma f]\to T[\sigma ]a}

T [ σ g ] T [ σ ] b {\displaystyle T[\sigma g]\to T[\sigma ]b}

T [ ] ϵ {\displaystyle T[]\to \epsilon }

A derivação de a b b a b b a b b {\displaystyle abbabbabb} é, então:

S [ ] S [ f ] S [ f g ] S [ f g g ] T [ f g g ] T [ f g g ] T [ f g g ] {\displaystyle S[]\to S[f]\to S[fg]\to S[fgg]\to T[fgg]T[fgg]T[fgg]}

T [ f g ] b T [ f g g ] T [ f g g ] T [ f ] b b T [ f g g ] T [ f g g ] T [ ] a b b T [ f g g ] T [ f g g ] {\displaystyle \to T[fg]bT[fgg]T[fgg]\to T[f]bbT[fgg]T[fgg]\to T[]abbT[fgg]T[fgg]}
a b b T [ f g g ] T [ f g g ] a b b a b b T [ f g g ] a b b a b b a b b {\displaystyle \to abbT[fgg]T[fgg]\to \dotsb \to abbabbT[fgg]\to abbabbabb}

Gramáticas indexadas lineares

Gerald Gazdar definiu uma segunda classe, as gramáticas indexadas lineares, por requerer que no máximo um não-terminal em cada produção seja especificado como recebendo a pilha, enquanto que em uma gramática indexada normal, todos os não-terminais recebem cópias da pilha. Ele mostrou que essa nova classe de gramáticas define uma classe de linguagens estritamente menor, as gramáticas levemente sensíveis ao contexto. Uma associação com uma gramática indexada linear pode ser decidida em tempo polinomial.

A linguagem { w w w : w { a , b } } {\displaystyle \{www:w\in \{a,b\}^{*}\}} é gerada por uma gramática indexada, mas não por uma gramática indexada linear, enquanto que { a n b n c n | n 1 } {\displaystyle \{a^{n}b^{n}c^{n}|n\geq 1\}} é gerada por uma gramática indexada linear.

Exemplo

Supondo que σ {\displaystyle \sigma } denota uma coleção arbitrária de símbolos de pilha, podemos definir uma gramática para a linguagem L = { a n b n c n | n 1 } {\displaystyle L=\{a^{n}b^{n}c^{n}|n\geq 1\}} como

S [ σ ] a S [ σ f ] c {\displaystyle S[\sigma ]\to aS[\sigma f]c}

S [ σ ] T [ σ ] {\displaystyle S[\sigma ]\to T[\sigma ]}

T [ σ f ] T [ σ ] b {\displaystyle T[\sigma f]\to T[\sigma ]b}

T [ ] ϵ {\displaystyle T[]\to \epsilon }

Para derivar a cadeia a b c {\displaystyle abc} temos os passos S [ ] a S [ f ] c a T [ f ] c a T [ ] b c a b c {\displaystyle S[]\to aS[f]c\to aT[f]c\to aT[]bc\to abc} .

Similarmente, para a a b b c c {\displaystyle aabbcc} : S [ ] a S [ f ] c a a S [ f f ] c c a a T [ f f ] c c a a T [ f ] b c c a a T [ ] b b c c a a b b c c {\displaystyle S[]\to aS[f]c\to aaS[ff]cc\to aaT[ff]cc\to aaT[f]bcc\to aaT[]bbcc\to aabbcc} .

Poder computacional

As linguagens linearmente indexadas são um subconjunto das linguagens indexadas, e todas as GIs podem ser gravadas como GIs, tornando as GILs estritamente menos poderosas que as GIs. Uma conversão de uma GIL para uma GI é relativamente simples. Regras de uma GIL normalmente parecem-se com X [ σ ] α Y [ σ ] β {\displaystyle X[\sigma ]\to \alpha Y[\sigma ]\beta } , módulo a parte do empilha/desempilha de uma regra de reescrita. Os símbolos α {\displaystyle \alpha } e β {\displaystyle \beta } representam cadeias de símbolos terminais/não-terminais, e qualquer símbolo não-terminal em qualquer deve ter uma pilha vazia, pela definição de uma GIL. Isso é, obviamente, contrário em relação a como as GIs estão definidas: numa GI, os não-terminais cujas pilhas não estão sendo empilhadas ou desempilhadas devem ter exatamente a mesma pilha que o não-terminal reescrito. Assim, de alguma forma, precisamos ter não-terminais em α {\displaystyle \alpha } e β {\displaystyle \beta } que, mesmo tendo pilhas não-vazias, comportem-se como se tivessem pilhas vazias.

Vamos considerar a regra X [ σ ] Y [ ] Z [ σ f ] {\displaystyle X[\sigma ]\to Y[]Z[\sigma f]} como um exemplo. Ao converter isso para uma GI, o substituto para Y [ ] {\displaystyle Y[]} deve ser algum Y [ σ ] {\displaystyle Y^{\prime }[\sigma ]} que se comporta exatamente como Y [ ] {\displaystyle Y[]} independentemente do que σ {\displaystyle \sigma } seja. Para alcançarmos isso, podemos simplesmente ter um par de regras que pega qualquer Y [ σ ] {\displaystyle Y^{\prime }[\sigma ]} onde σ {\displaystyle \sigma } não é vazio, e desempilhamos símbolos da pilha. Então, quando a pilha estiver vazia, pode ser reescrita como Y [ ] {\displaystyle Y[]} .

Y [ σ f ] Y [ σ ] {\displaystyle Y^{\prime }[\sigma f]\to Y^{\prime }[\sigma ]}

Y [ ] Y [ ] {\displaystyle Y^{\prime }[]\to Y[]}

Podemos aplicar isso em geral para derivar uma GI de uma GIL. Como, por exemplo, se a GIL para a linguagem { a n b n c n d m | n 1 , m 1 } {\displaystyle \{a^{n}b^{n}c^{n}d^{m}|n\geq 1,m\geq 1\}} é como se segue:

S [ σ ] T [ σ ] V [ ] {\displaystyle S[\sigma ]\to T[\sigma ]V[]}

V [ ] d   |   d V [ ] {\displaystyle V[]\to d~|~dV[]}

T [ σ ] a T [ σ f ] c   |   U [ σ ] {\displaystyle T[\sigma ]\to aT[\sigma f]c~|~U[\sigma ]}

U [ σ f ] b U [ σ ] {\displaystyle U[\sigma f]\to bU[\sigma ]}

U [ ] ϵ {\displaystyle U[]\to \epsilon }

A regra sentencial aqui não é uma regra de GI, mas utilizando o algoritmo de conversão acima, podemos definir novas regras para V {\displaystyle V^{\prime }} , mudando a gramática para:

S [ σ ] T [ σ ] V [ σ ] {\displaystyle S[\sigma ]\to T[\sigma ]V^{\prime }[\sigma ]}

V [ σ f ] V [ σ ] {\displaystyle V^{\prime }[\sigma f]\to V^{\prime }[\sigma ]}

V [ ] V [ ] {\displaystyle V^{\prime }[]\to V[]}

V [ ] d   |   d V [ ] {\displaystyle V[]\to d~|~dV[]}

T [ σ ] a T [ σ f ] c   |   U [ σ ] {\displaystyle T[\sigma ]\to aT[\sigma f]c~|~U[\sigma ]}

U [ σ f ] b U [ σ ] {\displaystyle U[\sigma f]\to bU[\sigma ]}

U [ ] ϵ {\displaystyle U[]\to \epsilon }

Cada regra agora se encaixa na definição de uma GI, na qual todos os não-terminais no lado direito de uma regra de reescrita recebem uma cópia da pilha do símbolo reescrito. As gramáticas indexadas são, portanto, capazes de descrever todas as linguagens que gramáticas linearmente indexadas conseguem descrever.

Equivalências

Vijay-Shanker and Weir (1994) demonstra que GILs, Gramáticas Categoriais Combinatórias, Gramáticas Árvore-Adjacentes, entre outras, são formalismos fracamente equivalentes, pois definem as mesmas linguagens de cadeia.

Gramáticas de Índice Distribuído(ID)

Outra forma de gramáticas indexadas, introduzida por Staudacher (1993), é a classe de gramáticas de Índice Distribuído. O que distingue GIDs de gramáticas indexadas de Ahos é a propagação de índices. Diferentemente dos IGs, que distribuem toda a pilha de símbolos para todos os não-terminais durante a reescrita, GIDs dividem a pilha em sub-pilhas e distribuem as sub-pilhas para não-terminais selecionados.

O esquema geral para uma regra de distribuição binária de GID é da forma


X [ f 1 f i f j f n ] α Y [ f 1 f i ] β Z [ f j f n ] γ {\displaystyle X[f_{1}\dotso f_{i}f_{j}\dotso f_{n}]\to \alpha Y[f_{1}\dotso f_{i}]\beta Z[f_{j}\dotso f_{n}]\gamma }

Onde α {\displaystyle \alpha } , β {\displaystyle \beta } , and γ {\displaystyle \gamma } são cadeiras de terminais arbitrários. Para uma cadeira ternariamente distributiva:


X [ f 1 f i f j f k f l f n ] α Y [ f 1 f i ] β Z [ f j f k ] γ W [ f l f n ] η {\displaystyle X[f_{1}\dotso f_{i}f_{j}\dotso f_{k}f_{l}\dotso f_{n}]\to \alpha Y[f_{1}\dotso f_{i}]\beta Z[f_{j}\dotso f_{k}]\gamma W[f_{l}\dotso f_{n}]\eta }

E assim em diante para números maiores de não-terminais no lado direito da regra de reescrita. Geralmente, se existem N {\displaystyle N} não-terminais na direita de uma regra de reescrita, a pilha é particionada em N {\displaystyle N} formas diferentes e distribuída entre os novos não-terminais. Perceba que há um caso especial onde a partição é vazia, que torna a regra uma regra GIL. As DILs são, então, um superconjunto das LILs.



Teoria de autômatos: linguagem formal e gramática formal
Hierarquia
Chomsky
Gramática Linguagem Reconhecedor
Tipo-0 Irrestrita Recursivamente enumerável Máquina de Turing
-- -- Recursiva Máquina de Turing que sempre para
Tipo-1 Sensível ao contexto Sensível ao contexto Autômato linearmente limitado
Tipo-2 Livre de contexto Livre de contexto Autômato com pilha
Tipo-3 Regular Regular Autômato finito