Escolar Documentos
Profissional Documentos
Cultura Documentos
Departamento de informática
COMPILADORES
Análise sintática
Parte 01
Geovane Griesang 2
Análise sintática
Análise léxica x Análise sintática #include <stdio.h>
#include <stdlib.h>
Exemplo de código-fonte em C: int main()
{
int x, y;
x = 2;
y = x + 30; y = x + 30;
printf("\n\nValor de y: %d.\n\n",y);
}
Geovane Griesang 3
Análise sintática
Análise léxica x Análise sintática
Exemplo de código-fonte em C:
Programa fonte: y = x + 30
Cod_atrib =
Análise sintática:
Id, y Cod_adic y +
Id, x num, 30 x 30
Geovane Griesang 4
Análise sintática
Análise
Código fonte Analisador léxico (front-end)
Analisador sintático
Analisador sintático
Analisador semântico
Otimizador de código
Geovane Griesang 5
Análise sintática
O Analisador Sintático (AS) obtém uma cadeia de tokens proveniente do
analisador léxico e verifica se o mesmo pode ser gerado pela gramática
da linguagem-fonte.
Geovane Griesang 6
Análise sintática
Cadeia de
tokens
Analisador
Na prática, não é necessário construir uma árvore de derivação Sintático
explicitamente, pois as ações de verificação e tradução podem
ser entremeadas com a análise.
Geovane Griesang 7
Análise sintática
Programa
fonte
Tabela de símbolos
Geovane Griesang 8
Análise sintática
Cadeia de
tokens
Em aula, vamos considerar que a saída do analisador sintático
é alguma representação da árvore de derivação para a cadeia
de tokens reconhecidas pelo analisador léxico.
Geovane Griesang 9
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 10
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 11
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 12
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 13
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 14
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 15
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 16
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 17
Análise sintática
Tratamento de erro de sintaxe
Geovane Griesang 18
Análise sintática
Tratamento de erro de sintaxe
Se tivéssemos uma boa ideia dos erros mais comuns que poderiam ser
encontrados, poderíamos aumentar a gramática para a linguagem em
exame com as produções que gerassem construções ilegais.
Se uma produção de erro for usada pelo AS, podemos gerar diagnósticos
apropriados p/ indicar a construção ilegal que foi reconhecida na entrada.
Geovane Griesang 19
Análise sintática
Tratamento de erro de sintaxe
Correção global:
Geovane Griesang 20
Análise sintática
Tratamento de erro de sintaxe
Correção global:
Geovane Griesang 21
Análise sintática
Geovane Griesang 22
Análise sintática
Análise sintática descendente
Essa análise pode ser vista como um método que produz uma derivação
mais a esquerda para uma cadeira de entrada.
Geovane Griesang 23
Entrada: id+id*id E → T E’
E’ → + T E’ | 𝜀
Análise sintática T
T’
→
→
F T’
* F T’ | 𝜀
F → (E) | id
E E E E E
lm lm lm lm lm
T E’ T E’ T E’ T E’
F T’ F T’ F T’ + T E’
id 𝜀 id 𝜀
E lm
E lm
E lm
T E’ T E’ T E’
F T’ + T E’ F T’ + T E’ F T’ + T E’
id 𝜀 F T’ id 𝜀 F T’ id 𝜀 F T’
id id * F T’
Geovane Griesang 24
Entrada: id+id*id E → T E’
E’ → + T E’ | 𝜀
Análise sintática T
T’
→
→
F T’
* F T’ | 𝜀
F → (E) | id
E lm
E E
lm
T E’ T E’ T E’
F T’ + T E’ F T’ + T E’ F T’ + T E’
id 𝜀 F T’ id 𝜀 F T’ id 𝜀 F T’ 𝜀
id * F T’ id * F T’ id * F T’
id id 𝜀 id 𝜀
Geovane Griesang 25
Análise sintática
Análise sintática descendente
Geovane Griesang 26
Análise sintática
Análise sintática descendente recursiva
Geovane Griesang 27
Análise sintática
Análise sintática descendente recursiva
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */
}
}
Geovane Griesang 28
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */ } }
Geovane Griesang 29
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */ } }
Geovane Griesang 30
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Apenas sugere que precisamos voltar para linha (1) e tentar outra opção
da produção-A. Somente quando não houver mais produções-A a serem
tentadas é que declaramos que foi encontrado um erro na entrada.
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */ } }
Geovane Griesang 31
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */ } }
Geovane Griesang 32
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Entretanto, este é um método muito ineficiente, não sendo visto com muita
frequência.
Geovane Griesang 33
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
Para ilustrar este método, suponha uma gramática cujas produções são
dadas a seguir:
S → cAd
A → ab | a
c A d c A d c A d
a b a
Geovane Griesang 34
S → cAd
A → ab | a
Análise sintática
Análise sintática descendente recursiva (com retrocesso)
(a) S
c A d
Neste ponto o analisador deve escolher uma das alternativas, mas deverá
se lembrar das próximas alternativas e qual a situação atual da derivação,
criando assim um ponto de escolha.
Geovane Griesang 35
S → cAd
A → ab | a
Análise sintática
(b) S
Análise sintática descendente recursiva (com retrocesso)
C A d
Escolhendo-se a primeira alternativa, A → ab, obtemos a
árvore (b), a qual corresponde à derivação S → cabd. a b
Neste ponto ocorre uma falha, pois a sentença gerada não corresponde à
sentença de entrada.
Geovane Griesang 36
S → cAd
A → ab | a
Análise sintática (c) S
Análise sintática descendente recursiva (com retrocesso)
c A d
a
Como a primeira alternativa falhou, resta agora seguir a segunda,
ou seja, A → a, o que produzirá a derivação S → cad, a qual
corresponde a árvore (c).
Como foi possível gerar a sentença inicial a partir desta gramática, então
tal sentença pode ser reconhecida por esta gramática.
Geovane Griesang 37
Análise sintática
Análise sintática descendente recursiva (sem retrocesso)
Geovane Griesang 38
Análise sintática
Análise sintática descendente recursiva (sem retrocesso)
As regras gramaticais:
<exp> : <termo> + <exp> | <termo> - <exp> | <termo>
<termo> : <fator> * <termo> | <fator> / <termo> | <fator>
<fator> : id | IntNum | RealNum | ( <exp> )
Geovane Griesang 39
<exp> : <termo> + <exp> | <termo> - <exp> | <termo>
<termo> : <fator> * <termo> | <fator> / <termo> | <fator>
Análise sintática <fator> : id | IntNum | RealNum | ( <exp> )
id → letra+ (letra | digito)*
IntNum → digito+
RealNum → digito* . digito+
Análise sintática descendente recursiva letra → [A-Za-z]
(sem retrocesso) digito → [0-9]
Rotina Exp
Inicio
Chamar Termo
Caso Lexema é
'+', '-': Chamar Lexico
Chamar Exp
Fim do Caso Rotina Termo
Fim da Rotina Exp Inicio
Chamar Fator
Caso Lexema é
'*', '/': chamar Lexico
chamar Termo
Fim do Caso
Fim da Rotina Termo
Geovane Griesang 40
<exp> : <termo> + <exp> | <termo> - <exp> | <termo>
<termo> : <fator> * <termo> | <fator> / <termo> | <fator>
Análise sintática <fator> : id | IntNum | RealNum | ( <exp> )
id → letra+ (letra | digito)*
IntNum → digito+
RealNum → digito* . digito+
Análise sintática descendente recursiva letra → [A-Za-z]
(sem retrocesso) digito → [0-9]
Rotina Fator
Inicio
Se Lexema é '(' então
chamar Lexico
chamar Exp
Se Lexema é ')' então
Chamar Lexico
Senão
Erro(') esperado')
Fim se Se Token ∈ {Id, IntNum, RealNum} então
Senão Chamar Lexico
... Senão
Fim se Erro('Operando esperado')
Fim da Rotina Fator Fim se
Geovane Griesang 41
<exp> : <termo> + <exp> | <termo> - <exp> | <termo>
<termo> : <fator> * <termo> | <fator> / <termo> | <fator>
Análise sintática <fator> : id | IntNum | RealNum | ( <exp> )
id → letra+ (letra | digito)*
IntNum → digito+
RealNum → digito* . digito+
Análise sintática descendente recursiva letra → [A-Za-z]
(sem retrocesso) digito → [0-9]
Programa AnalisadorSintaticoRecursivo
Inicio
Chamar Lexico
Chamar Exp
Se Token <> Eof então
Erro('Fim de arquivo não esperado')
Fim se
Fim do Programa AnalisadorSintaticoRecursivo
Geovane Griesang 42
Análise sintática
Análise sintática descendente recursiva
Questão de prova
O que pode ocorrer com uma gramática com recursão a esquerda?
Ex.: S → ScAd.
Geovane Griesang 43
E → T E’
E’ → + T E’ | 𝜀
Análise sintática T
T’
→
→
F T’
* F T’ | 𝜀
F → (E) | id
Exemplo: T E’ 2º
F T’ + T E’
No primeiro nó E’, a produção E’ → + T E’ é a escolhida.
No segundo nó E’, a produção E’ → 𝜀 é escolhida.
id 𝜀 F T’ 𝜀
Então, uma analisador pode escolher entre as produções-E’ id * T E’
examinando o próximo símbolo da entrada.
id 𝜀
Geovane Griesang 44
Análise sintática
Análise sintática descendente preditiva
Geovane Griesang 45
Análise sintática
Exercício:
Void A(){
1) Escolha uma produção-A, A → X1, X2, ..., Xk;
2) for (i = 1 até k) {
3) If (Xi é um não-terminal)
4) ativa procedimento Xi();
5) else if (Xi igual ao símbolo de entrada a)
6) avance na entrada até o próximo símbolo terminal;
7) else /* ocorreu um erro */
}
}
Geovane Griesang 46
Próxima aula
Geovane Griesang 47
Universidade de Santa Cruz do Sul – UNISC
Departamento de informática
COMPILADORES
Obrigado!!