Tanto os métodos descendentes como os ascendentes constroem a árvore de derivação da esquerda...

44
Tanto os métodos descendentes como os ascendentes constroem a árvore de derivação da esquerda para direita. A escolha das regras basea-se na cadeia a ser reconhecida, que é lida da esquerda para a direita. Analisador sintático: Tipos de análises sintáticas

Transcript of Tanto os métodos descendentes como os ascendentes constroem a árvore de derivação da esquerda...

Tanto os métodos descendentes como os ascendentes constroem a árvore de derivação da esquerda para direita.

A escolha das regras basea-se na cadeia a ser reconhecida, que é lida da esquerda para a direita.

Analisador sintático: Tipos de análises sintáticas

Analisador sintático: Análise Sintática Ascendente

Na análise sintática ascendente a construção da árvore de derivação para uma determinada cadeia (lexema) começa pelas folhas da árvore e segue em direção de sua raiz.

Caso seja obtida uma árvore cuja raiz tem como rótulo o símbolo inicial da gramática, e na qual a sequência dos rótulos das folhas forma a cadeia dada, então a cadeia é uma sentença da linguagem, e a árvore obtida é a sua árvore de derivação.

Embora a árvore de derivação seja usada para descrever os métodos de análise, na prática ela não precisa ser efetivamente construída.

A única estrutura de dados necessária para o processo de análise sintática é uma pilha.

Guarda informação sobre os nós da árvore dederivação relevantes em cada fase do processo

Analisador sintático: Análise Sintática Ascendente

Analisador sintático: Análise Sintática Ascendente

Definição:

Redução de uma cadeia → partir das folhas em direção à raiz de uma árvore de derivação.

A cada passo, procura-se reduzir uma cadeia (ou sub-cadeia) ao seu símbolo de origem, objetivando-se atingir o símbolo inicial da gramática.

Analisador sintático: Análise Sintática Ascendente

Etapas da redução de uma cadeia

1) Toma-se uma determinada cadeia .

2) Procura-se por uma sub-cadeia a1,a2,...an de que possa ser substituída pelo seu símbolo de origem . Ou seja, → a1,a2,...an . Assim a1,a2,...an b = a1 a2.

Analisador sintático: Análise Sintática Ascendente

3) Repetir o passo (2) até que = símbolo inicial da gramática.

Caso isso não seja possível, tem-se que a cadeia analisada não pertence a linguagem especificada.

Analisador sintático: Análise Sintática Ascendente

Analisador sintático: Análise Sintática Ascendente

Outro exemplo a cadeia x = a+a*a e produção

Nesse caso, a ordem das regras correspondea uma derivação àdireita, porém de trás para frente

Analisador sintático: Análise Sintática Ascendente

Problemas:

Os maiores problemas na análise sintática ascendente residem na dificuldade de determinação de qual parcela da cadeia (sub-cadeia) que deverá ser reduzida;

Qual será a produção a ser utilizada na redução, para o caso de existirem mais do que uma possibilidade.

Analisador sintático: Análise Sintática Descendente

Na análise sintática descendente tem-se procedimento inverso ao da ascendente.

Aqui a análise parte da raiz da árvore de derivação e segue em direção as folhas, ou seja,

a partir do símbolo inicial da gramática vai-se procurando substituir os símbolos não-terminais de forma a obter nas folhas da árvore a cadeia desejada.

Analisador sintático: Análise Sintática DescendenteEtapas da redução de uma cadeia

1) Toma-se uma determinada cadeia b e o símbolo inicial da gramática.

2) Procura-se por uma regra de derivação que permita derivar em sua totalidade ou pelo menos se aproximar desta.

3) Repetir o passo (2) até que a cadeia não apresente mais símbolos não terminais, verificando se a cadeia obtida coincide com .

Não havendo coincidência, a cadeia analisada não pertence a linguagem especificada.

Exemplo

Considere a seguinte gramática

Analisador sintático: Análise Sintática Descendente

e a cadeia x = a+a*a

Analisador sintático: Análise Sintática Descendente

Analisador sintático: Análise Sintática Descendente

Problemas:

Embora apresente os mesmos problemas que a analise sintática ascendente, implementa facilmente compiladores para linguagens obtidas de gramáticas LL(1)(análise da cadeia da esquerda para a direita e derivações esquerdas observando apenas o primeiro símbolo da cadeia para decidir qual regra de derivação será utilizada).

Gramática: Derivações e Precedência

Definição 1Ambigüidade refere-se geralmente a confusão na GLCSobrecarga (Overloading) pode criar ambigüidade f(17)Em algumas linguagens, f pode ser uma função ou uma macroPara eliminar ambigüidade é preciso conhecer contexto• Requer valores de declarações• É uma questão de tipo, uma gramática livre de contexto não é suficiente• Requer uma solução extra-gramatical (não em GLC)

Ambigüidade: Uma gramática que produz mais de uma árvore de derivação para alguma sentença é considerada ambígua

Uma GLC é ambígua se permitir mais de 1derivação mais à esquerda ou mais de 1derivação mais à direita para a mesma sentença

Gramática: Ambigüidade

Definição 2• Se uma gramática tem mais do que uma derivação mais à esquerda ou a direita, então a gramática é ambígua

• Se houver mais do que uma árvore gramatical, então a gramática é ambígua

Exemplo clássico — o problema do if-then-else

Esta ambigüidade é de natureza inteiramente gramatical

Gramática: Ambigüidade

Esta sentença tem duas derivações

producão 2, depoisproducão 1

produção 1, depoisprodução 2

Gramática: Ambigüidade

Removendo ambigüidade

Associar cada else ao then anterior mais próximo ainda não associado if (regra de senso comum)

Com esta gramática, o exemplo tem apenas uma derivação

Gramática: Ambigüidade

Gramática:LL(1) e LR(1):Técnicas de parsing

Top-down parsers (LL(1) derivação mais a esquerda, recursivo descendente)• Inicia na raiz da árvore e cresce em direção as folhas• Obtém uma produção e tenta associar a entrada• Se escolha errada pode tentar retroceder (backtrack)• Algumas gramáticas são livre de retrocesso (parsing preditivos )• Não podem tratar com gramáticas recursivas a esquerda Bottom-up parsers LR(1)• L é porque a entrada é da esquerda para a direita• R é porque é feito usando derivação mais a direita e o 1 porque avalia um token adiante• Inicia nas folhas e cresce até a raiz• Inicia em um estado válido para os primeiros tokens

Eliminações:

Utiliza Gramáticas Livres de Contexto (GLC) para descrever a sintaxe das construções de linguagem de programação como expressões e comandos

Derivações: a partir do símbolo inicial de uma regra, substitui-se um não terminal pelo corpo de uma de suas produções-O não terminal em cada passo é escolhido:

Em derivações mais à esquerda (lm), o não terminal mais à esquerda em cada forma sentencial sempre é escolhido

Em derivações mais à direita (rm), o não terminal mais à direita em cada forma sentencial sempre é escolhido

Gramática: Eliminações

Eliminação (fatoração) de recursão à esquerda

- Métodos de análise descendente não tratam recursões à esquerda

- Eliminação de recursão à esquerda imediata:

Gramática: Eliminações

Eliminação de recursividade à esquerda

Gramática: Eliminações

Exemplo de Fatoração a Esquerda

Cmd if Expr then Cmd else Cmd | if Expr then Cmd | Outro A a A b

• Fatorando a esquerda:

Cmd if Expr then Cmd else Opc | OutroA b X

else Opc if Expr then Cmd else else Opc | X a X |

Gramática: Eliminações

Gramática: Eliminações

Fatoração de uma gramática

• Elimina indecisão de qual produção aplicar quando duas ou mais produções iniciam com a mesma forma sentencial. Por exemplo

Gramática: Eliminações

Algoritmo:- Entrada: gramática G- Saída: gramática G, fatorada à esquerda1) para cada não terminal A, encontrar prefixo a mais longo ecomum a duas ou mais de suas alternativas2) Se a!= , então existe um prefixo comum não trivial,ℇsubstitua todas as produções A, A → aB1 | aB2 | ... | aBn | y, onde y representa todas as alternativas que não começam com a, por:- A→ aA' | y- A‘→ B1 | B2 | ... | Bn

Gramática: Eliminações

Gramática: Eliminações

Gramática: Eliminações

Gramática: Eliminações

Análise Descendente(Top-Down)

• Como implementar um reconhecedor para uma GLC?• Constrói-se a árvore de derivação, lendo a sentença de esquerda para a direita, e substituindo sempre o não-terminal mais à esquerda.

• Existe três tipos principais de parser top-down:– Recursivo com retrocesso– Recursivo preditivo– Tabular preditivo.

Análise Descendente(Top-Down)

Análise Descendente(Top-Down)

Análise Descendente(Top-Down)

Implementação do reconhecedor

• Cria-se um procedimento por não-terminal– Ele testa a aplicação de cada produção associada ao não terminal;– Lê no texto de entrada o próximo token• Chama o analisador lexical (yylex()) !• É necessário lembrar onde se fez uma escolha de umaalternativa, para poder retroceder neste ponto.

Análise Descendente(Top-Down)ReconheceTIPO() {switch(token) {case {integer, char, num}: ReconheceTIPOSIMPLES();

break;case ^: reconhece( id) ;

break; }}

ReconheceTIPOSIMPLES() {switch(token){case integer: reconhece(integer); break;case char: reconhece(char); break;case num: reconhece(num); reconhece(pp); reconhece(num); break;default: erro();}}

Análise Descendente(Top-Down)

Observações sobre o método recursivo com retrocesso• É fácil de implementar.• É necessário:1. Que a gramática não seja recursiva à esquerda• A Aa se tornaráReconheceA() { ReconheceA();... }• Recursão infinita!2. Que a gramática seja fatorada à esquerda• Senão, deve-se fazer retrocesso.3. Que os primeiros terminais deriváveis possibilitem a decisão de uma produção a aplicar!• Não há retrocesso sobre não-terminais...

Análise Descendente(Top-Down)

Definição: Conjuntos “First”• First(α):– Definição informal:• conjunto de todos os terminais que começamqualquer seqüência derivável de α.

Análise Descendente(Top-Down)

Condição para que se possa usar um analisador preditivo

Análise Descendente(Top-Down)

Análise Descendente(Top-Down)

O que acontece se First(A)?

Análise Descendente(Top-Down)

Para tratar o caso do ε:o conjunto Follow• Follow(B):– conjunto de terminais que podem aparecer à direitade um não-terminal B em uma sentença válida.– $ passa a denotar um terminal “virtual” que marca o fim da entrada (EOF, CTRL-D,…)•

Análise Descendente(Top-Down)

Exemplo First/FollowS A BA c | B cbB | caFirst(A) = {c, } Follow(A) = {c}First(B) = {c} Follow(B) = {$}First(S) = {c} Follow(S) = {$}

Análise Descendente(Top-Down)

Análise Descendente(Top-Down)

Observações First/Follow• Só terminais entram em First e Follow.• O algoritmo de cálculo de First(α):– É trivial quando α é um terminal t.– varre as produções X → tω quando α é um não-terminal X;– Inclui ε apenas quando X pode derivar em ε.• O algoritmo de cálculo de Follow(X)– É reservado aos não-terminais X– Inclui o $ em alguns casos triviais (X == o start S)– Varre as produções onde X aparece à direita (A → ωX ω’)– NUNCA inclui ε

Análise Descendente(Top-Down)

Exemplo First/FollowS XYZX aXb | Y cYZcX | dZ eZYe | fFirst(X) = {a, } Follow(X) = {c, d, b, e, f}First(Y) = {c, d} Follow(Y) = {e, f}First(Z) = {e, f} Follow(Z) = {$, c, d}First(S) = {a, c, d} Follow(S) = {$}