Você está na página 1de 12

COMPILADORES - Atividade 01 - Capítulos 1 e 2.

Aluno: Carlos Eduardo de Lima Matrícula: 20192135000286

Exercício 1.1.1: Qual é a diferença entre um compilador e um


interpretador? R.:

Um interpretador lê e executa código-fonte linha por linha, instrução por instrução.


Ele não faz a tradução do código-fonte em linguagem de máquina ou em código
intermediário, ele já executa diretamente. Os interpretadores são mais lentos que os
compiladores, pois fazem a tradução e a execução em tempo real. Já um compilador
faz a tradução do código-fonte completo para código de máquina ou código
intermediário antes de executar o programa. É feito também uma análise. Os
compiladores se desempenham melhor que os interpretadores pelo fato de a
tradução ser feita antes.
Interpretada -> Python, Javascript, PHP.
Compilada - > C, C++

Exercício 1.1.2: Quais são as vantagens de


(a) um compilador sobre um interpretador? R.: A principal vantagem seria que os
programas compilados geralmente são mais rápidos, devido à tradução completa do código
antes da execução.
(b) um interpretador sobre um compilador? R.: A principal vantagem seria a
facilidade de depurar, pois seria possível ver os resultados de cada linha de código
imediatamente, enquanto o compilador faria primeiro a tradução completa do código antes
da execução.

Exercício 1.1.3: Quais as vantagens de um sistema de processamento de linguagem


em qual o compilador produz linguagem assembly em vez de linguagem de
máquina? R.: Seria a portabilidade, pois o código assembly é mais legível, facilitaria
a manutenção e depuração e permitiria também a otimização.

Exercício 1.1.4: Um compilador que traduz uma linguagem de alto nível para outra
linguagem de alto nível é chamada de tradutor fonte a fonte. Quais são as
vantagens de usar C como uma linguagem de destino para um compilador? R.: A
linguagem C é usada ainda por muitos profissionais e por estudantes que estão
começando na programação pelo fato de sua portabilidade, eficiência, recursos e
muitas coisas da área da computação tem o C como código base. Essas são as
prováveis vantagens.

Exercício 1.1.5: Descreva algumas das tarefas que um montador precisa executar.
R.: O montador faz: tradução de símbolos, endereços e variáveis, faça a detecção
de erros e faz tarefas para organizar e gerar o código executável.
Exercício 1.3.1: Indique qual R.:
dos seguintes termos: a) a) imperativo -> (1) C, (2) C++
imperativo b) declarativa -> (3) Cobol
b) declarativa aplicam-se a qual dos
c) Von Neumann seguintes idiomas: (1) C
d) orientado a objetos (2) C++
e) funcional (3) Cobol
f) terceira geração (4) Fortran
g) quarta geração (5) Java
h) script (6) Lisp
(7) ML
(8) Perl
(9) Python
(10) VB.
c) Von Neumann -> (1) C, (2) C++, (5) Java
d) orientado a objetos -> (2) C++, (5) Java
e) funcional -> (6) Lisp
f) terceira geração -> (1) C, (2) C++, (5) Java
g) quarta geração -> (5) Java
h) script -> (9) Python

Exercícios para Seção 1.6 (página 35)


Exercício 1.6.1: Para o código C estruturado em bloco da Fig. 1. 13(a), indique os
valores atribuídos a w, x, y e z. R.:
Figura 1.13 A Z= 9
W= 13
X= 11 (Dúvida)
Y= 15
Exercício 1.6.2: Repita
o Exercício 1.6.1 para
o código da Fig.
1.13(b).
Figura 1.13 B
W= 9
X= 9 (Dúvida)
Y= 13
Z= 7

Exercício 1.6.3: Para o


código estruturado em
bloco da Fig. 1. 14,
assumindo o habitual
escopo estático de declarações, forneça o escopo para cada uma das doze
declarações.

Exercício 1.6.4: O que é impresso pelo seguinte código C?

R.:
b= (x+1)
c= (x+1)

Exercícios para Seção 2.2 (página 51)


Exercício 2.2.1 : Considere a gramática livre de contexto:

a) Mostre como a string aa+a* pode ser gerada por essa gramática.
R.:
S -> SS | aS+ | aaS+S+ | aa+aS+S+ | aa+a* | aa+a*

b) Construa uma árvore sintática para esta string.

S
/|\
a S
/|\
S +
/|\
aS
|\
S *
/|\
a S
|\
S
|
a

c) Que linguagem essa gramática gera? Justifique sua resposta.


R.: A gramática gera a linguagem com expressão aritmética sobre o a, com
isso pode também fazer repetições com o a e com os operadores +.

Exercício 2.2.2 : Que linguagem é gerada pelas seguintes gramáticas? Em cada


caso justifique sua resposta. R.:

A - 0011, 000111, 000000111111


B - a, a+a, a-a, a+a-a
C - (Faltou)
D - aba, abbba, bbaabbb
E - a, a+a, aa, (a+a)a, (aa)+(a+a)

Exercício 2.2.3: Quais das gramáticas do Exercício 2.2.2 são ambíguas? R.:
B, E

Exercício 2.2.4: Construa gramáticas livres de contexto não ambíguas para cada
uma das seguintes linguagens. Em cada caso, mostre que sua gramática está
correta.

a) Expressões aritméticas em notação pós-fixada.


R.: 5 3 + 2*

b) Listas associativas à esquerda de identificadores separados por vírgulas.


R.: A, B, C, D

c) Listas associativas à direita de identificadores separados por vírgulas. R.:


, A, B, C, D
d) Expressões aritméticas de números inteiros e identificadores com os
quatro binários operadores +, - , *, /.
R.: 2 + A * 3 - Z / 4

Exercício 2.2.5:
a) Mostre que todas as cadeias binárias geradas pela seguinte gramática têm
valores divisíveis por 3. Dica. Use indução no número de nós em uma árvore de
análise.

b) A gramática gera todas as strings binárias com valores divisíveis por 3?

Exercício 2.2.6: Construa uma gramática livre de contexto para numerais romanos.
S -> CM | M -> C | D | L | IV
-> C | D | L | IV
-> M | D | L | IV
-> M | CM | L | IV
-> M | C | C | IV
-> M | C | M | IV
-> M | C | M | IV
-> M | C | M | IV

Exercícios para Seção 2.3 (página 60)


Exercício 2.3.1: Construa um esquema de tradução dirigida pela sintaxe que traduza
expressões aritméticas da notação infixa para a notação prefixada na qual um
operador aparece antes de seus operandos; por exemplo. , -xy é a notação de
prefixo para x-y . Forneça árvores sintática anotadas para as entradas 9-5+2 e 95*2.
Árvore Sintática:
E
/\
9 E
/\
- T
/\
5 F
|
2
Tradução Prefixada: + - 9 5 2

Árvore Sintática:
E
/\
9 E
/\
- T
/\
T F
/\
5 *
|
2

Tradução Prefixada: - 9 * 5 2

Exercício 2.3.2: Construa um esquema de tradução dirigida pela sintaxe que traduza
expressões aritméticas da notação pós-fixada para a notação infixa. Dê árvores
sintáticas anotadas para as entradas 95-2* e 952*-.

Árvore Pós-fixa:
95 2 * -

Tradução Infixa: (9 - 5) * 2

Árvore Pós-fixa:
952*-*+

Tradução Infixa: (9 - (5 * 2))

Exercício 2.3.3: Construa um esquema de tradução dirigida pela sintaxe que traduza
inteiros em algarismos romanos.
S
|
INT
/|\
D D D D
| | | |
2 0 2 1
Exercício 2.3.4: Construa um esquema de tradução dirigida pela sintaxe que traduza
algarismos romanos em números inteiros.
S
|
ROMANO
|
"X"

Exercício 2.3.5: Construa um esquema de tradução dirigida pela sintaxe que traduz
expressões aritméticas pós-fixadas em expressões aritméticas infixas equivalentes.
23 5 + 7*
S
|
EXPRESSAO
| | |
OPERANDO OPERADOR OPERANDO
| | |
NUMERO + OPERANDO
| | |
23 OPERANDO
| | |
NUMERO *
| |
5 7

Exercícios para Seção 2.4 (página 68)


Exercício 2.4.1: Construa parsing descendentes recursivos, começando
com o seguinte gramáticas:

a) S
|
a a)
S
/|\
+SS
||
a-
/\
aS

b) S
|
()
/ \
S S
| |
() ε /
\ε ε

c) S
/\
0 S
/\
0 S
/\
0 S
/\
0 1
|
1

Exercícios para Seção 2.6 (página 84)


Exercício 2.6.1: Estenda o analisador léxico na Seção 2.6.5 para remover
comentários, definido da seguinte forma:

a) Um comentário começa com // e inclui todos os caracteres até o final de aquela


linha.

if (peek == '/') {
peek = (char) System.in.read();
if (peek == '/') {
// É um comentário do tipo //, então leia até o final da linha
while (peek != '\n' && peek != -1) {
peek = (char) System.in.read();
}
// Continue a leitura após o comentário
return scan();
} else {
// Não era um comentário, apenas o caractere '/'
return new Token('/');
}
}

b) Um comentário começa com / * e inclui todos os caracteres até o próximo


ocorrência da sequência de caracteres * /.

// Código anterior ...

public Token scan() throws IOException {


// Código anterior ...

if (peek == '/') {
peek = (char) System.in.read();
if (peek == '/') {
// É um comentário do tipo //, então leia até o final da linha
while (peek != '\n' && peek != -1) {
peek = (char) System.in.read();
}
// Continue a leitura após o comentário
return scan();
} else if (peek == '*') {
// É um comentário do tipo /* */, então leia até encontrar */
peek = (char) System.in.read();
while (true) {
if (peek == '*') {
peek = (char) System.in.read();
if (peek == '/') {
// Fim do comentário /* */
peek = ' ';
return scan();
}
} else {
peek = (char) System.in.read();
}

if (peek == -1) {
// Fim do arquivo, comentário não fechado
return new Token(Tag.INVALID, "Comentário não fechado");
}
}
} else {
// Não era um comentário, apenas o caractere '/'
return new Token('/');
}
}

// Código posterior ...


}

Exercício 2.6.2: Estenda o analisador léxico na Seção 2.6.5 para reconhecer o


operadores relacionais <, <=, ==, ! =, >=, >.

// Código anterior ...

public Token scan() throws IOException {


// Código anterior ...
if (peek == '/') { //
Código anterior ...
} else if (peek == '<') {
peek = (char) System.in.read();
if (peek == '=') {
peek = ' ';
return new Word(Tag.OP_REL, "<=");
} else {
return new Token('<');
}
} else if (peek == '=') { peek
= (char) System.in.read();
if (peek == '=') {
peek = ' ';
return new Word(Tag.OP_REL, "==");
} else {
return new Token('=');
}
} else if (peek == '!') { peek =
(char) System.in.read();
if (peek == '=') {
peek = ' ';
return new Word(Tag.OP_REL, "!=");
} else {
// Operador de negação
return new Token('!');
}
} else if (peek == '>') { peek
= (char) System.in.read();
if (peek == '=') {
peek = ' ';
return new Word(Tag.OP_REL, ">=");
} else {
return new Token('>');
}
}

// Código posterior ...


}

Exercício 2.6.3: Estenda o analisador léxico na Seção 2.6.5 para reconhecer


números de pontos flutuantes como 2. , 3.14, e .5.

// Código anterior ...

public Token scan() throws IOException {


// Código anterior ...

if (Character.isDigit(peek) || peek == '.') {


// Início do reconhecimento de números, incluindo ponto flutuante StringBuilder
numLexeme = new StringBuilder();

while (Character.isDigit(peek)) {
numLexeme.append(peek);
peek = (char) System.in.read();
}
if (peek == '.') {
numLexeme.append(peek);
peek = (char) System.in.read();

// Parte decimal while


(Character.isDigit(peek)) {
numLexeme.append(peek);
peek = (char) System.in.read();
}
}

// Verifica se há um ponto no final (por exemplo, 2. ou .5)


if (numLexeme.charAt(numLexeme.length() - 1) == '.') {
numLexeme.append('0');
}

return new Real(Double.parseDouble(numLexeme.toString()));


}

// Código posterior ...


}

Você também pode gostar