Tanto os métodos descendentes como os ascendentes constroem a árvore de derivação da esquerda...
-
Upload
alexandre-caminha-branco -
Category
Documents
-
view
229 -
download
0
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
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
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).
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
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
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
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)
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)
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)
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 ε