compiladores - unicamp• há compiladores que geram código em linguagem assembly. –...
TRANSCRIPT
![Page 1: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/1.jpg)
Compiladores
Marco A. Amaral HenriquesDCA/FEEC/UNICAMP
versão 2006
![Page 2: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/2.jpg)
Compilador• Programa que transforma texto escrito em
linguagem de alto nível (programa-fonte) em programa objeto.
ProgramaFonte Compilador Programa
Objeto
![Page 3: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/3.jpg)
Exemplo Simples de Compilação• Compilação de trecho de programa
int a, b, valor;a = 100;b = a*(valor + 20);
• Compilador vê trecho como a sequênciaint a, b, valor;a = 100;b = a*(valor + 20);
• Sequência deve ser analisada lexicamente:– Agrupar caracteres em unidades elementares
• Itens Léxicos: palavras válidas da linguagem. |int|a|,|b|,|valor|; |a|=|100|;|b|=|a|*|(|valor| +|20|)|;|
![Page 4: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/4.jpg)
Exemplo: Análise Sintática• Itens léxicos são analisados sintaticamente
– Agrupar itens léxicos em setenças válidas
• Código de máquina é gerado– Usando tabelas: uma entrada de código para cada operação
possível na linguagem (ineficiência).– Usando sistema formais:
• regras formais para construção e análise de sentenças,• algoritmos para analisar sentenças tornam-se viáveis.
int a , b , valor ; a = 100 ; b = a * (valor + 20 ) ;
![Page 5: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/5.jpg)
Sistema Formal• Conjunto de palavras e de relações chamadas
regras de inferência.• Gramática Formal
– Permite especificar formalmente uma linguagem.– É uma quádrupla ordenada G=(N,T, Σ, P) onde
• T : conjunto de símbolos terminais : correspondem aos símbolos nos programas-fonte.
• P : conjuto de produções : regras de transformação de uma cadeia de caracteres em outra.
• N : conjunto de símbolos não-terminais : aparecem em estágios intermediários da geração de um sentença.
• Σ : símbolo não-terminal inicial .
![Page 6: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/6.jpg)
Exemplo de Gramática Formal
• Gramática G = (N, T, Σ, P):• N = {Σ, A, B}• T = { a , b }• P = {Σ --> AB;
A --> aA;A --> a;B --> Bb;B --> b; }
• Pode gerar sequências de caracteres do tipo anbm, com n, m > 0.
![Page 7: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/7.jpg)
Tipos de Gramática
• De acordo com o número e o tipo de símbolos nos lados direito e esquerdo das produções, as gramáticas podem ser classificadas em quatro tipos distintos, segundo a hierarquia de Chomsky:– Tipo 0: Gramáticas redutíveis e dependentes do contexto– Tipo 1: Gramáticas irredutíveis e dependentes de contexto– Tipo 2: Gramáticas livres de contexto– Tipo 3: Gramáticas regulares
![Page 8: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/8.jpg)
Gramáticas Tipo 0• Gramáticas redutíveis e dependentes do contexto
– Têm produções que expandem/reduzem o comprimento da sequência de caracteres, dependendo do contexto onde esta se insere.
– Não há restrições quanto ao tipo de produções:• qualquer tipo e quantidade de símbolos à esquerda ou à
direita.– Ex: aA → c
BBB → zCt BbC → aAAAAAA AAAaaaAAAa → x
![Page 9: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/9.jpg)
Gramáticas Tipo 1• Gramáticas irredutíveis e dependentes de contexto
– Nenhuma produção diminui o número de caracteres da sequência, mas todas são dependentes do contexto onde está a mesma.
– Para produções na forma α → β, obrigatoriamente tem-se que |α| ≤ |β|, onde |x| indica o número de símbolos em x. Ou seja, a aplicação das produções aumenta ou mantem o tamanho da seqüência de símbolos, mas nunca o diminui.
– Ex: AaA → BBB AaaaA → AAAAAA Ccc → zCC
![Page 10: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/10.jpg)
Gramáticas Tipo 2• Gramáticas livres de contexto
– Lado esquerdo das produções tem um único símbolo e assim não depende do contexto.
• Para todas as produções na forma α → β, obrigatoriamente tem-se que |α| = 1.
– Símbolo do lado esquerdo é símbolo não-terminal.– Ex: P = { B → aBbc ;
B → B ;C → xpto }
![Page 11: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/11.jpg)
Gramáticas Tipo 3• Gramáticas regulares
– Livres de contexto e com restrições ao número máximo de símbolos acrescidos a cada produção.
– Podem ser modeladas como autômatos finitos.• Logo, existem algoritmos para implementá-las.
– Duas variantes:• Gramática Linear Direita:
– as produções são do tipo A → a ou A → aA• Gramática Linear Esquerda:
– as produções são do tipo A → a ou A → Aa
![Page 12: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/12.jpg)
Gramáticas Tipo 3: características• São adequadas para definir formatos de
constantes, identificadores e palavras reservadas de uma linguagem → úteis na Análise Léxica– Ex: G = ({letra, digito}, {IDENT, RESTO},
P, IDENT ) P = { IDENT → letra | letra RESTO;
RESTO → letra |digito |letra RESTO |digito RESTO }
• Exercício: supondo que os símbolos terminais “letra” e “digito” sejam equivalentes a letras e dígitos respectivamente, forneça dois exemplos bem distintos de seqüências válidas e dois de seqüências inválidas na gramática acima.
![Page 13: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/13.jpg)
Expressões Regulares (regexp)• Forma alternativa de se definir sentenças geradas
por gramáticas tipo 3.• As regexp clássicas de um alfabeto A podem ser:
– um elemento de A ou string vazia;– uma seqüência das regexps P e Q: PQ ;– uma escolha entre as regexps P e Q : P | Q (P ou Q) ;– zero ou mais ocorrências de P: P* .
• Ex: regexp que descreve um identificador: letra ( letra | digito )*
![Page 14: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/14.jpg)
Gramáticas Tipo 3: limitações• Tanto as Gramáticas Tipo 3 como as regexps não
são adequadas para expressar sentenças que possuam limitadores balanceados, tais como ( ... (...) ... (...) ... ( ... (... ) ... ) ... )
• Entretanto, estas sentenças podem ser expressas facilmente por gramáticas livres de contexto como, por exemplo: S → ( S ) S → SS S → ε
![Page 15: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/15.jpg)
Gramáticas Livres de Contexto• Mais utilizadas na etapa de análise sintática de
uma linguagem.• Possuem a propriedade da “autoincorporação”,
isto é possui pelo menos uma produção da forma A → α1 A α2 onde A é um símbolo não-terminal e α1 , α2 são seqüências não vazias de símbolos terminais.
• Obs: uma gramática livre de contexto que não possua a propriedade acima descrita pode ser convertida a uma gramática regular.
![Page 16: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/16.jpg)
Representação de Gramáticas Livres de Contexto
• Toda gramática livre de contexto equivale a uma gramática na Forma Normal de Chomsky, onde todas as produções podem ser escritas na forma
A → BC A → a
– Lado esquerdo da produção: símbolo não-terminal– Lado direito da produção: expansão do símbolo da
esquerda, contendo símbolos terminais e/ou não-terminais
![Page 17: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/17.jpg)
Notação BNF (Backus-Naur Form)• Representação textual de gramáticas livres de contexto
– operador binário ::= para descrever produções– colchetes angulares < e > para símbolos não-terminais
• Ex: <exp> ::= <exp> <termo>– operador OU | : produções alternativas (Ex: <S> ::= a | b )– operador para símbolos opcionais [ ]
• Ex: <S> ::= [ a ] equivale a <S> ::= a ou <S> ::= ε– operador de fatoração ( | )
• Ex: <S> ::= a (b | c) d equivale a <S> ::= abd ou <S> ::= acd– operador de repetição *
• Ex: <S> ::= a* equivale a <S> ::=ε ou <S> ::= a <S>– operador de concatenação { || }* para repetição múltipla
• Ex: <S> ::= {a||b}* equivale a <S>::=a <T> e <T> ::=ε ou <T> ::=ba <T>
![Page 18: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/18.jpg)
Tarefas Iniciais do Compilador• Análise Léxica
– Reconhecer os itens léxicos (tokens) do programa.– Atribuir identificador a cada item léxico.
• Análise Sintática– Validação da estrutura formada pelos itens léxicos.– Procura construir uma árvore sintática com os itens.
• Análise Semântica– Normalmente é implementada junto com a análise sintática.– Extrai informações da árvore sintática para sintetizar código
de máquina.• Consistência entre declaração e uso de variáveis.• Reserva de memória para variáveis.
![Page 19: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/19.jpg)
Tarefas Finais do Compilador• Geração de Código Intermediário
– Tradução de cada nó da árvore sintática em instruções de máquina.
• Há compiladores que geram código em linguagem assembly.– Formalização da gramática de linguagem de máquina é difícil.
• Rotinas de tradução ainda são especificadas manualmente.
• Otimização– Modificação do código e estruturas de dados gerados para
minimizar tempo de execução e espaço requerido.– Desempenho de otimizador depende da criatividade de seu
projetista.
![Page 20: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/20.jpg)
Análise Léxica• Reduz uma sentença a conjunto de itens léxicos.• Classifica itens léxicos.
– Distingue os tipos aceitos por uma gramática.– Classes mais comuns
• identificadores de variáveis• símbolos ou palavras reservadas (for, switch, etc em C)• literais ou constantes• símbolos especiais (símbolos de controle)• marcador de fim de arquivo
– Cada novo item léxico recebe um identificador e é guardado na Tabela de Terminais.
![Page 21: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/21.jpg)
Autômatos Finitos na representação de itens léxicos
• Itens léxicos normalmente representáveis por:– gramáticas regulares (Tipo 3) ou– expressões regulares (regexp)• Existe correspondência unívoca entre gramáticas
(expressões) regulares e autômatos finitos.• Autômatos finitos: quádrupla M = (K, Σ, δ, S, F)– K: conjunto finito de estados– Σ: alfabeto de entrada finito– δ: conjunto de transições– S: estado inicial (S ∈ K)– F: conjunto de estados finais (F ⊆ K)
![Page 22: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/22.jpg)
Representação de Autômatos Finitos• AFs são representados por grafos dirigidos,
denotando as transições entre os estados.• Círculos representam os estados.
– Círculos duplos representam estados finais.• Transições: representadas por triplas (si , ΣT , sf ):
– si : estado inicial da transição– ΣT : conjunto de símbolos do alfabeto que disparam a
transição quando o estado é si – sf : estado do autômato após a transição
asisf
![Page 23: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/23.jpg)
Representação de autômatos por tabelas de transição
• Forma mais prática de implementação.• Colunas representam os estados.• Linhas representam os símbolos do alfabeto de
entrada.• Cada célula da tabela indica o estado final de
uma transição a partir do estado indicado na coluna após a entrada do símbolo indicado na linha.
. . . si . . .
. . . . . . . . .
. . . sf . . .
. . . . . . . . .
. . .
. . .
a
![Page 24: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/24.jpg)
Tipos de Autômatos• Determinísticos
– para cada par (estado, entrada) existe apenas uma transição aplicável.
• Não-determinísticos– para cada par (estado, entrada) existe mais de uma
transição aplicável.• A todo AF não-determinístico corresponde um
AF determinístico que representa (aceita) a mesma linguagem.– Logo, é possível transformar um AF não-
determinístico por um AF determinístico sem perda de funcionalidade.
![Page 25: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/25.jpg)
Construção de autômato finito não-determinístico
• Algoritmo de Thompson– constrói AFs não determinísticos para reconhecer
sentenças de uma gramática regular.• Primeiro passo: decompor a expressão regular
em termos de suas relações elementares:– um símbolo do alfabeto da linguagem,– uma concatenação tipo RS,– uma alternativa tipo R | S ,– uma repetição tipo R .
• Segundo passo: construir um autômato finito que reconheça cada uma destas relações elementares.
![Page 26: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/26.jpg)
Autômatos Finitos Elementares
i
f
f
f
f
ii
i
M1
M1
M1
M2
M2
a
ε
εεε
εε
ε
ε
Reconhecimento do símbolo a Concatenação
RepetiçãoAlternativas
(estado final de M1 e inicial de M
2)
(string vazia)
Autômato M
![Page 27: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/27.jpg)
Exemplo de construção deAF não-determinístico
• Construção do autômato finito que reconheça a expressão regular R = (a | b)* abb.
• Relações elementares:R
1 = a
R2 = b
R3 = R
1 | R
2
R4 = R
3 *
R5 = R
4 R
1
R6 = R
5 R
2
R = R
6 R
2
![Page 28: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/28.jpg)
Exemplo de construção deAF não-determinístico: resultado
5 6ε
εε
ε410 117
1
3
2
8 9ε ε
ε
ε
a
bb ba
R = (a|b)*abb
![Page 29: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/29.jpg)
Conversão de AF não-determinístico a AF determinístico
• AFs não-determinísticos são ambíguos.• Conversão baseada na construção de subconjuntos.
– Subconjunto ε*(T): inclui os estados em T e todos os demais alcançáveis a partir deles por entradas vazias.
– Determina-se ε*(T0) para T
0 contendo os estados iniciais do
AF não-determinístico (estados originais).– Subconjunto ε*(T
0) é o estado inicial s
0 do AF
determinístico.– Analisa-se ε*(T
0) para cada entrada possível, obtendo-se T
1,
T2 etc. e repete-se o procedimento com
s1 = ε*(T
1), s
2 = ε*(T
2) etc.
– Subconjunto si = ε*(T
i) será um estado final do AF
determinístico se Ti contiver um estado final original.
![Page 30: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/30.jpg)
Resultado da conversãopara AF determinístico
s0
s1
s3
s4s
2
a
b a a
bb
b
b
a
a
Grafo Tabela
entr.
a
b
s0
s1
s2
s3
s4
s1
s1
s1
s1
s1
s2
s3
s2
s4
s2
R = (a|b)*abb
![Page 31: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/31.jpg)
Minimização de estados• Se existirem vários AFs reconhecendo uma mesma
sentença, alguns estados de alguns AFs podem ser desnecessários.
• Para minimizar o número de estados de um AF:– divide-se o grupo de estados S em um subgrupo G
1
contendo todos os estados finais (F) e outro G2
contendo os estados não-finais (S-F);– faz-se nova divisão em cada subgrupo, considerando
que um novo subgrupo Gi só conterá os estados s e t, se
todas as transições partindo de s e de t, levam sempre a um mesmo subgrupo;
– repete-se a divisão para os novos subgrupos até que não seja mais possível dividir.
![Page 32: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/32.jpg)
Resultado da minimizaçãodo AF determinístico
s1
s3
s4s
0
a a
bb
b
b
a
a
Grafo Tabela
entr.
a
b
s0
s1
s3
s4
s1
s1
s1
s1
s2
s3
s4
s2
R = (a|b)*abb
![Page 33: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/33.jpg)
Analisador Léxico• É um programa que implementa um autômato
finito para reconhecer ou rejeitar seqüência de símbolos σ de uma linguagem.
• Sejam os seguintes procedimentos auxiliares:
S0 = ESTADO_INICIAL(M): retorna o estado inicial do
autômato M;
Resp = ESTADO_FINAL(M,Si): indica se estado S
i é
elemento do conjunto de estados finais do autômato M;
Si+1
= PRÓXIMO_ESTADO(M, Si , símbolo): retorna o
próximo estado do autômato M, quando se encontra no estado S
i e recebe a entrada símbolo.
![Page 34: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/34.jpg)
Algoritmo de Analisador Léxico
SCANNER(M,σ)s = ESTADO_INICIAL(M)while true do
if É_VAZIO(σ)then if ESTADO_FINAL(M,s)
then return trueelse return false
else c = REMOVA_O_PRIMEIRO(σ)s = PROXIMO_ESTADO(M, s, c)if s = NULL
then return false
![Page 35: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/35.jpg)
Geradores de Analisadores Léxicos• Conjunto de programas para construção
automática de analisadores léxicos.• Podem não gerar analisadores eficientes.• Geradores mais comuns: lex e flex
– Formato geral de gramática em lex definida em arquivo com extensão .l :
definições%% <== divisão de seção no arquivoregras%% <== divisão de seçãorotinas do usuário
![Page 36: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/36.jpg)
Seção de Regras do LEX• Define a funcionalidade do analisador léxico
através de regras (produções da gramática).• Cada regra é um par padrão-ação.• Regras:
– expressões regulares (regexps) indicam uma sequência válida de caracteres;
– expressões regulares são descritas por uma linguagem definida por lex;
– a ação associada a cada regra é um bloco de código C que será executado sempre que a seqüência de símbolos de entrada for reconhecida pela regexp;
![Page 37: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/37.jpg)
Linguagem de regexps em lexO p e r a d o r S i g n i f i c a d o E x e m p l o
? e x p r e s s ã o a n t e r i o r é o p c i o n a l 1 0 ? 9 < = > 1 0 9 o u 1 9* q u a l q u e r r e p e t i ç ã o , i n c l u s i v e 0 a * < = > { 0 , a , a a , a a a , . . . }+ q u a l q u e r r e p e t i ç ã o , e x c l u i n d o 0 a + < = > { a , a a , a a a , . . . }
| a l t e r n a t i v a a | b < = > a o u b( ) a g r u p a m e n t o d e e x p r e s s õ e s
• q u a l q u e r c a r a c t e r , e x c e t o l i n e f e e d^ i n í c i o d e l i n h a , m a s s e e s t i v e r e n t r e [ ]
s i g n i f i c a c o m p l e m e n t o[ ] q u a l q u e r c a r a c t e r d e n t r e o s e s p e c i f i c a d o s [ a b c ] < = > { a , b , c }
- f a i x a d e v a l o r e s [ 0 - 9 ] < = > { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }{ } n ú m e r o d e r e p e t i ç õ e s p o s s í v e i s a { 1 , 2 } < = > { a , a a }
\ E s c a p e s c a r a c t e r s e g u i n t e o ur e p r e s e n t a c a r a c t e r e s n ã o i m p r i m í v e i s .
\ • < = > •\ t < = > t a b u l a ç ã o
![Page 38: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/38.jpg)
Seção de Definições do LEX• Pode conter:
– Macrosdigito [0-9]frac .[0-9]+
– Linhas de comando em C, sempre delimitadas por %{ e %} .
%{#include <classes.h>#define NUMBER 400%}
![Page 39: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/39.jpg)
Exemplo de Geração de Analisador Léxico
Gramática G=(N,T,Σ,P)
N = {Σ, <IDN>, <INT>, <REAL>, <SIMB_ATR>,<SIMB_MUL>,<SIMB_DIV>, <SIMB_SOM>,<SIMB_SUB>, <SIMB_POT>,<SIMB_PA1>,<SIMB_PA2>, <BL>, <seq>, <digito>, <letra>,<exp> }
T = {0,1,2,3,4,5,6,7,8,9, . ,a,b,c,...,z,A,B,C,...,Z,+,-,*,/,(,),=,”\n”,”\t”,” ”}
![Page 40: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/40.jpg)
Produções da Gramática Exemplo• P = { Σ ::= <BL><exp>;
<exp> ::= <IDN>|<INT>|<REAL>|<SIMB_ATR>|<SIMB_MUL>|<SIMB_DIV>|<SIMB_SOM>|<SIMB_SUB>|<SIMB_POT> ;
<IDN> ::= <letra> <seq>; <BL> ::= “\t”<BL> | “ ”<BL> | “\t” | “ ” ; <seq> ::= <letra> <seq> | <digito> <seq> | <letra> | <digito>; <INT> ::= <digito> <INT> | <digito> ; <REAL> ::= <digito> <REAL> | .<INT> ; <SIMB_MUL> ::= * ;
<SIMB_DIV> ::= / ; <SIMB_SOM> ::= + ; <SIMB_SUB> ::= - ;
<SIMB_POT> ::= *<SIMB_MUL> ; <SIMB_ ATR> ::= = ; <SIMB_PA1> ::= ( ; <SIMB_PA2> ::= ) ; <digito> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ; <letra> ::= a | b | c | d | . . . | A | B | C | D | . . . | Z | “\n” }
![Page 41: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/41.jpg)
Criação de Arquivo .l %{
#defineIDN 257#defineINT 258#defineREAL259. . .%}%%[a-zA-Z] | [a-zA-Z][a-zA-Z0-9]+ {/* Ação Semântica 1 */
printf(“Token da classe <Identificador> \n”); return IDN; }
[0-9]+ {/* Ação Semântica 2 */ printf(“Token da classe <Inteiro> \n”); return INT; }
[0-9]+\ . [0-9]+ |\ . [0-9]+ {/* Ação Semântica 3 */
printf(“Token da classe <Racional> \n”); return REAL; } . . .
![Page 42: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/42.jpg)
Rotinas do Usuário em Arquivo .lSeção de definições%%Seção de regras%%Seção de rotinas do usuário#include <stdio.h>main(int argc, char *argv) {
int val;while (val = yylex( ))
printf(“valor = %d \n”, val);}
![Page 43: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/43.jpg)
Utilização do Analisador Léxico• Assumindo que o arquivo .l se chama teste.l :
> lex teste.l• Tal comando gera um programa lex.yy.c que aceita
sequência de caracteres e retorna itens léxicos.• Programa lex.yy.c deve ser compilado
> cc -o teste lex.yy.c -ll • Exemplo de uso: > teste a=7.02 resultará em
Token da classe <Identificador>valor = 257Token da classe <Operador de atribuição>valor = 261Token da classe <Racional>valor = 259
![Page 44: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/44.jpg)
Análise Sintática• Gramáticas do Tipo 3 (gramáticas regulares) não
são adequadas para identificar a forma como os itens léxicos estão combinados (análise sintática).
• Gramáticas do Tipo 2 (gramáticas livres de contexto) são mais adequadas para representar as regras de uma linguagem de programação e, portanto, podem ser usadas em análisadores sintáticos (parsers).– Nem todas as construções de uma linguagem de
programação podem ser representadas diretamente, mas por meio de reconhecedores de sentenças livres de contexto e algumas estratégias heurísticas é possível automatizar a etapa da análise sintática.
![Page 45: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/45.jpg)
Reconhecimento de sentenças
• Procura-se “reduzir” a sentença de símbolos terminais até se alcançar o símbolo não-terminal inicial (processo inverso da derivação ou expansão).
• Caso o símbolo não-terminal inicial não seja alcançável por nenhuma combinação das regras da gramática, a sentença é considerada inválida.– Neste caso é preciso tentar todas as combinações de
regras possíveis até que não haja mais nenhuma combinação não tentada.
![Page 46: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/46.jpg)
Exemplo de reconhecimento• Seja a gramática G=(N,T, <E>, P), onde:
N = {<E>, <T>, <F>} T = {+, ×, id , ( , ) }
P = { <E> ::= <E> + <T> | <T> ;
<T> ::= <T> × <F> | <F> ;
<F> ::= ( <E> ) | id }
• A sentença (id + id) id não pode ser reduzida
nesta gramática, mas (id + id) × id pode.
![Page 47: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/47.jpg)
Derivações Canônicas• Há diversas opções para a seqüência de aplicação
das regras, algumas reconhecendo a sentença e outras não.
• Derivações Canônicas são formas sistemáticas de aplicação das regras gramaticais.– Derivação mais à esquerda (leftmost derivation):
aplicar uma regra de derivação ao símbolo não-terminal mais à esquerda.
• Seqüência de reconhecimento mais à esquerda– Derivação mais à direita (rightmost derivation):
seleciona-se o símbolo não-terminal mais à direita para aplicação da regra de derivação.
• Seqüência de reconhecimento mais à direita
![Page 48: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/48.jpg)
Exemplos de Derivações Canônicas Derivação mais à esquerda
<E>::= <T>::= <T> × <F>::= <F> × <F>::= (<E>) × <F>::= (<E> + <T>) × <F>::=(<T> + <T>) × <F>::=(<F> + <T>) × <F>::=(id + <T>) × <F>::=(id + <F>) × <F>::=(id + id) × <F>::=(id + id) × id
Derivação mais à direita
<E>::= <T>::= <T> × <F>::= <T> × id::= <F> × id::= (<E>) × id::= (<E> + <T>) × id::= (<E> + <F>) × id::= (<E> + id) × id::= (<T> + id) × id::= (<F> + id) × id::= (id + id) × id
![Page 49: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/49.jpg)
Árvores Sintáticas ou Gramaticais• Representação para derivações de uma sentença a partir
do símbolo inicial Σ.• Símbolo Σ ocupa raiz da árvore.• Símbolos terminais ocupam folhas da árvore.• Símbolo não-terminal <S> corresponde à raiz de uma
sub-árvore.– Ex: se <S> ::= X1X2X3...Xn , então <S> é uma sub-árvore da
gramática.<S>
X1 X2 X3 Xn. . .
![Page 50: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/50.jpg)
Exemplos de árvores sintáticas
![Page 51: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/51.jpg)
Formas de reconhecimento• Reconhecimento pode ser visto como:
– leftmost parse: encontrar uma seqüência de reconhecimento mais à esquerda
ou
– rightmost parse: encontrar uma seqüência mais à direita
ou
– construção de uma árvore sintática.
![Page 52: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/52.jpg)
Gramática Ambígua• Gramática livre de contexto na qual existe mais de
uma árvore sintática para uma mesma sentença.• Ex: gramática G=(N,T,Σ,P)
• N = {Σ , <inteiro>}• T = { 1 , 0 }• P = {Σ ::= <inteiro>; <inteiro> ::= <inteiro> <inteiro>; <inteiro> ::= 1; <inteiro> ::= 0 }tem duas árvores para sequência 101.
![Page 53: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/53.jpg)
Gramática Não-ambígua• Só há uma árvore sintática por sentença.• Permite geração de mais de uma derivação para uma
mesma sentença, dependendo da ordem de substituição dos símbolos não-terminais (problema de precedência).
• Formas naturais de escolha do símbolo– substituir o mais à esquerda
• Gramáticas LL : input from Left, Leftmost derivation– substituir o mais à direita
• Gramáticas LR : input from Left, Rightmost derivation
• Às vezes pode ser obtida de gramática ambígua, mas não existe algoritmo que determine se uma dada gramática é ou não é ambígua.
![Page 54: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/54.jpg)
Exemplo de Gramática Não-ambígua• Gramática G=(N,T,Σ,P)
• N = {Σ, <inteiro> , <digito>}• T = { 1 , 0 }• P = { Σ ::= <inteiro> ;
<inteiro> ::= <inteiro> <digito> ;<inteiro> ::= <digito> ;<digito > ::= 1 ;<digito > ::= 0 }
tem somente uma árvore para sequência 101.
![Page 55: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/55.jpg)
Analisadores Sintáticos• Constroem a árvore sintática correspondente à
sentença sob análise.• Duas formas de contrução:
– ascendente (bottom-up): parte das folhas para a raizou
– descendente (top-down): parte da raiz e tenta chegar até as folhas.
• Ex: seja a função REDUZIR(G,α) que retorna o símbolo não-terminal à esquerda de uma produção da gramática G cujo lado direito contenha α.
![Page 56: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/56.jpg)
Exemplo de construção ascendentePARSER_ASCENDENTE(G,α)
declare s : Símbolowhile true do s ← REMOVER_PRIMEIRO(α)
if s = OBTER_NÃO_TERM_INICIAL(G) e ESTA_VAZIA(α)
then return trueelse INSERIR(α, s)
α ← REDUZIR(G,α) if ESTA_VAZIA(α)
then return false
![Page 57: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/57.jpg)
Analisador de deslocamento e redução• Baseia-se na técnica de construção ascendente para
reconhecer sentenças válidas.• Símbolos terminais da sentença são lidos um a um.• A cada símbolo lido, analisador decide se:
– lê um novo símbolo (desloca o ponteiro para o próximo da sentença) ou
– aplica uma produção da gramática aos símbolos já lidos, reduzindo-os a um símbolo não-terminal.
• Sua peça fundamental é a Tabela de Deslocamento e Redução (Shift-Reduce Table)
![Page 58: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/58.jpg)
Tabela SR• A Tabela SR (Shift-Reduce) é baseada nas
relações de precedência simples entre os símbolos da gramática.
• As relações de precedência são:
X Y : X confere precedência a Y
e
X > Y : X tem precedência sobre Y.
![Page 59: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/59.jpg)
Regras para relações “confere precedência”
• Regra 1: $ ∑ , isto é, delimitador de sentença confere precedência ao símbolo não-terminal inicial.
• Regra 2: se existe alguma produção de G na forma α → βXYμ, então diz-se que XY.
• Regra 3: se X α , onde α é um símbolo não-terminal, e existe uma produção para α em G onde Y é o primeiro símbolo do lado direito (α→Yμ), então diz-se que XY.
![Page 60: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/60.jpg)
Regras para relações “tem precedência sobre”
• Regra 4: ∑ > $ , isto é, símbolo não-terminal inicial tem precedência sobre delimitador de sentença.
• Regra 5: se, para algum símbolo não-terminal α, existe a relação α Y e existe uma produção para α cujo último símbolo é X (α → βX), então diz-se que X > Y.
• Regra 6:se, para algum símbolo não-terminal α, existe a relação α > Y e existe uma produção para α cujo último símbolo é X (α → βX), então diz-se que X > Y.
• Regra 7: se, para algum símbolo não-terminal α, existe a relação X > α e existe uma produção para α cujo primeiro símbolo é Y (α → Yμ), então diz-se que X > Y.
![Page 61: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/61.jpg)
Observações sobre regras de precedência
• Não se deve confundir as relações de precedência com as relações “maior que” ou “menor que”, pois podem surgir situações que aparentemente não fariam sentido. Por exemplo:– XY não implica que Y>X ;– é possível encontrar gramáticas em que XY ocorre
ao mesmo tempo que YX ;– é possível encontrar gramáticas em que XY ocorre
ao mesmo tempo que X>Y .
![Page 62: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/62.jpg)
Formação da Tabela SR• Gramática é estendida com a inclusão do símbolo $
que serve para indicar início e fim de sentença.• Regras de 1 a 7 são aplicadas à gramática.• Para toda relação Xa, a tabela deverá indicar que
deve ser buscado o próximo símbolo da sentença.– X é um símbolo qualquer e a é um símbolo terminal.
• Para toda relação X>a, a tabela deverá indicar que é possível fazer uma redução nos últimos símbolos lidos da sentença.
• Para os pares (X,a) de símbolos sem relação de precedência definida, a tabela deverá estar em branco.
![Page 63: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/63.jpg)
Exemplo de construção de Tabela SR• Seja a gramática G=(N,T, <E>, P), onde:
N = {<E>, <T>, <F>} T = {+, ×, id , ( , ) } P = { <E> ::= <E> + <T> | <T> ;
<T> ::= <T> × <F> | <F> ;<F> ::= ( <E> ) | id }
• Pela Regra 1: $E• Pela Regra 2: E+ +T T×
×F (E E)• Pela Regra 3: $E $T +T +F ×(
×id (E (T $F +( +id (F $( $id (( (id
![Page 64: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/64.jpg)
Exemplo de construção de Tabela SR (cont.)
• Seja a gramática G=(N,T, <E>, P), onde:N = {<E>, <T>, <F>} T = {+, ×, id , ( , ) } P = { <E> ::= <E> + <T> | <T> ;
<T> ::= <T> × <F> | <F> ;<F> ::= ( <E> ) | id }
• Pela Regra 4: E>$
• Pela Regra 5: T>+ F>× T>)• Pela Regra 6: T>$ F>+ )>× id>×
F>) F>$ )>+ id>+ )>) id>) )>$ id>$
![Page 65: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/65.jpg)
Exemplo de construção de Tabela SR (cont.)
id + × ( ) $$ S SE S S R*T R S R RF R R R Rid R R R R+ S S× S S( S S) R R R R
indica reconhecimentoda sentença
indica combinaçãoerrônea de símbolos
![Page 66: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/66.jpg)
Geradores de Analisadores Sintáticos
• Ferramentas similares e complementares aos geradores de analisadores léxicos.
• Ferramentas mais comuns: yacc (yet another c compiler) e bison.– lex gera a função yylex( ) que retorna o identificador
de um item léxico reconhecido.– yacc gera a função yyparse( ), que analisa os itens
léxicos e decide se eles formam ou não uma sentença válida.
![Page 67: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/67.jpg)
Passos para Gerar Analisador Sintático• Escrever programa analisador léxico ou usar
ferramenta lex para tal.• Escrever gramática da linguagem em arquivo
com extensão .y .• Escrever programa analisador sintático ou usar a
ferramenta yacc para tal.• Compilar e ligar os programas-fonte.
– Para yylex( ) e yyparse( ) trabalharem em conjunto é preciso garantir que os tokens e seus valores sejam comuns às duas funções.
![Page 68: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/68.jpg)
Formato Geral da Gramática de yacc
• Similar ao da gramática de lex– Três seções no arquivo .y :
definições (declaração de nomes e tipos de tokens, de variáveis etc)
%%regras (contém as produções da gramática em BNF:
símbolo ::= derivações {ações semânticas} )%%rotinas do usuário (contém a função principal
main( ) e outras rotinas do usuário)
![Page 69: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/69.jpg)
Exemplo de Geração de Analisador Sintático
• Gramática G = (N,T,<stat>,P)N = {<stat> , <expr> , <termo> , <fator> }
T = { INT , REAL , IDN , ( , ) , + , - , * , / }
P = { <stat> ::= <expr>; <expr> ::= <expr> (+ | - ) <termo> | <termo> ; <termo> ::= <termo> ( * | / ) <fator> | <fator> ; <fator> ::= INT | REAL | IDN | ( <expr> ) }
![Page 70: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/70.jpg)
Criação de Arquivo .y%token IDN%token INT%token REAL%token SIMB_ATR%token SIMB_PA1%token SIMB_PA2%token SIMB_MUL%token SIMB_DIV%token SIMB_SOM%token SIMB_SUB%token SIMB_POT%token SIMB_END%start stat
%%stat: SIMB_END | expressao SIMB_END { /* Ação Semântica 0 */ printf("<stat> ::= <expressao> SIMB_END\n"); exit(1); } ;
expressao: termo { /* Ação Semântica 1 */
printf("<expr> ::= <termo> \n"); } | expressao SIMB_SOM termo { /* Ação Semântica 2 */
printf("<expr> ::= <expr> + <termo>\n"); } | expressao SIMB_SUB termo { /* Ação Semântica 3 */
printf("<expr> ::= <expr> - <termo>\n"); } ;/* demais regras devem ser incluídas . . . */%%main( ) {
yyparse( );}
![Page 71: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/71.jpg)
Utilização do Analisador Sintático• Função main( ) deve ser retirada do analisador
léxico, para que somente uma exista no conjunto .• Analisador sintático y.tab.c é gerado por
> yacc teste.y (usando o nome teste para o arquivo .y )• Os programas-fonte devem ser compilados e
ligados, formando o executável analisador .> gcc -o analisador y.tab.c lex.yy.c -ll -ly
![Page 72: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/72.jpg)
Usando o Analisador Sintático> analisador93 + (122)Token da classe <Inteiro><fator> ::= INTToken da classe <Op. Soma>Token da classe <Abre parênteses>Token da classe <Inteiro><fator> ::= INTToken da classe <Fecha parênteses><fator> ::= ( <expr> )<expr> ::= <expr> + <termo><stat> ::= <expr> SIMB_END
![Page 73: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/73.jpg)
Análise Semântica noAnalisador Sintático
• Ações semânticas podem ser atribuídas às produções da gramática– Gramática se torna gramática com atributos.– Exemplo
Produção Ação Semântica<expr> ::= <termo> Atribuir valor de <termo> a <expr> .<expr> ::= <termo> (+|-) <termo>
Valor de <expr> é a soma/subtração dos valores dos filhos.<termo> ::= <fator> Atribuir valor de <fator> a <tarmo> .<termo> ::= <fator> (*|/) <fator>
Valor de <termo> é o produto/divisão dos valores do filhos.<fator> ::= <expr> Atribuir valor de <expr> a <fator> .<fator> ::= <INT> Atribuir valor do token léxico <INT> a <fator> .
• Não existe gerador “universal” para analisadores semânticos.– É possível aproveitar gerador de analisadores sintáticos para definir ação
atribuída a cada produção.
![Page 74: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/74.jpg)
Criação de Arquivo .y%token IDN%token INT%token REAL%token SIMB_ATR%token SIMB_PA1%token SIMB_PA2%token SIMB_MUL%token SIMB_DIV%token SIMB_SOM%token SIMB_SUB%token SIMB_POT%token SIMB_END%start stat
%%stat: SIMB_END | expressao SIMB_END { /* Ação Semântica 0 */ printf("Resultado = %d \n", $1); exit(1); } ;
expressao: termo { /* Ação Semântica 1 */ $$ = $1; } | expressao SIMB_SOM termo { /* Ação Semântica 2 */ $$ = $1 + $3; printf("Soma de %d e %d = %d \n", $1, $3, $$); } | expressao SIMB_SUB termo { /* Ação Semântica 3 */ $$ = $1 - $3;
printf("Diferença de %d e %d = \n", $1, $2, $$); } ;/* demais regras devem ser incluídas . . . */%%main( ) {
yyparse( );}
![Page 75: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/75.jpg)
Utilização do Analisador Sintático-Semântico
• É a mesma adotada para o analisador sintático:• Cria-se o analisador y.tab.c através de
> yacc teste.y (usando o nome teste para o arquivo .y )• Compila-se e liga-se os programas-fonte y.tab.c e
lex.yy.c , para gerar arquivo executável analisador .> gcc -o analisador y.tab.c lex.yy.c -ll -ly
![Page 76: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/76.jpg)
Exemplo de uso do Analisador Sintático-Semântico
> analisador103 - (54 + 9)Token da classe <Inteiro>Token da classe <Op. Subtração>Token da classe <Abre parênteses>Token da classe <Inteiro>Token da classe <Op. Soma>Token da classe <Inteiro>Token da classe <Fecha parênteses>Soma de 54 e 9 = 63Diferença de 103 e 63 = 40Resultado = 40>
![Page 77: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/77.jpg)
Análise Semântica• É difícil verificar por meio de gramáticas:
– se todas as variáveis estão declaradas;– se variáveis estão sendo usadas com o tipo no qual
foram declaradas.• Análise semântica cuida do inter-relacionamento
entre partes distintas do programa.• Tarefas básicas:
– verificação de tipos de variáveis;– verificação de fluxo de controle;– verificação de unicidade de declaração de variáveis;– outras tarefas, dependendo da linguagem.
![Page 78: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/78.jpg)
Exemplos de Análise Semântica- verificação de tipos -
• Na compilação com gcc do código em C:int teste(int a, float b){
return a%b;}
teríamos o seguinte erro:In function 'teste':...: invalid operands to binary %
acusado pelo analisador semântico, pois o operador “ % ” (módulo) não admite operando real.
![Page 79: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/79.jpg)
Exemplos de Análise Semântica- verificação de fluxo de controle -
• Na compilação com gcc do código em C:void teste(int i, int j){
if (j == k)break;
elsecontinue; }
teríamos os seguintes erros:In function 'teste':...: break statement not within loop or switch...: continue statement not within a loop
acusados pelo analisador semântico, pois o comando break só pode ser usado dentro de um laço ou no final de um switch-case, e o continue só pode ser usado em laços.
![Page 80: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/80.jpg)
Exemplos de Análise Semântica- verificação de unicidade -
• Na compilação com gcc do código em C:void teste(int k){
struct { int a;float a;} x;
float x;switch (k){
case 0x31: x.a = k;case '1': x = x.a; }
teríamos os seguintes erros:In function 'teste':...: duplicate member 'a'...: previous declaration of 'x'...: duplicate case value
![Page 81: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/81.jpg)
Conversão automática de tipos• Vários compiladores fazem conversão
automática de tipos quando encontram alguma incompatibilidade.– Conversão conhecida também como coerção ou cast.
• Exemplos: codigo = codigo – '0'
– a constante '0' é convertida do tipo char para o tipo int antes de se resolver a expressão aritmética.
medida = 5.9 + 2
– a constante inteira 2 é convertida do tipo int para o tipo float antes de se resolver a expressão aritmética.
![Page 82: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/82.jpg)
Conversão manual de tipos• O programador pode controlar as conversões de
tipos manualmente por meio dos operadores de molde.– Coloca-se o nome do tipo desejado entre parênteses
antes da expressão cujo resultado deve ser convertido.• Ex. 1: int a, *ponteiro;
a = ponteiro;
– compilando as linhas acima obteríamos:warning: assignment makes integer from pointer without a cast
• Ex. 2: int a, *ponteiro; a = (int) ponteiro;
– neste caso não obteríamos nenhum alerta, pois o tipo de ponteiro seria convertido para int antes da atribuição.
![Page 83: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/83.jpg)
Geração de Código
• Geração ótima de código não é factível.• Geração de código orientada a sintaxe:
– adicionar à gramática as ações que escrevem num arquivo a sequência de instruções adequadas a cada redução.
• Normalmente feita em duas etapas:– geração de código intermediário com base em processador fictício;– conversão do código intermediário em código definitivo para o
processador alvo.• Tipos de código intermediário:
– notação posfixa– código de três endereços
![Page 84: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/84.jpg)
Código de Três Endereços• Composto por instruções com operações unárias,
operações binárias e uma atribuição.– Instruções envolvem no máximo três variáveis: duas
para os operandos e uma para receber resultados.• Esta é a razão para o nome “Três Endereços”.
– Quatro tipos básicos de instruções:• atribuição• desvios• chamada a rotinas• acesso (indireto ou indexado)
![Page 85: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/85.jpg)
Código de Três Endereços- instruções de atribuição -
• Três formas básicas:– variável recebe resultado de operação binária
a = b operador c ;– variável recebe resultado de operação unária
a = operador b ;– variável recebe valor de outra variável
a = b ;• Ex.:
– instruções em C: a = b + c * d ;– instruções intermediárias:
t = c * d ;a = b + t ;
![Page 86: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/86.jpg)
Código de Três Endereços- instruções de desvio -
• Possuem duas formas básicas:– desvio incondicional: GOTO rótulo– desvio condicional: IF x operador y GOTO rótulo
• Exemplo:
while (i++ <= k)x[i] == 0;
x[0] = 0 ;
_L1: if i>k goto _L2; i := i + 1; x[i] := 0; goto _L1;_L2: x[0] := 0;
![Page 87: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/87.jpg)
Código de Três Endereços- instruções de chamada de rotinas -
• Ocorre em duas etapas:– argumentos são devidamente armazenados pela
instrução param ;– rotina é efetivamente chamada pela instrução call;
• pode ou não haver valor de retorno.• Exemplo: para chamar uma função func(a,b,c) o
código intermediário seriaparam aparam bparam c_t1 := call func,3
– o valor “3” após a chamada mostra quantos argumentos foram armazenados para serem usados na chamada à rotina.
![Page 88: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/88.jpg)
Código de Três Endereços- instruções de acesso -
• Acessos indexados:– Exemplos:
a := b[i]d[j] := c
• Acessos indiretos: permitem manipulação de endereços.– Exemplos:
a := &b c := *d
*e := f
![Page 89: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/89.jpg)
Código de Três Endereços- representação interna -
• Baseada em tabelas de três ou quatro colunas.• Ex. para expressão a = b + c * d ;
1
2
operador arg_1 arg_2 resultado
* c d _t
+ b _t aquádrupla
tripla: associaresultados aos números de linha na tabela
1
2
operador arg_1 arg_2
* c d
+ b (1)
![Page 90: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/90.jpg)
Notação Posfixa• Também conhecida por notação polonesa ou
notação polonesa reversa (RPN).• Características:
– operador vem após operandos;– não exige parênteses;– pode ser eficientemente implementada em máquinas
baseadas em pilhas (máquinas de zero endereços):• operandos são inseridos e retirados do topo da pilha com
instruções tipo push e pop;• operadores retiram da pilha os operandos e devolvem o
resultado da operação para o topo da pilha.• Exemplos:
a * b + c ; ==> a b * c +(a + b) * (c + d) ==> a b + c d + *
![Page 91: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/91.jpg)
Exemplo de processadorcom notação posfixa
• Repertório parcial de instruções de um processador fictício:
Código Mnemônico Função
11 LDC <valor> Empilhe valor. 12 LD Desempilhe endereço e empilhe
conteúdo deste endereço. 13 ST Desempilhe valor; desempilhe endereço;
armazene valor neste endereço. 16 ADD Desempilhe a; desempilhe b; empilhe b+a . 17 SUB Desempilhe a; desempilhe b; empilhe b-a .
![Page 92: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/92.jpg)
Exemplo de uso de processador fictício• Resolução de a = (2+3) - 1;
– Em notação posfixa: 2 3 + 1 - a =– Sequência de instruções:
Mnemônico Conteúdo da pilha
LDC <end. de a> <end. de a>LDC 2 <end. de a> , 2LDC 3 <end. de a> , 2 , 3ADD <end. de a> , 5LDC 1 <end. de a> , 5 , 1SUB <end. de a> , 4ST
![Page 93: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/93.jpg)
Adaptação do Arquivo .y%token IDN%token INT%token REAL%token SIMB_ATR%token SIMB_PA1%token SIMB_PA2%token SIMB_MUL%token SIMB_DIV%token SIMB_SOM%token SIMB_SUB%token SIMB_POT%token SIMB_END%start stat
%%stat: SIMB_END | expressao SIMB_END { /* Ação Semântica 0 */ exit(1); } ;
expressao: termo { /* Ação Semântica 1 */ $$ = $1; } | expressao SIMB_SOM termo { /* Ação Semântica 2 */ $$ = $1 + $3; fprintf("ADD \n",); } | expressao SIMB_SUB termo { /* Ação Semântica 3 */ $$ = $1 - $3;
fprintf("SUB \n"); } ;/* demais regras devem ser incluídas . . . */%%main( ) {
yyparse( );}
![Page 94: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/94.jpg)
Otimização• Conjunto de transformações no código gerado
visando minimização de tempo de execução e/ou memória ocupada.– Otimização independente de máquina:
• Não considera a arquitetura da máquina, como p. ex.x + 0 --> x
– Otimização dependente da máquina:• Usa recursos da arquitetura para melhorar o código
ADD --> ADDQ (no 68000)– Otimização local: considera apenas um bloco de
instruções.– Otimização global: considera todo o procedimento.
![Page 95: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/95.jpg)
Otimização por Trecho de Instruções• Técnica de otimização local que inclui:
– Eliminação de códigos redundantes– Eliminação de códigos não alcançáveis– Eliminação de desvios desnecessários– Redução de complexidade– Uso de modos de endereçamento
![Page 96: Compiladores - Unicamp• Há compiladores que geram código em linguagem assembly. – Formalização da gramática de linguagem de máquina é difícil. • Rotinas de tradução](https://reader034.vdocuments.net/reader034/viewer/2022050214/5f608664b69e39545f100b9c/html5/thumbnails/96.jpg)
Otimizações Independentes de Máquina• Eliminação de expressões comuns• Propagação de cópias• Eliminação de códigos mortos• Otimização em laços
– Movimento de códigos– Eliminação de variáveis de indução
• Substituições algébricas