Buscar

LFA - Lista de exercicios

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 19 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 19 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 19 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Universidade Paulista (UNIP) 
Ciência da Computação 
Linguagens Formais e Autômatos 
Prof. Nelson Batista Leitão Neto 
Aluno: Matheus Aloisio Caetano de Brito Neves 
RA: N1480F-2 
 
 
Exercícios 01: 
 
1) O que vem a ser um compilador, dentro de suas características predominantes? Dê 
exemplos e faça uma simulação. 
R. Simplificando, um compilador é um programa que lê um programa escrito em uma 
linguagem - a linguagem fonte - e a traduz em um programa equivalente em outra 
linguagem - a linguagem alvo. Um exemplo de compilador é o Android Studio que traduz 
instantaneamente a linguagem. 
 
2) Como se divide um compilador? Explique cada uma delas. A geração de Árvore Sintática 
é feita em qual das etapas? Como é executada? 
R. Existem duas partes na compilação: a ANÁLISE e a SÍNTESE: 
ANÁLISE: Divide o programa fonte nas partes constituintes e cria uma representação 
intermediária. 
SÍNTESE: Constrói o programa objeto desejado, a partir da representação intermediária. 
A geração de Árvore Sintática é feita na Análise. as operações implicadas pelo programa 
fonte são determinadas e registradas numa estrutura hierárquica. 
 
3) Quais são as 4 ferramentas que manipulam programas fontes? Explique cada uma delas. 
R. EDITORES DE ESTRUTURAS - Recebe como entrada um conjunto de comandos 
para construir um programa fonte. 
PRETTY PRINTERS (“impressoras bonitas”)- Analisa um programa e o imprime numa 
forma em que a sua estrutura se torne claramente visível. 
VERIFICADORES ESTÁTICOS - Lê um programa, analisa-o e tenta descobrir erros 
potenciais, sem executá-lo. 
INTERPRETADORES - Em lugar de produzir um programa objeto como resultado da 
tradução, um interpretador realiza as operações especificadas pelo programa fonte. 
 
4) Dado as fases do Compilador, explique detalhadamente cada uma delas: 
• Análise Léxica; 
R. Nesta fase o arquivo de entrada é varrido caractere a caractere. 
Símbolos especiais (espaço em branco, símbolos de pontuação e new line) são 
utilizados para estabelecer os limites das palavras. 
Eliminação de espaços em branco e comentários. 
Durante a análise léxica, as palavras ou lexemas são guardados na tabela de 
símbolos e classificados de acordo com a linguagem, em palavras reservadas, 
comandos, variáveis e tipos básicos. 
Identificação de erros léxicos ("overflow" de campo numérico, uso de símbolos não 
pertencentes ao alfabeto da linguagem). 
 
• Análise sintática; 
R. É responsável pela verificação da boa formação dos comandos da linguagem, 
de acordo com as regras especificadas pela gramática da linguagem. 
Sentenças mal formadas, geralmente, interrompem o processo de compilação e 
são apresentadas como mensagens de erro. 
No fim da análise sintática, temos a representação do programa original de forma 
hierárquica, onde o programa é representado por uma árvore sintática. 
Uma árvore sintática é uma representação compactada de uma árvore PARSE na 
qual os operadores aparecem como nós interiores e os operandos de um operador 
são os filhos do nó daquele operador. 
Os erros de sintaxe são mais frequentes que os erros léxicos. 
Identificação e recuperação de erros de sintaxe. 
Construções léxicas não requerem recursão, enquanto as sintáticas sim. 
As gramáticas livres de contexto são uma formalização de regras recursivas que 
podem ser usadas para guiar a análise sintática. 
 
• Análise Semântica; 
R. A Análise semântica mais comum consiste na verificação da consistência de 
tipos dos operandos envolvidos em operações aritméticas ou dos parâmetros 
passados a procedimentos. 
O código intermediário deve ser fácil de produzir e fácil de traduzir no programa 
objeto. 
 
• Geração do Código Intermediário; 
R. O gerador de código intermediário será acionado quando o programa for 
analisado léxica, sintática e semanticamente, se encontrando correto do ponto de 
vista das três análises citadas. 
Neste ponto do projeto, entra a parte de análise e entramos no processo de 
síntese. 
Para essa geração, deve-se percorrer a árvore em profundidade (depth first), para 
que o código seja gerado das folhas para os nós. 
 
• Otimizador de Código; 
R. Reorganiza o código para um melhor desempenho, em tempo de execução. 
 
• Tratamento de Erros; 
R. Tipos de erros: léxicos, sintáticos, semânticos e lógicos. 
Os erros sintáticos são os mais frequentes. 
 
• Estratégias de recuperação de erros; 
R. Estratégias de recuperação de erros: 
1) PANIC MODE (modo de pânico) - O compilador descarta símbolos de entrada 
até encontrar um token de sincronização (“;" ou "end"). 
2) PHASE LEVEL (nível de fase) - O compilador tenta corrigir o erro encontrado, 
sem alterar o código fonte. (colocar um ";" onde não tem ou trocar ":" por ";"). 
3) PRODUÇÃO DE ERRO - Pode ser usado quando se sabe, de antemão, quais 
são os erros mais prováveis de acontecer; acrescenta-se à gramática, algumas 
produções que usam as construções erradas. 
4) CORREÇÃO GLOBAL - Tenta calcular a sequência mínima de mudanças para 
a correção de um erro. 
 
• Gerenciamento da Tabela de Símbolos; 
R. Uma função essencial do compilador é registrar os identificadores usados no 
programa fonte e coletar as informações sobre os seus diversos atributos de um 
identificador, tais como: (memória alocada, tipo, escopo). 
Uma tabela de símbolos é uma estrutura de dados contendo um registro para 
cada identificador, com os campos contendo os atributos do identificador. 
 
• Geração do Código; 
R. O gerador de código objeto é a última parte de um compilador. 
A tarefa central desse gerador de código é transformar uma especificação de 
código intermediário vinda da etapa anterior para uma especificação de código 
assembly, para poder ser executado num PC. 
 
• Geração do Módulo Executável; 
R. Compilação é o processo de tradução de um programa escrito em linguagem 
de alto nível para código em linguagem de máquina. Compilação é um processo 
análogo ao da montagem (verificação / análise do código fonte, resolução das 
referências de memória, reserva de espaço em memória e conversão para código 
de máquina binário). O que diferencia a compilação do processo de montagem é 
sua maior complexidade. No processo de montagem, há uma relação de 1:1, ou 
seja, cada instrução do código fonte resulta em uma instrução de máquina, 
enquanto na compilação a relação é múltipla, cada instrução do código fonte 
gerando várias instruções de máquina. 
Durante a compilação, o código fonte é analisado (análise léxica, sintática e 
semântica), é gerado um código intermediário e são construídas tabelas de 
símbolos, alocam-se as áreas de memória para variáveis e atribui-se os 
registradores a serem utilizados, e é finalmente gerado o código objeto em 
linguagem binária de máquina. Em alguns compiladores, é gerado um código 
intermediário em Assembly (que pode ser visualizado pelo programador) e que em 
seguida passa pelo montador para gerar finalmente o código objeto em linguagem 
de máquina. 
O código objeto pode ser absoluto (os endereços constantes são endereços reais 
de memória) ou realocável (os endereços são relativos, tendo como referência o 
início do programa, e os endereços reais de memória são definidos apenas em 
tempo de execução). 
 
• Edição de Ligações; 
R. Assim, o código objeto preparado pelo compilador em geral não é 
imediatamente executável, pois ainda existe código (as rotinas de biblioteca) a ser 
incorporado ao programa. 
A cada chamada de biblioteca encontrada no código fonte, o compilador precisará 
incluir uma chamada para a rotina e o endereço dos dados que devam ser 
passados para a rotina. 
A tarefa de examinar o código objeto, procurar as referências a rotinas de 
biblioteca (que constituem referências externas não resolvidas), buscar a rotina da 
biblioteca, substituir a chamada pelo código ("resolver as referências externas") e 
obter os parâmetros para incluí-los no código objeto é executada por um programa 
chamado Ligador (LinkEditor). O resultado da execução do Ligador é o código 
final pronto paraser executado pelo computador, chamado módulo de carga ou 
código executável. 
O módulo de carga, após testado e depurado (isto é, depois de resolvidos todos 
os erros, também chamados "bugs") é armazenado em memória de massa para 
ser executado quando necessário. 
O processo de compilação e ligação é executado apenas pelo programador na 
fase de desenvolvimento e não mais precisará ser executado pelo usuário, 
quando da execução do programa. 
 
Lista 1 
 
1) Escreva 5 palavras para cada um dos alfabetos abaixo: 
 
∑ = { GU, DA, BA, JA } 
R. Palavra sobre ∑: JABA, GUDADA, BADA,JAGU,GUJABADA 
∑ = { a, b,...,z, A, B,...,Z } 
R. Palavra sobre ∑: Matheus, Maria, AMORA, Aloisio, ALOISIO 
∑ = { 0, 1,..., 9 } 
R. Palavra sobre ∑: 18, 10, 23 ,01, 52 
∑ = { +, *, @, #, ?, ! } 
R. Palavra sobre ∑: @#, ?!, +@?, *!#, #+ 
∑ = { w, q, b, s } 
R. Palavra sobre ∑: wb, wq, ws, sb,sq 
∑ = { ~, $, %, ^, \ } 
R. Palavra sobre ∑: ~?, ^%, $\, ~$\, %? 
∑ = { t1, t2, t3, t4, t5, t6 } 
R. Palavra sobre ∑:t1t2, t4t3,t2t6, t5t1, t5t4 
∑ = { aa, bb, cc, dd,..., zz } 
R. Palavra sobre ∑: aabbcc, aaccdd, bbaavv, zzaa, mmtt 
∑ = { ab, cd, ef, gh, ij, lm, no, pq, rs, tu, vxz} 
R. Palavra sobre ∑: abcdef, abef, nolm, tuvxz, pqrs 
∑ = { xX, yY, zZ, wW, tT } 
R. Palavra sobre ∑: xXzZ, tTwW, yYzZwW, wWtT, zZyY 
∑ = { 10, 20, 30, 40, 50, 60 } 
R. Palavra sobre ∑: 1020,1050, 6050, 204050, 6030 
∑ = { 1a, 2b, 3c, 4d, 5e, 6f, 7g, 8h } 
R. Palavra sobre ∑: 1a6f, 2b7g,8h5e2b,4d3c, 7g8h3c 
∑ = { V,F,X,W } 
R. Palavra sobre ∑: VF,XW, VW,FXW, VFXW 
Ø = { A, B, CC } 
R. Palavra sobre Ø: AB, BA, ACC,CCAB,BACC 
Y = { Maria, Joao, Jose, Sonia } 
R. Palavra sobre Y: MariaJoao, JoseSonia, SoniaMaria, JoaoMaria, JoseMariaJoao 
 
 
2) Dado ∑ = {a, b}, escreva: 
Todas as palavras possíveis sobre ∑ de comprimento 1 
R. |a|, |b| 
Todas as palavras possíveis sobre ∑ de comprimento 2 
R. |ab|, |ba|, |aa|, |bb| 
Uma palavra qualquer sobre o ∑ de comprimento 15 = 
R. |ababaabbaabbaab| 
Duas palavras quaisquer sobre o ∑ de comprimento 7 
R. |abbaaba|, |baabbab| 
Três palavras quaisquer sobre o ∑ de comprimento 5 
R. Palavra sobre ∑: abbab, baaba, bbbabb 
 
 
3) Dado ∑ = { dó, ré, mi, fá, sol, lá, si }, determine o comprimento da palavra: 
a) | ré | = 1 
b) | dórémifá | = 4 
c) | milámilámilámilá | = 8 
d) | solsisollásol | = 5 
e) | solsifámidórélá | = 7 
f) | solsolsol | = 3 
g) | miréfamirésolmirésimirélámiré | = 14 
 
LISTA 02 
 
 
1) Dado ∑ = { a,b } , x = aabbb, y = bbbaa e z = abab palavras sobre ∑, escreva: 
a) yε 
bbbaa 
b) xyy 
aabbbbbbaabbbaa 
c) xxx 
aabbbaabbbaabbb 
d) y3 
bbbaabbbaabbbaa 
e) xy2 
aabbbbbbaabbbaa 
f) y2εx2 
bbbaabbbaaaabbbaabbb 
g) xzy 
aabbbababbbbaa 
h) zxy 
ababaabbbbbbaa 
i) zεx2 
ababaabbbaabbb 
j)zzx 
ababaaabbb 
l) yzx2 
bbbaaababaabbbaabbb 
m)z4 
abababababababab 
n)z2x2y2 
ababababaabbbaabbbbbbaabbbaa 
o) z2x2y 
ababababaabbbaabbbbbbaa 
 
2) Dado ∑ = { a, b, c }, escreva: 
 
a)∑0 = { ε } 
 
b)∑1 = { a, b, c } 
 
c)∑2 = { a, b, c }{ a, b, c } = {aa,ab,ac,ba,bb,bc,ca,cb,cc} 
 
d)∑3 = { a, b, c }{ a, b, c }{ a, b, c } = { a, b, c }{aa,ab,ac,ba,bb,bc,ca,cb,cc} = 
{aaa,aab,aac,aba,abb,abc,aca,acb,acc,baa,bab,bac,bba,bbb,bbc,bca,bcb,bcc, 
caa,cab,cac,cba,cbb,cbc,cca,ccb,ccc } 
 
3) Dados as palavras x = wf, y = abab e z = vf, escreva o resultado da concatenação abaixo: 
 
a) xxy 
wfwfabab 
 
b) xyz 
wfababvf 
 
c) xzy 
wfvfabab 
 
d) z2y 
vfvfabab 
 
e) zεy3 
vfabababababab 
 
f) εyx 
ababwf 
 
g)x2y2z 
wfwfababababvf 
 
h)xy3x 
wfababababababwf 
 
4) Usando os alfabetos ∑ = { V,F } e Ø = { A, B, C } , determine os conjuntos abaixo: 
a) ∑0 ={ ε } 
 
b) ∑1 = { V,F } 
 
c) Ø2 = Ø Ø {A,B,C}{A,B,C}={AA,AB,AC,BA,BB,BC,CA,CB,CC} 
 
d) ∑2 = { V,F }{ V,F } = {VV,VF,FV,FF} 
 
e) ∑3 = { V,F }{ V,F }{ V,F } = { V,F }{VV,VF,FV,FF} ={ VVV,VVF,VFV,VFF, FVV,FVF,FFV,FFF } 
 
 
LISTA 03 
Exemplos: 
 
Dado ∑ = {a,b}, determinar as linguagens definidas pelas seguintes expressões regulares: 
 
a) a | b 
temos: L(a)={a} e L(b)={b} 
 
L(a | b) = L(a) U L(b) = { a } U { b } = {a,b} 
 
 
b) (a | b) (a | b) 
temos: L((a | b) (a | b)) = L(a | b) L(a | b) 
 
L((a | b) (a | b)) = {a,b} {a,b} = {aa, ab, ba, bb} 
 
c) a* 
temos: (L(a))* = L (a)* 
L(a)* = L(a)0 U L(a)1 U L(a)2 U L(a)3 U ... 
L(a)0 = { ε } 
L(a)1 = L(a) = {a} 
L(a)2 = L(a) L(a) = {a} {a} ={aa} 
L(a)3 = L(a)2L(a) = {aa} {a} = {aaa} 
L(a)* = { ε, a, aa, aaa, … } 
 
d) (a | b)2 
= L (a | b)2 = L(a | b) L(a | b) = {a,b}{a,b} = {aa, ab, ba, bb} idem letra “b” 
 
e) (a | b)* = 
temos: L( a | b)* = L(a | b)0 U L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)0 = { ε } 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )* = { ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
 
f) (a | a*b) 
temos: L ( a | a*b) = L (a) | L(a*b) 
L (a) = { a } 
L (a*b) = L (a)* L(b) 
L(a)* = L(a)0 U L(a)1 U L(a)2 U L(a)3 U ... 
L(a)0 = { ε } 
L(a)1 = L(a) = {a} 
L(a)2 = L(a) L(a) = {a} {a} ={aa} 
L(a)3 = L(a)2L(a) = {aa} {a} = {aaa} 
L(a)* = { ε, a, aa, aaa, … } 
 
L(a*b) = { ε, a, aa, aaa, … }{b} 
L(a*b) = {b, ab, aab, aaab, ...} 
 
L(a | a*b) = {a} U {b, ab, aab, aaab, ...} = {a, b, ab, aab, aaab, ... } 
 
g) (a | b) a* 
temos: (L(a))* = L (a)* 
L(a)* = L(a)0 U L(a)1 U L(a)2 U L(a)3 U ... 
L(a)0 = { ε } 
L(a)1 = L(a) = {a} 
L(a)2 = L(a) L(a) = {a} {a} ={aa} 
L(a)3 = L(a)2L(a) = {aa} {a} = {aaa} 
L(a)* = { ε, a, aa, aaa, … } 
 
L(a) U L(b) = { a } U { b } = {a,b} 
 
L(a | b) a* = {a,b} { ε, a, aa, aaa, … } ={aε, aa, aaa, aaaa,... ,bε, ba, baa, baaa, … } 
 
h) b*a 
temos: (L(b))* = L (b)* 
L(b)* = L(b)0 U L(b)1 U L(b)2 U L(b)3 U ... 
L(b)0 = { ε } 
L(b)1 = L(b) = {b} 
L(b)2 = L(b) L(b) = {b} {b} ={bb} 
L(b)3 = L(b)2L(b) = {bb} {b} = {bbb} 
L(b)* = { ε, b, bb, bbb, … } 
L(a) = {a} 
Lb*a = { ε, b, bb, bbb, … }{a} = { εa, ba, bba, bbba, … } 
 
 
i) b+ a 
temos L(b+) e L(a) 
L (b+)= {b,bb,bbb,bbbb, ...} e L(a)={a} 
Lb+ a ={b,bb,bbb,bbbb, ...} {a} ={ba,bba,bbba,bbbba, ...} 
 
j) (a | b )+ 
temos: L( a | b)+ = L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )+ = { a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
 
 
l) a ( a | b )* a 
temos: L( a | b)* = L(a | b)0 U L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)0 = { ε } 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )* = { ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
 
La ={a} 
Então: {a} { ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} {a} = 
L a ( a | b )* a ={ aεa , aaa, aba, aaaa, aaba, abaa, abba, aaaaa, ..., abbba, aaaaaa,...} 
 
m) b ( a | b )+ b 
temos: L( a | b)+ = L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )+ = { a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
Lb ={b} 
Então: {b}{ a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...}{b} 
L b ( a | b )+ b = { bab, bbb, baab, babb, bbab, bbbb, baaab, ..., bbbbb, baaaab,...} 
 
n) ab ( a | b )* 
temos: L( a | b)* = L(a | b)0 U L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)0 = { ε } 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )* = { ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
Lab = Lab= {ab} 
Lab ( a | b )*={ab}{ ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
Lab ( a | b )*= { abε , aba, abb, abaa, abab, abba, abbb, abaaa, ..., abbbb, abaaaa,...} 
 
o) b+ ( a | b ) 
temos: L(a)={a} e L(b)={b} 
 
L(a | b) = L(a) U L(b) = { a } U { b } = {a,b} 
L(b)+ = {b, bb, bbb, … } 
Lb+ ( a | b ) = {b, bb, bbb, … }{a,b} 
Lb+ ( a | b ) = {ba,bba,bbba,... , bb,bbb,bbbb, ...} 
 
 
p) ( ( a* b ) | ( bab ) ) ( a | b ) 
temos ( a* b ) = L(a)* = { ε, a, aa, aaa, … } Lb ={b} 
(a*b)= { εb, ab, aab, aaab, … } 
Temos ( bab )= La ={a} Lb={b} La={a} 
(bab) = {a}{b}{a} = {aba} 
Temos (( a* b ) | ( bab )) = { εb, ab, aab, aaab, … } U {aba} 
Logo { εb, ab, aab, aaab, …,aba} 
Temos L(a)={a} e L(b)={b} 
L(a | b) = L(a) U L(b) = { a } U { b } = {a,b} 
Então =( ( a* b ) | ( bab ) ) ( a | b ) 
{ εb, ab, aab, aaab, …,aba}{a,b} 
{ εba, aba, aaba, aaaba, …,abaa, εbb, abb, aabb, aaabb, …,abab } 
 
 
q) ( ab ) ( a | b )* 
temos: L( a | b)* = L(a | b)0 U L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)0 = { ε } 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb} 
 
L( a | b )* = { ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
Lab = La ={a} Lb={b} 
Lab ( a | b )*= {a}{b}{ ε , a, b, aa, ab, ba, bb, aaa, ..., bbb, aaaa,...} 
Lab ( a | b )*= { aε , aa, ab, aaa, aab, aba, abb, aaaa, ..., abbb, aaaaa,..., bε , ba, bb, baa, bab, 
bba, bbb, baaa, ..., bbbb, baaaa,...}} 
 
 
r) a ( ba ) ( b | a )+ 
temos: L( a | b)+ = L(a | b)1 U L(a | b)2 U L(a | b)3 U ... 
L(a | b)1 = { a, b} 
L(a | b)2 = L( a | b ) L ( a | b) = { a,b } { a,b } = {aa, ab, ba, bb} 
L(a | b)3 = L( a | b)2 L( a | b) = {aa, ab, ba, bb } { a , b } = {aaa, aab, aba, abb, baa, bab, bba, 
bbb ...} 
Temos (ba)= Lb={b} e La ={a} 
L( ba ) ( b | a )+ = {b}{a}{aaa, aab, aba, abb, baa, bab, bba, bbb, ...} 
{baaa, baab, baba, babb, bbaa, bbab, bbba, bbbb, ... , aaaa, aaab, aaba, aabb, abaa, abab, 
abba, abbb, ...} 
Logo a ( ba ) ( b | a )+ = {a}{baaa, baab, baba, babb, bbaa, bbab, bbba, bbbb, ... , aaaa, aaab, 
aaba, aabb, abaa, abab, abba, abbb, ...} 
{abaaa, abaab, ababa, ababb, abbaa, abbab, abbba, abbbb, ... , aaaaa, aaaab, aaaba, aaabb, 
aabaa, aabab, aabba, aabbb, ...} 
 
Seja ∑1 = {a,b,...,z} e ∑2 = {0,1,...,9} os alfabetos sobre os quais foram definidos as linguagens 
L e D, respectivamente. Descreva as linguagens resultantes das seguintes operações 
realizadas sobre L e D: 
 
a) L+ D 
 
 
b) L ( L | D ) = 
 
c) D ( D | L ) 
 
 
 
 
 
 
LISTA 04 
 
1) Descreva o funcionamento do Analisador Léxico. 
R: Responsável por analisar o fluxo de entrada do compilador, que é o programa fonte, e 
retornar para o analisar sintático a sequência de tokens identificados, na forma da 
tupla (token,conteudo). 
2) Qual a funcionalidade do Analisador Sintático? 
R: Verificação da boa formação do comando. Esperamos que o analisador sintático 
relate quaisquer erros de quaisquer erros de sintaxe de uma forma inteligível. Deve também se 
recuperar dos erros que ocorram mais comumente, a fim de poder continuar processando o 
resto de sua entrada. 
3) Quais são os métodos mais usados para o desenvolvimento do Analisador Sintático? 
✓ R: Analisador Sintático Top-Down. 
 Constroem árvores do topo (raiz), para o fundo (folhas). 
✓ Analisador Sintático Botton-Up. 
Começam pelas folhas e trabalham a árvore acima até a raiz. Em ambos os casos, a 
entrada é varrida da esquerda para a direita, um símbolo de cada vez. 
4) Dentro do tratamento dos erros de sintaxe, quais são os níveis que podem conte-los? 
Explique cada um deles. 
R: Léxico: errar grafia de um identificador, palavra-chave ou operando. 
Sintático: expressão aritmética com parênteses não balanceados. 
Semântico: operando aplicado a um operando incompatível. 
Logico: chamada infinitamente recursiva. 
5) Explique como é feito e em que fase acontece esses tratamentos de erros de sintaxe. 
R: Na recuperação de erros, tenta-se colocar o analisador em um estado tal que o restante da 
sentença de entrada ainda possa ser analisado. Este processo pode envolver: a modificação da 
entrada (excluir tokens), a modificação da pilha, ou de ambos. 
6) Quais são as metas estabelecidas dentro do tratador de erros num analisador sintático? 
R: Deve relatar a presença de erros de forma clara, deve ser recuperar de cada erro 
suficientemente rápido a fim de se capaz de detectar erros subsequentes, não deve retardar o 
processamento de programas corretos. 
7) Descreva as estratégias de recuperação de erros: 
 a) Modalidade do desespero 
 Este é o método mais simples de implementar e pode ser usado pela maioria dos métodos 
de análise sintática. Ao descobrir um erro, o analisador sintático descarta símbolos de entrada, um de cada 
vez, até que seja encontrado um token pertencente a um conjunto designado de tokens de sincronização. A 
correção na modalidade do desespero, que frequentemente pula uma parte considerável da entrada sem 
verificá-la, procurando por erros adicionais, possui a vantagem da simplicidade e, diferentemente dos 
outros métodos a serem enfocados adiante, tem a garantia de não entrar num laço infinito. 
 b) Recuperação de Frases 
 Ao descobrir um erro, o analisador sintático pode realizar uma correção local na entrada 
restante. Isto é, pode substituir um prefixo da entrada remanescente por alguma cadeia que permita ao 
analisador seguir em frente. Correções locais típicas seriam substituir uma vírgula por ponto-e-vírgula, 
remover um ponto-e- vírgula estranho ou inserir um ausente. 
a) Produção de Erro 
Se tivéssemos uma boa idéia dos erros 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. 
Usamos, então, a gramática aumentada com essas produções de erro para construir um analisador 
sintático. Se uma produção de erro for usada pelo analisador, podemos gerar diagnósticos apropriados 
para indicar a construção ilegal que foi reconhecida na entrada. 
b) Correção Global 
Idealmente, gostaríamos que um compilador fizesse tão poucas mudanças quanto possível, 
ao processar uma cadeia de entrada ilegal. Existem algoritmos para escolher uma sequência mínima de 
mudanças de forma a se obter uma correção global de menor custo. Dadas uma cadeia de entrada 
incorreta x e uma gramática G, esses algoritmos irão encontrar uma árvore gramatical para uma cadeia 
relacionada y, de tal forma que as inserções, remoções e mudanças de tokens requeridas para 
transformar x em y sejam tão pequenas quanto possível. 
8) Descreva as partes de um Analisador Sintático. 
1 – TERMINAIS 
Símbolos básicos a partir dos quais a cadeia é formada. 
Ex.: if, then, else. 
2 – NÃO-TERMINAIS 
 Variáveis sintáticas que denotam cadeias de caracteres. 
Ex.: cmd, exp. 
3 – PRODUÇÃO 
 É a forma pela qual os terminais e os não-terminais podem ser combinados. 
4 – ESTADO DE PARTIDA (SENTENÇA) 
 Um não-terminal é distinguido como símbolo de partida, 
 então G = (T, NT, P, S). 
➢ SÍMBOLOS TERMINAIS 
a) Letra minúscula do inicio do alfabeto. 
b) . , ( ) + - * ... 
c) [id] [IF] [THEN]. 
➢ SÍMBOLOS NÃO-TERMINAIS 
c) Letras maiúsculas do alfabeto. 
d) Cadeias de terminais. 
e) Símbolo de partida (S). 
Ex.: ExPR → ExPr op exPr 
 ExPR → (ExPR) 
 ExPR → - ExPR 
 ExPR → id 
 OP → + 
 OP → * 
 OP → / 
 OP →  
 
TERMINAIS: id, +, -, *, /, , ( ). 
NÃO–TERMINAIS: ExPR e OP 
SÍMBOLO DE PARTIDA: ExPR. 
 
9) Resolver 3 exercícios do Módulo 1 e 3 exercícios do Módulo 2 de LFA, no sistema. do aluno 
on-line, no Portal da Unip. 
Módulo 1 
 
Módulo 2 
 
 
 
LISTA 05 – LFA – TRADUÇÃO DIRIGIDA PELA SINTAXE 
 
1)Dentro das produções e regras semânticas descritas no exemplo anterior, faça a 
implementação para que a calculadora de mesa também seja funcional para divisão e 
subtração;2) Agora, faça a representação da árvore gramatical para as seguintes expressões: 
 
o 5 * 4 + 7 
 F.val = 27 
 
 F.val = 20 T.val = 7 
 | | 
 F.val = 5 * T.val = 4 digito.lexval = 7 
 | | 
digito.lexval = 5 digito.lexval = 4 
 
Produção Regras Semânticas 
X → D n Imprimir (D. val) 
D → D1 + W D.val := D1.val + W.val 
D → W D.val := W.val 
W → W1 / G W.val := W1.val / W.val 
W → G W.val := G.val 
G → (D) G.val := D.val 
G → dígito G.val := dígito.lexval 
o 16 / 2 – 5 
 F.val = 3 
 
 F.val = 8 - T.val = 5 
 | | 
 F.val = 16 / T.val = 2 digito.lexval = 5 
 | | 
digito.lexval = 16 digito.lexval = 2 
 
o 6 * 8 + 9 / 3 
 
 F.val = 51 
 
 F.val = 48 + T.val = 3 
 | | 
 F.val = 6 * T.val = 8 W.val = 9 / T.val = 3 
 | | | | 
digito.lexval = 6 digito.lexval = 8 digito.lexval = 9 digito.lexval = 3 
 
o 18 / 6 – 2 * 1 
 F.val = 1 
 
 F.val = 3 - T.val = 2 
 | | 
 F.val = 18 / T.val = 6 W.val = 2 * T.val = 1 
 | | | 
digito.lexval = 18 digito.lexval = 6 digito.lexval = 2 digito.lexval = 1 
 
o 36 * 2 / 4 
 F.val = 18 
 
 F.val = 72 / T.val = 4 
 | | 
 F.val = 36 * T.val = 2 digito.lexval = 4 
 | | 
digito.lexval = 36 digito.lexval = 2 
 
 
 
 
o 20 – 10 / 2 + 4 
 F.val = 19 
 
 F.val = 15 + T.val = 4 
 | | 
 F.val = 20 - T.val = 5 dig.lexval = 4 
 
dig.lexval = 20 T.val = 10 / W.val = 2 
 | | 
 dig.lexval = 10 dig.lexval = 2 
 
 
3)Como são utilizados os atributos sintetizados? 
 
R: Estes são usados extensivamente na prática. Uma definição dirigida pela sintaxe que use 
exclusivamente atributos sintetizados é dita uma definição S-atribuida. Uma árvore gramatical 
para uma definição S-atribuida pode ser sempre anotada através da avaliação das regras 
semânticas para os atributos a cada nó, de baixo para cima, das folhas para raiz. 
 
4)Explique o principio de funcionamento completo da tradução dirigida pela sintaxe. 
 
R: Tradução dirigida pela sintaxe fundamentalmente funciona pela adição de ações às 
produções em uma gramática livre de contexto, resultando em uma Definição Dirigida pela 
Sintaxe. Ações são passos ou procedimentos que serão efetuados quando a produção for 
usada em uma derivação. Por convenção, colocam-se chaves ao redor de ações; as chaves 
forem necessárias como símbolos da gramática, utilizam-se aspas para diferenciar. Uma 
especificação de gramática incorporada com ações a serem executadas é chamada de 
esquema de tradução dirigida pela sintaxe (às vezes simplesmente 'esquema de tradução'). 
 
5)Como funciona o Analisador Semântico? 
R: A análise semântica percorre a árvore sintática relaciona os identificadores com 
seus dependentes de acordo com a estrutura hierárquica. 
Essa etapa também captura informações sobre o programa fonte para que as fases 
subsequentes gerarem o código objeto, um importante componente da análise 
semântica é a verificação de tipos, nela o compilador verifica se cada operador recebe 
os operandos permitidos e especificados na linguagem fonte. 
 
LISTA 06 
1-Dê a definição de atributos herdados. 
 
R: São convenientes para expressar construções de LPs em relação ao contexto em 
que aparecem. Bastante útil na verificação de tipos. Controlar se um identificador 
aparece do lado esquerdo (endereço) ou direito (valor) de uma atribuição 
 
2-Explique o princípio de funcionamento dos atributos herdados. 
 
R: Úteis para especificar dependência do contexto, por exemplo se um identificador 
aparece à esquerda ou direita de uma atribuição. 
 
 
3-Qual a finalidade de um compilador verificar se existem conversões, dentro de sua análise? 
 
R: Essa checagem, chamada de verificação estática, assegura que certos tipos de erro 
de programa serão detectados e reportados 
 
4-Quais são os tipos de verificações estáticas? Descrevê-las. 
 
R: Verificação de tipos: Um compilador deveria relatar um erro se um operador for 
aplicado a um operando incompatível. 
https://pt.wikipedia.org/wiki/Gram%C3%A1tica_livre_de_contexto
Verificação do fluxo de controle: os enunciados que fazem o fluxo de controle deixar 
uma construção precisam ter algum local onde transferir o controle. 
Ex.: um enunciado break em C faz com que o controle deixe o while, for ou switch 
envolvente mais interno; um erro ocorre se um tal enunciado envolvente não existir. 
 
Verificação de unicidade: Existem situações nas quais um objeto precisa ser definido 
exatamente uma vez. 
Ex.: em Pascal, um identificador precisa ser declarado univocamente (só admite uma 
interpretação), os rótulos precisam ser distintos, e os elementos num tipo escalar não 
podem ser repetidos. 
 
Verificação relacionada aos nomes: Algumas vezes, o mesmo nome precisa figurar 
duas ou mais vezes. 
Ex.: Na linguagem ADA, um laço ou bloco precisa ter um nome que apareça ao início e 
ao final da construção. O compilador precisa verificar se o mesmo nome é usado em 
ambos os locais. 
 
 
5-Faça o diagrama da posição do verificador de tipos. 
 
 
 
6-Qual a finalidade do uso de árvores sintáticas como forma de representação interna? Como 
os operadores e palavras-chave funcionam, dentro desta estrutura? 
 
R: O uso de árvores sintáticas como forma de representação interna permite que a 
tradução seja desacoplada da análise sintática. Numa árvore sintática, os operadores e 
palavras-chave não figuram como folhas, mas, são associados ao nó interior que seria o 
pai daquelas folhas na arvore gramatical. Outra simplificação encontrada nas arvores 
sintáticas é que as cadeias de produções podem ser eliminadas.

Continue navegando