Gramática formal

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa

Em teoria das linguagens formais, uma gramática formal (algumas vezes simplesmente chamada de gramática) é um conjunto de regras de produção de cadeias em uma linguagem formal, ou seja, um objeto que permite especificar uma linguagem ou língua. As regras descrevem como formar cadeias ― a partir do alfabeto da linguagem ― que são válidas de acordo com a sintaxe da linguagem. Uma gramática não descreve significado das cadeias ou o que pode ser feito com elas em um contexto ― apenas suas formas.

A expressão "gramática formal" pode ter os sentidos:

A Teoria da Linguagem Formal, disciplina que estuda gramáticas e linguagens formais, é um ramo da Matemática Aplicada. Suas aplicações podem ser encontradas na Ciência da Computação Teórica, Linguística Teórica, Semântica Formal, Matemática Lógica, entre outras áreas.

Uma gramatica formal é uma conjunto de regras para se reescrever cadeias, tomando como partida um símbolo inicial, do qual se começa a reescrita. Portanto, uma gramática é normalmente encarada como um gerador de linguagem. Entretanto, ela também pode ser usada como uma base para um reconhecedor ― uma função em computação que determina se uma dada cadeia pertence à linguagem ou está gramaticalmente incorreta. Para descrever tais reconhecedores, a teoria da linguagem formal usa formalismos distintos, conhecidos como Teoria dos Autômatos. Um dos resultados mais interessantes da teoria dos autômatos é que não é possível desenhar um reconhecedor para certas linguagens formais.

Análise sintática é o processo de reconhecer uma elocução (cadeia em linguagem natural) quebrando-a em um conjunto de símbolos e analisando cada um de acordo com a gramática da linguagem. O significado das elocuções da maioria das linguagens está estruturado conforme a sintaxe de tal linguagem — prática conhecida como semântica composicional. Como resultado, o primeiro passo para descrever o significado de uma elocução de uma linguagem é quebrá-la parte por parte, e verificar a sua forma analítica (conhecida como "árvore de análise" em Ciência da Computação, e como "estrutura profunda" em gramática gerativa).

Exemplo introdutório[editar | editar código-fonte]

Uma gramática consiste, principalmente, de um conjunto de regras para transformação de cadeias. (Se ela apenas consistisse dessas regras, ela seria considerada um sistema semi-Thue). Para gerar uma cadeia na linguagem, começa-se com uma cadeia que consiste em apenas um símbolo inicial. As regras de produção são, então, aplicadas em uma ordem qualquer, até que uma cadeia que não contenha nem o símbolo inicial, nem os chamados símbolos não-terminais, seja produzida. Uma regra de produção é aplicada a uma cadeia substituindo-se uma ocorrência do lado esquerdo da gramática por uma do lado direito. A linguagem formada pela gramática consiste de todas as cadeias distintas que podem ser geradas dessa forma. Qualquer sequência particular de regras de produção sobre o símbolo inicial produz uma cadeia distinta na linguagem. Se existem várias maneiras de gerar a mesma cadeia, a gramática é chamada de ambígua.

Por exemplo, assumimos que o alfabeto consiste de a e b, o símbolo inicial é S, e temos as seguintes regras de produção:

1. S \rightarrow aSb
2. S \rightarrow ba

Então começamos com S, e podemos escolher uma regra pra aplicar a ele. Se nós escolhermos a regra 1, obteríamos a cadeia aSb. Se nós escolhermos a regra 1 outra vez, nós substituiríamos o S do aSb por aSb, e obteríamos a cadeia aaSbb. Se agora nós escolhermos a regra 2, nós substituiríamos o S do aaSbb por ba e obteríamos a cadeia aababb, terminando o processo. Nós podemos escrever essa série de escolhas mais suscintamente, usando símbolos: S \Rightarrow aSb \Rightarrow aaSbb \Rightarrow aababb. A linguagem da gramática é, então, o conjunto infinito \left \{a^nbab^n | n \ge 0 \right \} = \left \{ba, abab, aababb, aaababbb, ...\right \}, em que ak é a repetido k vezes (e n, em particular, representa o número de vezes que a regra de produção 1 foi aplicada).

Definição formal[editar | editar código-fonte]

A Sintaxe das Gramáticas[editar | editar código-fonte]

Na formalização de gramáticas generativas primeiramente proposta por Noam Chomsky nos anos de 1950,[1] [2] uma gramática G era composta pelos seguintes componentes:

  • Um conjunto finito N de símbolos não-terminais, que é disjunto das cadeias formadas a partir de G.
  • Um conjunto finito \Sigma de símbolos terminais que é disjunto de N.
  • Um conjunto finito P de regras de produção, cada uma com a forma (\Sigma \cup N)^{*} N (\Sigma \cup N)^{*} \rightarrow (\Sigma \cup N)^{*} onde {*} é o operador de Kleene e \cup denota a união entre conjuntos. Isso significa que cada regra de produção mapeia uma cadeia de símbolos para outra, onde a primeira contém um número arbitrário de símbolos, dos quais pelo menos um é não-terminal. A segunda cadeia consistiria somente da cadeia vazia — ou seja, não contêm símbolos - sendo, às vezes, representada com notações especiais pra evitar confusão (\Lambda, e ou \epsilon).
  • Um símbolo diferenciado S \in N que é o símbolo inicial, também chamado de símbolo sentença.

Uma gramática é formalmente definida como uma tupla (N, \Sigma, P, S). Tal gramática formal é, às vezes, chamada de sistema de reescrita ou de gramática de estrutura de frase na Literatura.[3] [4]

A Semântica das Gramáticas[editar | editar código-fonte]

A operação sobre uma gramática pode ser definida em termos das relações entre cadeias:

  • Dada uma gramática G = (N, \Sigma, P, S), a relação binária \Rightarrow_G (lê-se G deriva em um passo) sobre cadeias de (\Sigma \cup N)^{*} é definida por: x \Rightarrow_G y \mbox{ iff } \exists u, v, p, q \in (\Sigma \cup N)^*: (x = upv) \wedge (p \rightarrow q \in P) \wedge (y = uqv)
  • A relação  {\Rightarrow_G}^* (lê-se G deriva em 0 ou mais passos) é definida como o fecho reflexivo-transitivo de  \Rightarrow_G.
  • Uma forma sentencial é um membro de (\Sigma \cup N)^* que pode ser derivado, partindo do símbolo inicial S, em um número finito de passos; ou seja, uma forma sentencial é um membro de \{ w \in (\Sigma \cup N)^* \mid S {\Rightarrow_G}^* w \}. Uma forma sentencial que não contém símbolos não-terminais (i.e. é um membro de \Sigma^*) é chamada de sentença.
  • linguagem de G, denotada como \boldsymbol{L}(G), é definida como todas as sentenças que podem ser derivadas em um número finito de passos partindo do símbolo inicial S; ou seja, o conjunto \{ w \in \Sigma^* \mid S {\Rightarrow_G}^* w \}.

Note que a gramática G = (N, \Sigma, P, S) é efetivamente um sistema semi-Thue (N \cup \Sigma, P), pois reescreve cadeias exatamente do mesmo jeito; a única diferença está no fato de que nós distinguimos especificamente símbolos não-terminais que devem ser reescritos nas regras de reescrita, e estamos apenas interessados em reescritas a partir do símbolo inicial S designado para cadeias sem símbolos não-terminais.

Exemplo[editar | editar código-fonte]

Para esses exemplos, as linguagens formais estão especificadas utilizando a notação de construção de conjuntos.

Considere a gramática G onde N = \left \{S, B\right \}, \Sigma = \left \{a, b, c\right \}, S é o símbolo inicial, e P é composto pelas seguintes regras de produção:

1. S \rightarrow aBSc
2. S \rightarrow abc
3. Ba \rightarrow aB
4. Bb \rightarrow bb

Essa gramática define a linguagem L(G) = \left \{ a^{n}b^{n}c^{n} | n \ge 1 \right \} onde a^{n} denota uma cadeia formada por n consecutivos a's. Dessa forma,a linguagem é o conjunto de cadeias que é composta por um ou mais a's, seguidos pelo mesmo número de b's, seguidos pelo mesmo número de c's.

Alguns exemplos de derivação de cadeias em L(G) são:

  • \boldsymbol{S} \Rightarrow_2 \boldsymbol{abc}
  • \boldsymbol{S} \Rightarrow_1 \boldsymbol{aBSc} \Rightarrow_2 aB\boldsymbol{abc}c \Rightarrow_3 a\boldsymbol{aB}bcc \Rightarrow_4 aa\boldsymbol{bb}cc
  • \boldsymbol{S} \Rightarrow_1 \boldsymbol{aBSc} \Rightarrow_1 aB\boldsymbol{aBSc}c \Rightarrow_2 aBaB\boldsymbol{abc}cc \Rightarrow_3 a\boldsymbol{aB}Babccc \Rightarrow_3 aaB\boldsymbol{aB}bccc  \Rightarrow_3 aa\boldsymbol{aB}Bbccc \Rightarrow_4 aaaB\boldsymbol{bb}ccc \Rightarrow_4 aaa\boldsymbol{bb}bccc
(Note a notação: P \Rightarrow_i Q lê-se "A cadeia P gera a cadeia Q pela regra de produção i ". A parte gerada é, a cada vez, indicada em negrito.)

A Hierarquia de Chomsky[editar | editar código-fonte]

Quando Noam Chomsky formalizou as gramáticas generativas pela primeira vez em 1956,[1] ele as classificou em tipos hoje conhecidos como pertencentes à hierarquia de Chomsky. A diferença entre esses tipos é que eles têm cada vez mais rigorosas regras de produção e podem expressar menos linguagens formais. Dois importantes tipos são gramáticas livres de contexto (Tipo 2) e gramáticas regulares (Tipo 3). As linguagens que podem ser descritas com tais gramáticas são chamadas linguagens livres de contexto e linguagens regulares, respectivamente. Apesar de menos poderosas que gramáticas irrestritas (Tipo 0),que podem, na verdade, expressar qualquer linguagem que pode ser aceita por uma Máquina de Turing, esses dois tipos restritos de gramática são mais frequentemente usadas porque analisadores para eles podem ser eficientemente implementados.[5] Por exemplo, todas linguagens regulares podem ser reconhecidas por uma máquina de estados finitos, e para alguns subconjuntos úteis de gramáticas de livre-contexto existem algoritmos bem conhecidos para gerar analisadores sintáticos eficientes para reconhecer as linguagens correspondentes às gramáticas geradas.

Gramáticas de livre-contexto[editar | editar código-fonte]

Uma gramática livre de contexto é uma gramática em que o lado esquerdo de cada regra de produção é formado apenas por um único símbolo não-terminal. Essa restrição é não-trivial; nem todas as linguagens podem ser geradas por gramáticas livre de contexto. As que podem são chamadas de linguagens livre de contexto.

A linguagem L(G) = \left \{ a^{n}b^{n}c^{n} | n \ge 1 \right \} definida abaixo não é uma linguagem livre de contexto, e isso pode ser rigorosamente provado utilizando o lema do bombeamento para linguagens livres de contexto, mas, por exemplo, a linguagem \left \{ a^{n}b^{n} | n \ge 1 \right \} (pelo menos 1 a seguido pelo mesmo número de b's) é livre de contexto, pois pode ser definida por uma gramática G_2 com N=\left \{S\right \}, \Sigma=\left \{a,b\right \}, S símbolo inicial, e as seguintes regras de produção:

1. S \rightarrow aSb
2. S \rightarrow ab

Uma linguagem livre de contexto pode ser reconhecida em tempo O(n^3) (veja: notação Big O) por um algoritmo como algoritmo de Earley. Isso significa que, para toda linguagem livre de contexto, uma máquina cuja entrada é uma cadeia pode ser construída, determinando em tempo O(n^3) se a cadeia é membro da linguagem, onde n é o comprimento da cadeia.[6] Linguagens determinísticas livres de contexto são um subconjunto de linguagens livres de contexto que podem ser reconhecidas em tempo linear.[7] Existem vários algoritmos que se focam nesse conjunto de linguagensr ou algum subconjunto dele.

Gramáticas regulares[editar | editar código-fonte]

Nas gramáticas regulares, o lado esquerdo é composto unicamente por símbolos não-terminais, mas o lado direito também é restrito. O lado direito pode ser a cadeia vazia, ou um simples símbolo terminal, ou um símbolo terminal seguido de um símbolo não-terminal e nada mais. (às vezes é usada uma definição mais ampla: pode-se permitir cadeias mais longas de terminais ou únicos não-terminais sem nada mais, tornando as linguagens mais fáceis de se denotar).

A linguagem \left \{ a^{n}b^{n} | n \ge 1 \right \} definida abaixo não é regular, mas a linguagem \left \{ a^{n}b^{m} \,| \, m,n \ge 1 \right \} (pelo menos um a seguido por pelo menos um b, onde os números podem ser diferentes) é, já que pode ser definida pela gramática G_3 com N=\left \{S, A,B\right \}, \Sigma=\left \{a,b\right \}, S o símbolo inicial, e as seguintes regras de produção:

  1. S \rightarrow aA
  2. A \rightarrow aA
  3. A \rightarrow bB
  4. B \rightarrow bB
  5. B \rightarrow \epsilon

Todas as linguagens geradas por gramáticas regulares podem ser reconhecidas em tempo linear por uma máquina de estados finitos. Contudo, na prática, gramáticas regulares são comumente expressas usando expressões regulares. Algumas formas de expressão regular usadas na prática não geram rigorosamente linguagens regulares e não apresentam performance linear de reconhecimento devido a aquelas divergências.

Outras formas de gramáticas generativas[editar | editar código-fonte]

Muitas extensões e variações sobre a hierarquia original de Chomsky de gramáticas formais têm sido desenvolvidas, tanto pelos linguistas quanto pelos cientistas da computação, usualmente com o objetivo de aumentar seu poder de expressividade ou de torná-las mais facilmente analisáveis. Algumas formas de gramática desenvolvidas incluem:

  • Gramáticas árvore-adjacente aumenta a expressividade de gramáticas generativas convencionais ao permitir que regras de reescrita operem sobre árvore de análise sintática em vez de apenas cadeias.[8]
  • Gramáticas de afixo[9] e gramáticas de atributos[10] [11] permitem que regras de reescrita sejam ampliadas com uso de atributos e operações semânticas, úteis para aumentar a expressividade da gramática e para construir ferramentas práticas para tradução de linguagens.

Gramáticas recursivas[editar | editar código-fonte]

Não se confunda com linguagem recursiva

Uma gramática recursiva é uma gramática que contém regras de produção que são recursivas. Por exemplo, uma uma gramática para uma linguagem livre de contexto é recursiva à esquerda se existe símbolo não-terminal A que pode ser colocado através das regras de produção para produzir uma cadeia com A como o símbolo mais à esquerda.[12] Todos os tipos de gramática da Hierarquia de Chomsky podem ser recursivas.

Gramáticas analíticas[editar | editar código-fonte]

Apesar de haver um enorme estoque de literatura sobre algoritmos de análise sintática, a maioria desses algoritmos assume que a linguagem a ser analisada é, inicialmente, descrita por meio de uma gramática formal generativa, e que o objetivo é transformar essa gramática em um analisador sintático que funciona. Ou seja, uma gramática generativa não corresponde, de maneira alguma, ao algoritmo usado para analisar uma linguagem, e vários algoritmos têm restrições diferentes sobre a forma de regras de produção que são consideradas bem formadas.

Uma abordagem alternativa é formalizar a linguagem em termos de uma gramática analítica, o que corresponderia mais diretamente à estrutura e semântica de um analisador sintático para a linguagem. Exemplos de formalismos de gramática analítica incluem os seguintes:

  • A linguagem de máquina implementa diretamente uma gramática analítica irrestrita. Regras de substituição são usadas para transformar uma entrada e produzir saídas e comportamento. O sistema também pode produzir the lm-diagram que mostra o que acontece quando as regras de uma gramática analítica irrestrita estão sendo aplicadas.
  • Linguagem de análise top-down: um formalismo de gramática analítica altamente minimalista desenvolvido no começo dos anos de 1970 para estudar o comportamento de analisadores sintáticos top-down.[13]
  • Gramática de ligação: uma forma de gramática analítica desenhada para a linguística, que deriva a estrutura sintática através do exame das relações de posicionamento entre pares de palavras.[14] [15]
  • Gramática de análise de expressões: uma generalização mais recente de uma linguagem de análise top-down. Desenhada levando-se em conta as necessidades práticas de expressividade de uma linguagem de programação e de compiladores.[16]

Referências

  1. a b doi: 10.1109/TIT.1956.1056813
    Esta citação será automaticamente completada em poucos minutos. Você pode furar a fila ou completar manualmente
  2. Chomsky, Noam. Syntactic Structures. The Hague: Mouton, 1957.
  3. Ginsburg, Seymour. Algebraic and automata theoretic properties of formal languages. [S.l.]: North-Holland, 1975. 8–9 pp. ISBN 0-7204-2506-9
  4. Harrison, Michael A.. Introduction to Formal Language Theory. Reading, Mass.: Addison-Wesley Publishing Company, 1978. 13 pp. ISBN 0-201-02955-3
  5. Grune, Dick & Jacobs, Ceriel H., Parsing Techniques – A Practical Guide, Ellis Horwood, England, 1990.
  6. Earley, Jay, "An Efficient Context-Free Parsing Algorithm," Communications of the ACM, Vol. 13 No. 2, pp. 94-102, February 1970.
  7. doi:10.1016/S0019-9958(65)90426-2
    Esta citação será automaticamente completada em poucos minutos. Você pode furar a fila ou completar manualmente
  8. Joshi, Aravind K., et al., "Tree Adjunct Grammars," Journal of Computer Systems Science, Vol. 10 No. 1, pp. 136-163, 1975.
  9. Koster , Cornelis H. A., "Affix Grammars," in ALGOL 68 Implementation, North Holland Publishing Company, Amsterdam, p. 95-109, 1971.
  10. Knuth, Donald E., "Semantics of Context-Free Languages," Mathematical Systems Theory, Vol. 2 No. 2, pp. 127-145, 1968.
  11. Knuth, Donald E., "Semantics of Context-Free Languages (correction)," Mathematical Systems Theory, Vol. 5 No. 1, pp 95-96, 1971.
  12. Notes on Formal Language Theory and Parsing, James Power, Department of Computer Science National University of Ireland, Maynooth Maynooth, Co. Kildare, Ireland.JPR02
  13. Birman, Alexander, The TMG Recognition Schema, Doctoral thesis, Princeton University, Dept. of Electrical Engineering, February 1970.
  14. Sleator, Daniel D. & Temperly, Davy, "Parsing English with a Link Grammar," Technical Report CMU-CS-91-196, Carnegie Mellon University Computer Science, 1991.
  15. Sleator, Daniel D. & Temperly, Davy, "Parsing English with a Link Grammar," Third International Workshop on Parsing Technologies, 1993. (Revised version of above report.)
  16. Ford, Bryan, Packrat Parsing: a Practical Linear-Time Algorithm with Backtracking, Master’s thesis, Massachusetts Institute of Technology, Sept. 2002.

Ligações externas[editar | editar código-fonte]

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