Você está na página 1de 24

LINGUAGENS E

COMPILADORES
Análise Sintática Ascendente
LINGUAGENS E COMPILADORES
Agenda:

1. Análise Sintática Ascendente


2. Gerador de Analisadores Sintáticos Ascendentes

Obs.: Reveja a apresentação sobre


Análise Sintática e Léxica.
Prof. Dr. Ricardo Luis de Azevedo da Rocha
1. ANÁLISE SINTÁTICA ASCENDENTE
• Corresponde à construção de uma árvore de derivação para uma
cadeia de entrada a partir das folhas (parte de baixo) em direção
à raiz (topo)

T
T*F T* F

F
F
F F

id * id id * id id * id

id * id id * id

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


ANÁLISE SINTÁTICA ASCENDENTE
• Conceito
• A estratégia de análise sintática ascendente busca, a partir de uma
cadeia potencialmente pertencente à linguagem, efetuar
substituições sistemáticas de símbolos terminais por não-terminais
da gramática
• Caso seja possível se chegar ao símbolo não-terminal
inicial da gramática, a cadeia é considerada
reconhecida. Caso não seja possível, a cadeia é
rejeitada. Essa estratégia é chamada Empilhar e
Reduzir (Shift – Reduce).
• Existem dois métodos mais utilizados:
• Precedência simples e precedência de operadores
• Métodos LR
Slide extraído de Maurício Rodrigues de Morais – “Compiladores”
ANÁLISE SINTÁTICA ASCENDENTE
• 4 operações

• SHIFT (empilhar) → próximo símbolo entrada é empilhado


• REDUCE (reduzir) → símbolo mais à direita de um handle
no topo; deve localizar a extremidade
esquerda do handle e decidir sobre a regra.
• ACEITAÇÃO → término da cadeia e pilha
com S (símbolo inicial)
• ERRO → descobre erro sintático e chama
rotina de recuperação.
Slide extraído de Maurício Rodrigues de Morais – “Compiladores”
ANÁLISE SINTÁTICA ASCENDENTE
Uso de uma pilha:
Empilha (SHIFT) símbolos da cadeia até detectar o símbolo
mais à direita de um handle;
Desempilha o handle (REDUCE) e empilha o lado esquerdo
da respectiva regra.
Repetir o ciclo até a situação de erro ou
terminar a entrada e pilha = S.
• Um fato importante que justifica o uso de uma
pilha numa fase numa análise sintática de
empilhar e reduzir é que o handle sempre irá
aparecer no topo da pilha, nunca dentro da
mesma
Slide extraído de Maurício Rodrigues de Morais – “Compiladores”
MÉTODO BOTTOM-UP
• Exemplo:
• x–2*y
Gramática

Slide extraído de Clauirton Siebra – UFPB “Construção de Compiladores”


ANALISADORES LR(K)
• Analisadores redutores eficientes que leem a sentença em análise da
esquerda para a direita (left-to-right) e produzem uma derivação mais
à direita (rightmost) ao reverso, considerando k símbolos em cada
leitura
São capazes de reconhecer, praticamente, todas as
estruturas sintáticas definidas por gramáticas livres
de contexto

Tem como desvantagem a dificuldade da


implementação do mesmo, sendo necessário, em
muitos casos, a utilização de ferramentas
automatizadas para construção da tabela de análise

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


ANALISADORES LR(K)
Os analisadores LR são classificados quanto ao tipo
de tabela de análise que utilizam em:
• SLR (Simple LR), fáceis de implementar, porém
aplicáveis a uma classe restrita de gramáticas
• LR Canônicos, mais poderosos, podendo ser
aplicados a um grande número de linguagens
livres de contexto

• LALR (Look Ahead LR), nível intermediário de


complexidade e implementação eficiente que funciona
para a maioria das linguagens de programação
• É utilizado pelo gerador de analisadores
sintáticos yacc
Slide extraído de Guilherme Amaral Avelino – “Compiladores”
ANALISADORES LR(K) - FUNCIONAMENTO
Xi - símbolo da gramática
Ei - estado a1 ••• ai •••• an$

Em Analisador LR
Xm Tabela de análise
•••
X1
E0

(1) E ::= E + T (2) E ::= T (3) T ::= T * F


(4) T ::= F (5) F ::= (E) (6) F ::= id

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


ANALISADORES LR(K) - FUNCIONAMENTO
Ação Transição
Estado
id + * ( ) $ E T F
0 e5 e4 1 2 3
1 e6 ac
2 r2 e7 r2 r2
3 r4 r4 r4 r4
4 e5 e4 8 2 3
5 r6 r6 r6 r6
6 e5 e4 9 3
7 e5 e4 10
8 e6 e11
9 r1 e7 r1 r1
10 r3 r3 r3 r3
11 r5 r5 r5 r5
Slide extraído de Guilherme Amaral Avelino – “Compiladores”
ANALISADORES LR(K) - FUNCIONAMENTO
• Seja Em o estado no topo da pilha e ai o token sob o cabeçote de leitura
• O analisador consulta a tabela AÇÃO[Em, ai], que pode assumir um dos
valores:
empilha: causa o empilhamento de “aiEx”;
reduz n (onde n é o número da produção A::=β):
causa o desempilhamento de 2r símbolos, onde r = |β |
e o empilhamento de "AEy" onde Ey resulta da
consulta à tabela de TRANSIÇÃO [Em-r*, A];
aceita: o analisador reconhece a sentença
como válida
erro: o analisador para a execução, identificando
um erro sintático
* Em-r é o estado do topo da pilha após a operação de redução

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


ANALISADORES LR(K) - FUNCIONAMENTO
Pilha Entrada Ação/Transição
0 id * id + id $ e5: empillha id 5
0 id 5 * id + id $ r6: reduz F::=id
TRANSIÇÃO[0,F]
0F3

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


CONSTRUÇÃO DA TABELA PARA ANALISADORES SLR
A construção da tabela de controle para analisadores SLR, baseia-se no Conjunto
Canônico de Itens LR(0) o qual serve de base para a construção de um AFD p/ o
reconhecimento
Um item LR(0), para uma gramática G, é uma produção com um ponto em alguma
posição do lado direito
A ::= •XYZ Inicio da busca por uma cadeia derivável de XYZ
A ::= X•YZ X já foi encontrada, continua a busca por YZ
A ::= XY•Z XY já foi encontrada, continua a busca por Z
A ::= XYZ• Fim da busca• XYZ foi encontrada, podendo ser
reduzida p/ A

• O ponto é a indicação de até onde uma produção


já foi analisada no processo de reconhecimento

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


FUNÇÕES CLOSURE E GOTO
Fechamento de conjuntos de itens (CLOSURE)
Se I é um conjunto de itens para a gramática G, então CLOSURE(I) é
construído a partir das duas regras:
E’ → E
E→E+T|T
1. Inicialmente, acrescente todo item de I no CLOSURE(I)
T→T*F|F
1. Se A→α•Bβ está em CLOSURE(I) e B → γ é uma F → (E) | id
produção, então adicione o item B →•γ em
CLOSURE(I), se ele ainda não estiver lá• Aplique
esta regra até que nenhum outro item possa ser
incluído no CLOSURE(I)
• Exemplo: sendo I = {E´ → •E}, calcule CLOSURE(I)
CLOSURE(I) = {

E´ → •E, E → •E+T, E → •T, T → •T*F, T → •F, F → •(E), F → •id}

Aplica regra 1 a I Aplica regra 2


FUNÇÕES CLOSURE E GOTO
• Função de Transição (GOTO)
• É definida como GOTO (I,X), onde I é um conjunto de itens e X é um símbolo
da gramática
• Formalmente, GOTO (I,X) é a função CLOSURE do conjunto dos itens
A→αX•β, tais que A→α•Xβ pertence a I
• Informalmente, consiste em coletar as produções com o ponto no lado
esquerdo de X, passar o ponto para a direita de X, e obter a função
CLOSURE desse conjunto
• Exemplo: sendo I={E’ →E•, E →E•+T}, calcule GOTO(I,+)
GOTO(I,+) = { E→ E+•T, Calcula CLOSURE(E→ E+•T)
T→ •T*F, Passa o ponto para o lado
E’ → E T→ •F, direito do símbolo X
E → E + T | T F→•(E),
T → T * F | F F→ •id } Adiciona a novo produção
F → (E) | id

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


CONJUNTO CANÔNICO DE ITENS
void itens(G’){
C = CLOSURE({S’→•S});
repeat
for (cada conjunto de itens I em C)
for (cada X símbolo da gramática)
if (GOTO(I,X) não vazio em não está em C)
adicione GOTO(I,X) em C;
until nenhum novo conjunto de itens seja adicionado em
uma rodada
}

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


CONSTRUÇÃO DA TABELA SLR
• Seja C={I0, I1, ..., In}. Os estados do analisador são 0, 1, ..., n. A linha i da tabela é
construída a partir do conjunto Ii, como segue:

• As ações do analisador para o estado i são determinadas:


1. Se GOTO (Ii,a) = Ij, então faça AÇÃO[i,a] = empilha j;
2. Se A→α• está em Ii, então para todo FOLLOW(A),
faça AÇÃO[i,a] = reduz n, sendo n o número da
produção A→α
3. Se S’→S• está em Ii, então faça AÇÃO[i,$] = aceita
As transições para o estado i são construídas:
1. Se GOTO(Ii,A) = Ij, então TRANSIÇÂO(i,A) = j

Obs: se ocorrer algum conflito resultante da aplicação


das regras descritas, podemos afirmar que a gramática não é
SLR(1)

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


Ação Transição
Estado
id + * ( ) $ E T F
0 e5 e4 1 2 3
1 e6 ac
2 r2 e7 r2 r2
3 r4 r4 r4 r4
4 e5 e4 8 2 3
5 r6 r6 r6 r6
6 e5 e4 9 3
7 e5 e4 10
8 e6 e11
9 r1 e7 r1 r1
10 r3 r3 r3 r3
11 r5 r5 r5 r5
(1) E ::= E + T (2) E ::= T (3) T ::= T * F
(4) T ::= F (5) F ::= (E) (6) F ::= id
Slide extraído de Guilherme Amaral Avelino – “Compiladores”
TABELA SLR
• Representação eficiente do autômato de pilha que
reconhece a linguagem. Onde:

O topo da pilha contém sempre o estado atual


do autômato
Dado o estado atual e o token de entrada, a tabela
indica a ação a ser executada
No caso da ação ser uma redução a tabela
Transição indica o próximo estado a ser
assumido pelo autômato
As entradas em branco correspondem
às situações de erro

Slide extraído de Guilherme Amaral Avelino – “Compiladores”


2. GERADOR DE ANALISADORES SINTÁTICOS
DESCENDENTES
• Existem vários geradores de parser
• JavaCC
• JLex & Cup
• AntLR
• SableCC
• …
Tem um dos melhores suportes a
gramáticas em EBNF (Extended Backus
Naur Form) e gera estrutura OO da AST
(Abstract Syntax Tree) além de classes
utilitárias usando o padrão Visitor.

Slide extraído de Augusto Sampaio – UFPE “JavaCC”


JFLEX E JCUP
• Esquema da operação
.jflex .java .java .cup

JFLex JCup

Descrição em Descrição em
gramática regular gramática livre de
javac contexto

Analisador Analisador
Léxico Sintático
Arquivo fonte Arquivo de tokens Arvore sintática
.class

Slide extraído de Clauirton Siebra – UFPB “Construção de Compiladores”


LINGUAGENS E
COMPILADORES
Análise Sintática Ascendente

Você também pode gostar