Gramáticas LR(1)

Gerador de Analisador Sintático a partir da GIC.

Embora as gramáticas LR(0) proporcionem um algoritmo completo e eficiente para a análise sintática, as linguagens abrangidas não incluem expressões algébricas, pelo que é necessário considerar um esquema mais adequado.

Aqui que entram as gramáticas LR(1), que usam informação sobre o "proximo terminal não processado" (o avanço) para guiar o processo da análise sintática.

Item LR(1)

Seguindo a estrutura da apresentação das gramáticas LR(0), define-se:

  1. Itens, Itens Válidos e Fecho de um conjunto de itens.
  2. Autómato dos itens válidos.
  3. Condições LR(1).
  4. Tabela de Análise Sintática.
  5. Autómato de Pilha Reconhecedor.

Item LR(1). Item LR(1) Válido. Seja uma GIC.

Um Item LR(1) de tem a forma onde:

  • núcleo é um item LR(0).
  • símbolos de avanço .

O item LR(1) é válido para se, para cada existe uma derivação com .

O fecho de um conjunto de itens afeta os símbolos de avanço.

O Fecho LR(1) de um conjunto de itens LR(1) define-se recursivamente:

  • base .
  • passo Se então, para cada produção também onde
  • fecho nada mais pertence a .

Por exemplo, dada a GIC tem-se

Autómato Finito dos Itens LR(1) Válidos

Tal como nas gramáticas LR(0), os itens LR(1) válidos são reconhecidos por um AFD.

Autómato dos Itens LR(1) Válidos (AIV). Seja uma GIC qualquer e

O autómato dos itens LR(1) válidos de é o AFD tal que:

  • estado inicial .
  • transição Para cada ,

Por exemplo, para a GIC dada acima:

Diagrama do Autómato dos Itens LR(1) Válidos
Diagrama do Autómato dos Itens Válidos
Em cada estado os itens completos são assinalados com . O estado não está representado.

O cálculo de passo-a-passo:

  1. Como ocorre , é necessário adicionar os itens iniciais de . O núcleo é .
  2. Para calcular o avanço deste item, note-se que inicialmente portanto, pela definição de , .
  3. Portanto, o item LR(1) a acrescentar em é .
  4. Agora, de é preciso acrescentar os itens iniciais de . Os núcleos são e . O cálculo dos avanços é idêntico para estes dois itens.
  5. Estes itens resultam de . Pela definição de , .
  6. Portanto, são acrescentados dois itens LR(1): e .
  7. Do item , pelas razões anteriores, é necessário acrescentar dois itens LR(1): e .
  8. Torna a acontecer mas os itens que resultam já constam no e nada mais é acrescentado.
  9. Finalmente o fecho tem vários itens com o mesmo núcleo e que diferem apenas no avanço. Neste caso esses itens "fundem-se" num único, unindo os avanços:
    1. e fundem-se em .
    2. e fundem-se em .

Tabela de Análise Sintática LR(1)

Tal como no caso das gramáticas LR(0), os estados do AIV LR(1) permitem determinar se o processo da análise sintática pode, ou não, ser aplicado.

Para que a análise sintática seja determinista é necessário que os estados sejam livres de conflitos (redução/redução e redução/transferência). No caso das gramáticas LR(0), sem informação sobre os avanços, cada estado do AIV pode determinar ou uma única redução ou uma transferência. Nos AIV das gramáticas LR(1) os itens têm avanços, que proporcionam decisões mais informadas em cada caso.

No AIV acima, visto como um AIV LR(0), o estado tem um conflito redução/transferência. Mas o avanço do item restringe a aplicação da redução apenas quando o avanço na entrada é . Portanto não há conflito com uma eventual transferência de .

Em cada estado, cada avanço identifica a ação (reduzir, transferir, aceitar, rejeitar) no processo da análise sintática.

Portanto, a tabela de análise sintática LR(1) tem uma ação possível para cada símbolo terminal. Especificamente:

Tabela de Análise Sintática LR(1). (TAS LR(1)) Dada uma GIG e o seu AIV LR(1), a tabela de análise sintática LR(1) tem:

  • Para cada estado do AIV LR(1), uma linha, exceto para o estado .
  • Para cada símbolo , uma coluna que descreve a transição do AIV.
  • Para cada símbolo , uma coluna que, cruzada com a linha do estado , determina a ação:
    • aceitar (ou ) se contém um item completo de e se .
    • transferir (ou ) se contém um item .
    • reduzir (ou ) se contém o item completo , e .
    • rejeitar (omitido).

Por exemplo, A TAS LR(1) do exemplo acima é:

Comparando esta tabela com as obtidas nas TAS LR(0), a coluna ação é mais específica, considerando agora os símbolos de avanço e, portanto, a ação depende não só do estado no AIV mas também do próximo símbolo na entrada.

Numa TAS LR(1) mantém-se a necessidade de determinar, sem ambiguidade, cada ação no processo da análise sintática. Em relação ao caso LR(0), a escolha da ação depende não só do estado do AIV mas também do símbolo de avanço.

Quando esta informação (estado AIV + símbolo de avanço) não é suficiente para determinar uma única ação tem-se um conflito, que pode ser de dois tipos:

  • Conflito Redução/Redução LR(1): Num estado com dois itens completos em que os avanços se intersetam. Formalmente, se no AIV LR(1) existe um estado com dois itens completos distintos e e .
  • Conflito Redução/Transferência LR(1): Num estado com um item completo em que sai uma aresta "com um terminal" que está no avanço desse item completo. Formalmente, se no AIV LR(1) existe um item completo e um item e .

Teorema das Gramáticas LR(1). Uma GIC é LR(1) se e só se o seu AIV não tem conflitos redução/redução LR(1) nem redução/transferência LR(1).

Autómato de Pilha Reconhecedor LR(1)

Quando o AIV LR(1) de uma GIC está livre de conflitos é possível definir-se um autómato de pilha para reconhecer a linguagem gerada pela GIC. Além disso, para as palavras geradas/aceites, a observação da computação permite recuperar a derivação direita da respetiva palavra.

Autómato de Pilha Reconhecedor LR(1). Seja uma GIC LR(1) e o seu AIV LR(1). O Autómato de Pilha Reconhecedor LR(1) (APR LR(1)) de , que reconhece a linguagem gerada por , é com

  • estados de controlo: .
  • estados finais: .

e em que a transição, , é definida pelos seguintes elementos:

  • iniciar: .
  • avançar: Para cada então .
  • transferir: Para cada com um item em que e então .
  • reduzir: Para cada estado com um item completo com e para cada , quando no AIV existe a computação e então .
  • aceitar: Para cada estado com um item completo do símbolo inicial da GIC, se e quando no AIV existe a computação então

Alternativamente as transições do APR LR(1) podem ser descritas pela seguinte tabela:

Intuitivamente os estados do APR LR(1) refinam os do APR LR(0) com informação sobre o avanço. O estado "consulta" o símbolo de avanço (por exemplo, ) e encaminha a computação para o respetivo estado , onde os passos são feitos sob o pressuposto "o avanço é ".

A computação fica em até ser transferido da entrada para a pilha. Depois dessa transferência é necessário tornar a consultar o avanço (em ) e proceder de acordo com o novo avanço.

O símbolo marca o fím da entrada e é processado de acordo com esse pressuposto. Por exemplo, não há transições de para e só neste estado pode ocorrer a ação aceitar.

Continuando o exemplo anterior, a transição do APR LR(1) tem as seguintes arestas:

  • iniciar transições : .
  • avançar
  • transferir
  • reduzir
  • aceitar

que corresponde ao diagrama

Diagrama do APR LR(1)
Diagrama do APR
As arestas são avançar, reduzir e aceitar e são transferir.

Como é que este APR processa palavras? Por exemplo, é gerada pela GIC, enquanto que não.

Para o APR tem a computação que aceita e mostra a derivação . Quando à computação de , rejeita:


Com este exemplo termina a resolução do Problema Principal de ALP — Dada uma linguagem e uma palavra no mesmo alfabeto, determinar se de forma computável, eficiente e adequada.

  1. A linguagem é adequada se for formalmente definida por uma GIC LR(1).
  2. Dada uma GIC que gere a linguagem, a construção algorítmica do seu AIV LR(1) é eficiente.
  3. Pode-se verificar algoritmicamente e de forma eficiente se a GIC é LR(1), confirmando que nenhum estado do seu AIV LR(1) tem contradições. Nesse caso a linguagem é adequada.
  4. A construção do APR LR(1) a partir do AIV LR(1) é, também, algorítmica e eficiente.
  5. Dada uma palavra sobre o alfabeto da linguagem, o processamento pelo APR LR(1) é eficiente (e, claro, algorítmico). Adicionalmente, se a palavra está na linguagem, é possível recuperar a sua derivação na GIC para efeitos de processamento semântico.

Problema Principal de ALP

Resumindo, este processo define um algoritmo (qua pode ser implementado em qualquer linguagem de programação comum) que é eficiente e resolve o Problema Principal de ALP.

Gramáticas LALR(1)

Neste ponto é fácil melhorar o seguinte problema: a construção do AIV gera muitos estados, o que pode ter um efeito negativo no desempenho dos restantes passos.

Quando dois estados do AIV têm os mesmos núcleos e, eventualmente, avanços distintos, a fusão consiste em juntar esses dois estados num único, cujos itens são obtidos:

  • os núcleos são os mesmos;
  • cada avanço é a união dos avanços dos itens correspondentes.

Usando um exemplo anterior

Diagrama do Autómato dos Itens LR(1) Válidos
Núcleos Repetidos
Os estados e têm exatamente os mesmos núcleos.

O amalgamento deste AIV é

Autómato Amalgamado
Autómato Amalgamado
O estado resulta de fundir com . Neste exemplo não há mais fusões possíveis.

Formalmente:

Autómato Amalgamado. Seja um AIV LR(1).

Se for um conjunto de estados de com os mesmos núcleos, a fusão destes estados é o estado com os itens tais que .

Seja uma partição de tal que:

  • todos os estados de têm os mesmos núcleos e
  • se os núcleos dos estados de e são disjuntos. então

O autómato amalgamado é o autómato que resulta de fundir os estados com o mesmo conjunto de núcleos: com

  • estados de controlo .
  • transição se existe tal que .

Os autómatos amalgamados definem uma classe de gramáticas distinta de LR(1):

Gramática LALR(1). Uma GIC é LALR(1) se o seu autómato amalgamado satisfaz as condições LR(1): não tem conflitos redução/redução nem redução/transferência.

O principal interesse das gramáticas LALR(1) é, essencialmente, prático: Intuitivamente, são as gramáticas com "bons" AIV depois de amalgamados.