10 minuto(s) de leitura

Aula I

Compilar

Traduzir algo escrito em uma determinada linguagem para uma linguagem de máquina.

Traduz um código fonte (alto nível) para um código objeto binário (baixo nível).

Código fonte -> compilador -> código executável

História

no inicio programas eram escritos em ling de maq

o primeiro compilador foi criado por Grace Hooper em 1952, A-0 System (Univac I)

compilador completo em 1957, FORTAN - John Backus

Componentes

  • Análise léxica
  • Análise sintática
  • Análise semântica
  • Geração e otimização de código

Analise léxica

Vai executar os autômatos.

Identificar os elementos do textos, caractere por caractere.

Verificar se a palavra é reservada, constante, variável.

Ignora comentários.

Analise sintática

Identifica as construções válidas da linguagem com base nos elementos léxicos.

Analise semântica

Garante que as construções identificadas façam sentido de acordo com as regras da linguagem.

Verifica se as variáveis usadas foram devidamente declaradas

Gerador de código

Criação de código de baixo nível que reflete os comandos do código fonte.

Otimização dos comandos gerados para uma determinada arquitetura.

Exemplo

soma := soma + 35

Análise léxica

(valor) (classe)

SOMA identificador

:= comando de atribuição

SOMA identificador

  • operador numérico de adição

35 constante numérica inteira

Análise sintática

Árvore de execução (desenho).

Caso a análise léxica esteja certa, constrói a árvore e código está certo.

Distribui as expressões, sequencias e operações

Em linguagens formais e autômatos → processo de derivação na linguagem → procurava derivar.

Criava a árvore de derivação → aqui é árvore sintática.

Linguagens formais não seguiam nenhum algoritmo específico → tentava e erro.

analisador sintatioc

Análise semântica

SOMA foi declarada?

SOMA é variável?

Qual o escopo de SOMA?

Qual o tipo de SOMA?

Coloca informações adicionais na árvore

Geração de código

Movimentação de registradores

Código dentro do processador (assembly).

MOV AX, [soma]
ADD AX, 35
MOV [soma], AX

Componentes em detalhes

componentes em detalhes

Compiladores vs Interpretadores

Existência das três analises (léxica, sintática e semântica).

Compilador faz trabalho rápido.

Interpretadores geram código objeto durante a execução.

Interpretadores são mais lentos, porem alterações no código são mais rápidas de serem realizadas.

Bytecode

Presente no Java.

Ao invés de gerar comandos em linguagens de maquina, os comandos são armazenados na forma de códigos binários.

Este código será então interpretado por uma maquina virtual.

Compila até uma parte, depois manda para a máquina virtual.

Bom para rodar em arquitetura diferentes (um código Java feito no Linux pode rodar no Linux, Windows e Mac sem problemas).

Alula 2

O que é gramática?

Gramática é uma ferramenta para descrever uma linguagem.
É a base do analisador léxico e sintático.

Onde autômatos finitos são utilizados?

Autômatos finitos são utilizados na análise lexicográfica para reconhecimento dos programas e na definição de suas estrutras.

O que é um compilador?

É um tradutor entre duas linguagens (L1 e L2) de programação.
Neste caso L1 representa o código fonte e L2 o código de máquina.

Relembrando

Alfabeto: conjunto finito não vazio de símbolos.
Palavra: sequência finita de símbolos do alfabeto.
Comprimento da palavra: número de símbolos que compõem a palavra.
Concatenação ou produto de palavras.

Uma linguagem sobre um alfabeto Σ é um subconjunto de Σ*.

Qual é a regra geral da gramática?

Gramática G=(V,T,P,S), onde:
– V: conjunto de símbolos não terminais
– T: conjunto de símbolos disjuntos de V
– P: conjunto de regras de produção
– S: elemento de V denominado inicial

Exemplo 1

image

image

Exemplo 2

Obs: fere regra de produção - símbolos não terminais não podem estar nos dois lados (EOE).

image

image

Detecção de erros

Dinâmicos

São erros originados em tempo de execução Ex: input não esperado do usuárui

Estáticos

São erros encontrados durante a compilação

  • identificadores ma contruidos (analise lexica).
    Verifica se reconhece os elementos.
    Ex: na seguiu as regras de variaveis

  • Desrespeito a gramatica - “syntaxa error” (analise sintatica).
  • Desrespeita a política de tipos, visibilidade de identificadores, passagem de parâmetros, etc (análisesemântica).

image

Qual a função da análise léxica?

Sua função é ler o arquivo fonte e “etiquetar” os elementos significativos.
Estes elementos significativos são chamados de tokens

O que são tokens?

Tokens são os significados dos padrões de caracteres em um código fonte.

O processo de varredura é um caso especial de casamento de padrões.
Métodos utilizados: Expressão regular (ER) e autômatos finitos.
A velocidade do processamento é um ponto crítico.

O que é lexema?

Lexema é a sequência de caracteres na fonte que se associa a um padrão e então a um token - instância do token.

Simplificando

Lexema -> variavel / operação encontrado no codigo (if, sum, …)
Token -> como é representada |(numero, literal, …)

image

A palavra léxico faz referencia ao conjunto teoricamente infinito de todas as palavras já realizadas e potenciais de uma língua
Em linguagem de programação, palavras são objetos como nomes de variáveis, números, keywords.
Estas palavras são chamadas de tokens.

image

Entenda VALOR como Lexema e CLASSE como Token.

Input: letras individuais das palavras.
Output: strings divididas em tokens.
Descarta espaços em branco (espaços, quebra de linha e etc) e comentários.

Qual o objetivo da análise léxica?

Facilitar o trabalho do analisador sintático.

Por que separar o analisador léxico do analisador sintático?

Pois é mais eficiente, modular e tradicional.

O que faz um gerador léxico?

Transforma especificações de tokens e espaços em branco (em linguagem humana compreensível) em programas eficientes.

Especificações léxicas são geralmente escritas usando expressões regulares.
ER: notação algébrica para descrever um conjunto de caracteres.
Assim, os gerados léxicos são descritos como autômatos finitos.

Análise léxica - ER

image

image

Estrutura léxica - MiniJava

image

Análise léxica - ER (continuação)

image

Exercício 1

image

Respostas

a) 0*
42

b) 0∗
([0−9] |
[1−3][0−9] |
4[0−1] |
4[3−9] |
[5−9][0−9] |
[1−9][0−9][0−9]+)

c) 0∗ (4[3−9] |
[5−9][0−9] |
[1−9][0−9][0−9]+)

Qual é o melhor autômato para reconhecer as palavras?

É p autômato finito deterministico com o minimo de estados.

Vamos estudar 3 etapas

  • ER para Autômato Finito Não Deterministico (AFN).
  • Autômato Finito Não Deterministico (AFN) para Autômato Finito Deterministico (AFD).
  • Minimização de estado do Deterministico (AFD).

Análise léxica - ER para AFN

Utilização de fragmentos.
Colar os diversos fragmentos para construir o autômato completo.

image

image

Exercício 1

(a|b)*ac
Qual é o AFN?

image

image

Aula III

Exercício II

image

Análise léxica - AFN para AFD

Simula todos os caminhos de um AFN simultaneamente.
Criação de diversos “estados” de operação.
Cada estado se tornará um único AFD.

Epsilon-states

Sempre que estivermos em um estado AFN, nós sempre poderemos ler um símbolo vazio.
Assim, nos podemos usar uma transição vazia sem ler nenhum símbolo.

algoritmo

image

Exemplo 1

Passar o AFN do exercício 1 anterior para AFD.

(a b)*ac -> AFD.

image

E = {a,b,c}
s’0 = {1,2,5,6,7}
s’1 = {3,8,1,2,5,6,7}
s’2 = {8,1,2,5,6,7}
s’3 = {4}

(s’0,a) = {3,8} U {1,2,5,6,7}
s’1 = {3,8,1,2,5,6,7}

(s’0,b) = {8} U {1,2,5,6,7}
s’2 = {8,1,2,5,6,7}

(s’0,c) = {∅} U {∅}

(s’1,a) = {3,8} U {1,2,5,6,7}
(s’1,a) = {3,8,1,2,5,6,7} = s’1

(s’1,b) = {8} U {1,2,5,6,7}
(s’1,b) = {8,1,2,5,6,7} = s’2

(s’1,c) = {4} U {∅}
s’3 = {4} -> como possui 4, s’3 é um estado final.

(s’2,a) = {3,8} U {1,2,5,6,7}
(s’2,a) = {3,8,1,2,5,6,7} = s’1

(s’2,b) = {8} U {1,2,5,6,7}
(s’2,b) = {8,1,2,5,6,7} = s’2

(s’2,c) = {∅} U {∅}

(s’3,a) = {∅} U {∅}

(s’3,b) = {∅} U {∅}

(s’3,c) = {∅} U {∅}

Meu desenho:

image

CORREÇÃO DO PROFESSOR

image image image image image image image image image image image image

AFN e AFD

image

Aula IV

Exercíco 1

image image

E = {a,b}
s’0 = {1,2,3,4,5}
s’1 = {1,6,2,3,4,5}
s’2 = {6}
s’3 = {7,1,6,2,3,4,5}
s’4 = {7}
s’5 = {8,7,1,6,2,3,4,5}
s’6 = {8}


(s’0,a) = {1,6} U {2,3,4,5}
s’1 = {1,6,2,3,4,5}
entenda como:
s’0 percorrendo ‘a’ da {1,6}
{1,6} percorrendo vazio da {2,3,4,5}
Depois união de todos
{1,6,2,3,4,5}.

(s’0,b) = {6} U {∅}
s’2 = {6}
entenda como:
s’0 percorrendo ‘b’ da {6}
{6} percorrendo vazio da {∅}
Depois união de todos
{6}.

(s’1,a) = {7,1,6} U {2,3,4,5}
s’3 = {7,1,6,2,3,4,5}
entenda como:
s’1 percorrendo ‘a’ da {7,1,6}
{7,1,6} percorrendo vazio da {2,3,4,5}
Depois união de todos
{7,1,6,2,3,4,5}.

(s’1,b) = {6} U {∅}
s’1,b = {6} = s’2
entenda como:
s’1 percorrendo ‘b’ da {6}
{6} percorrendo vazio da {∅}
Depois união de todos
{6}.

(s’2,a) = {7} U {∅}
s’4 = {7}

(s’2,b) = {∅} U {∅}

(s’3,a) = {8,7,1,6} U {2,3,4,5}
s’5 = {8,7,1,6,2,3,4,5} -> como possui 8 e 8 é estado final no AFN, s’5 é um estado final.

(s’3,b) = {6} U {∅}
s’3,b = {6} = s’2

(s’4,a) = {8} U {∅}
s’6 = {8} -> como possui 8, s’6 é um estado final.

(s’4,b) = {∅} U {∅}

(s’5,a) = {8,7,1,6} U {2,3,4,5}
s’5,a = {8,7,1,6,2,3,4,5} = s’5

(s’5,b) = {6} U {∅}
s’5,b = {6} = s’2


Meu desenho:

image


CORREÇÃO DO PROFESSOR

image image image

Exercíco 2

image

q0 percorrendo 0 vai para q0 (loop).
q0 percorrendo 1 vai para q1.

q1 percorrendo 1 vai para q1 (loop).
q1 percorrendo 0 vai para q1 e q2 (criamos um estado q1q2).

Obs: Podemos fazer operação de união como no slide:
q1 percorre 0 -> {q1,q2}
q2 percorre 0 -> {q2}
União dos dois
{q1,q2}

q2 percorrendo 0 vai para q2 - para não criar novo estado deixamos q1q2 (loop).
q2 percorrendo 1 vai para q1q2 (loop)

q1 percorre 1 -> {q1}
q2 percorre 1 -> {q1,q2}
União dos dois
{q1,q2}

image

Exercíco 3

image

q0 percorrendo 0 vai para q0 e q1 (criamos um estado q0q1).
q0 percorrendo 1 vai para q1.

q0q1 percorrendo 0 vai para q0q1 (loop).

q0 percorre 0 -> {q0,q1}
q1 percorre 0 -> {∅}
União dos dois
{q0,q1}

q0q1 percorrendo 1 vai para q0q1 (loop).

q0 percorre 1 -> {q1}
q1 percorre 1 -> {q1,q0}
União dos dois
{q0,q1}

q1 percorrendo 1 vai para q0 (podemos aproveitar o estado q0q1 já que o q1 faz parte do loop).

image

Aula V

Último exercício de AFN para AFD.

ER = a(a bc)*

AFN = ex 1 AFN

AFD =

AFD: E = {a,b,c}
s’0 = {1}
s’1 = {2,3,4,5,8}
s’2 = {7,2,3,4,5,8}
s’3 = {6}

s’0 = {1} U {1}
s’0 = {1}

(s’0,a) = {2} U {3,4,5,8}
s’1 = {2,3,4,5,8} -> tem 8, estado final

(s’0,b) = {∅} U {∅}

(s’0,c) = {∅} U {∅}

(s’1,a) = {7} U {2,3,4,5,8}
s’2 = {7,2,3,4,5,8} -> tem 8, estado final

(s’1,b) = {6} U {∅}
s’3 = {6}

(s’1,c) = {∅} U {∅}

(s’2,a) = {7} U {2,3,4,5,8}
(s’2,a) = {7,2,3,4,5,8} = s’2

(s’2,b) = {6} U {∅}
(s’2,b) = {6} = s’3

(s’2,c) = {∅} U {∅}

(s’3,a) = {∅} U {∅}

(s’3,b) = {∅} U {∅}

(s’3,c) = {7} U {2,3,4,5,8}
(s’3,c) = {7,2,3,4,5,8} = s’2

ex 1 AFD

Vídeo Auxiliar: Assista

Flex/Lex

É uma linaguagem de analisador léxico.

Existem 3 maneiras de construir um analisador léxico:

  • Utilizar um gerador automático de analisadores léxicos.
  • Escrever um analisador léxico utilizando uma linguagem de programação convencional.
  • Escrever um analisador léxico utilizando uma linguagem de montagem.

Linguagem Lex

Gerador automático de analisadores léxicos.

Também conhecida como Flex em uma implementação mais recente.

Função:

  • Diferenciar os diversos tipos de tokens através de ER
  • Não verifica se todos as partes estão presentes
  • Decidir como sub-dividir os tokens

Estrutura de um programa Lex:

[definições]
%%
(expressão_regular [ação])*
[%%
funções auxiliares em C]

image

image

image

image

Exemplos

image

image

image

Tente fazer

image

Resposta

image

Exercícios

image

Exercício 1

image

Exercício 2

image

Exercício 3

image

Exercíco 4

image

Exercíco 5

image

Exercíco 6

image

Exemplos de Análise Léxica

image

image

Exercícios

Exercício 1

Código:

while indice < 10 do
 indice:= total + indice;

Sequência de tokens:
<while,> <id,7> «,> <numero,10> <do,> <id,7> <:=,> <id,12> <+,> <id,7> <;, >

Exercício 2

Código:

position = initial + rate * 60

Sequência de tokens:
<id, 1> <=, > <id, 2> <+, > <id, 3> <*, > <numero, 60>

Exercício 3

Código:

a[index] = 4 + 2

Sequência de tokens:
<id, 1> <[,> <id, 2> <],> <=,> <numero, 4> <+,> <numero, 2>

Exercício 4

Código:

position = initial + rate * 60

Sequência de tokens:
<id, 1> <=, > <id, 2> <+, > <id, 3> <*, > <numero, 60>

Extra

Código:

const a[book] = 5;
contador = 11;
while contador > 1 do {
	contador =- 1;
	if (contador <= 5) {
		a[contador] = contador + 2;
		print("numero inferior");
	}
}
contador *= 60;

Sequência de tokens:
<const, > <id, 1> <[, > <id, 2} <], > <=, > <numero, 5> <;, >
<id, 3> <=, > <numero, 11> <;, >
<while, > <id, 3> <>, > <numero, 1> <> <do, > <{, >
<id, 3> <=-, > <numero, 1> <;, >
<if, > <(, > <id, 1> «=,> <numero, 5> <), > <{, >
<id, 1> <[, > <id, 1> <], > <=, > <id, 3> <+, > <numero, 2> <;, >
<print, > <(, > <literal, “numero inferior”> <), > <;, >
<}, >
<}, >
<id, 3> <*=, > <numero, 60> <;, >

Deixe um comentário