Prévia do material em texto
RESUMO DE ATIVIDADES COMPILADORES – COM JUSTIFICATIVAS
Pergunta 1
5 em 5 pontos
Considere as alternativas a seguir e escolha apenas aquela que define o que é um
"analisador léxico" em um compilador.
Resposta
Selecionada:
c.
Um componente que remove comentários e espaços em branco do
código-fonte.
Respostas: a.
Um componente que gera o código executável a partir do código-
fonte.
b.
Um componente que verifica a sintaxe do código-fonte.
c.
Um componente que remove comentários e espaços em branco do
código-fonte.
d.
Um componente que otimiza o código-fonte para melhor
desempenho.
e.
Um componente que verifica se as variáveis no código-fonte estão
declaradas.
Comentário da
resposta:
JUSTIFICATIVA
Um analisador léxico é responsável por remover comentários e espaços
em branco do código-fonte, além de identificar os "tokens" ou símbolos
presentes no código, como palavras-chave, identificadores, números
etc.
Pergunta 2
5 em 5 pontos
Considere o processo de compilação de um programa e analise as afirmações para, em
seguida, assinalar a alternativa correta.
I. A execução do programa faz parte do processo de compilação.
II. A execução do programa é uma etapa separada após a compilação
III. Na análise léxica, os caracteres são lidos e, depois, agrupados em conjuntos que são
relevantes para outros componentes do compilador.
IV. Na análise semântica, são analisados erros sintáticos de um programa.
Resposta
Selecionada:
e.
Apenas II e III estão corretas.
Respostas: a.
Apenas II e IV estão corretas.
b.
Apenas I e III estão corretas.
c.
Apenas I e II estão corretas.
d.
Apenas I, II e III estão corretas.
e.
Apenas II e III estão corretas.
Comentário
da resposta:
JUSTIFICATIVA
(I) A execução do programa não faz parte do processo de compilação,
pois ocorre após o código-fonte ser traduzido para código executável
pelo compilador. (II) A compilação inclui análise léxica, análise sintática,
análise semântica e, opcionalmente, otimização de código, mas a
execução é uma etapa separada após a compilação. (IV) Na análise
semântica são verificados erros semânticos de um programa. A assertiva
(III) está correta, indicando a função da análise léxica.
Pergunta 1
Dado o seguinte código-fonte em uma linguagem de programação:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
Quantos tokens de identificador são gerados pelo analisador léxico nesse código?
Resposta Selecionada: c.
2
Respostas: a.
0
b.
1
c.
2
d.
3
e.
4
Comentário da
resposta:
JUSTIFICATIVA
No código fornecido, há dois identificadores: "i" e "System". "i" é usado
como uma variável, enquanto "System" é uma referência a uma classe
ou objeto.
Pergunta 2
3,34 em 3,34 pontos
Analise o seguinte trecho de código em uma linguagem de programação fictícia e responda
corretamente à pergunta:
if (x > 5) {
y = 10;
} else {
y = 20;
}
Qual é o token gerado pelo analisador léxico para o operador "else"?
Resposta Selecionada: a.
Palavra-chave
Respostas: a.
Palavra-chave
b.
Delimitador.
c.
Identificador.
d.
Operador relacional.
e.
Operador aritmético.
Comentário da
resposta:
JUSTIFICATIVA
O token gerado pelo analisador léxico para a palavra "else" é uma palavra-
chave, pois indica uma estrutura de controle condicional em muitas
linguagens de programação.
Pergunta 3
3,33 em 3,33 pontos
Considere o seguinte trecho de código em uma linguagem de programação fictícia:
int x = 42
Qual é o token gerado pelo analisador léxico para a palavra-chave "int"?
Resposta Selecionada: d.
Tipo de dado.
Respostas: a.
Identificador.
b.
Número.
c.
Operador de atribuição.
d.
Tipo de dado.
e.
Delimitador.
Comentário da
resposta:
JUSTIFICATIVA
O token gerado para a palavra-chave "int" é o tipo de dado, que
representa o tipo de variável que está sendo declarado.
Pergunta 1
3,34 em 3,34 pontos
Considere a seguinte regra gramatical simplificada para declarações de variáveis em uma
linguagem de programação como a PHP:
<declaration> ::= var <identifier> = <literal>;
Qual das seguintes declarações de variáveis está em conformidade com a regra gramatical
acima?
Resposta Selecionada: a.
var x = 5;
Respostas: a.
var x = 5;
b.
x = 5;
c.
var = 5;
d.
x = var 5;
e.
var 5;
Comentário da
resposta:
JUSTIFICATIVA
A declaração de variável var x = 5; está em conformidade com a regra
gramatical fornecida, pois segue a estrutura <declaration> definida como var
<identifier> = <literal>;, em que <identifier> é o nome da variável e <literal> é
um valor atribuído a ela.
Pergunta 2
3,34 em 3,34 pontos
Considere a seguinte gramática para expressões matemáticas simples:
<expr> ::= <term> + <expr> | <term> - <expr> | <term>
<term> ::= <factor> * <term> | <factor> / <term> | <factor>
<factor> ::= <number> | (<expr>)
<number> ::= [0-9]+
Qual das seguintes expressões é sintaticamente válida de acordo com essa gramática?
Resposta Selecionada: e.
(2 * (3 + 4))
Respostas: a.
2 * (3 + 4)
b.
2 * (3 + 4
c.
2 * 3 + 4
d.
2 * (3 + 4))
e.
(2 * (3 + 4))
Comentário da
resposta:
JUSTIFICATIVA
A expressão (2 * (3 + 4)) é sintaticamente válida de acordo com a
gramática fornecida, pois segue as regras definidas para expressão,
termo, fator e número.
Pergunta 3
3,32 em 3,32 pontos
Dado o seguinte trecho de código em uma linguagem de programação:
if (x > 5) {
y = 10;
}
Qual regra gramatical representa a estrutura condicional "if" no código acima?
Resposta Selecionada: a.
<stmt> ::= if (<expr>) { <stmt> }
Respostas: a.
<stmt> ::= if (<expr>) { <stmt> }
b.
<stmt> ::= if { <stmt> } else { <stmt> }
c.
<expr> ::= if (<stmt>) { <stmt> }
d.
<stmt> ::= if (<expr>) { <stmt> } else { <stmt> }
e.
<expr> ::= if (<stmt>)
Comentário da
resposta:
JUSTIFICATIVA
A estrutura condicional "if" no código é representada pela regra <stmt>
::= if (<expr>) { <stmt> }, em que <stmt> representa uma instrução,
<expr> representa uma expressão condicional e {} delimitam um bloco
de código.
Pergunta 1
2 em 2 pontos
Dado o seguinte trecho de código em uma linguagem de programação:
int main() {
int x = 5;
x = x + 1;
return x;
}
Suponha que você está construindo um analisador sintático ascendente LR(1) para essa
linguagem. Qual é o próximo passo de análise após reconhecer o seguinte símbolo: int x
= 5;?
Resposta
Selecionada:
b.
Procurar por um token de lookahead correspondente a uma instrução
dentro do bloco main().
Respostas: a.
Realizar uma redução da produção declaration para stmt.
b.
Procurar por um token de lookahead correspondente a uma instrução
dentro do bloco main().
c.
Procurar por um token de lookahead correspondente ao símbolo x.
d.
Realizar uma redução da produção stmt para declaration.
e.
Realizar uma redução da produção stmt para expression_stmt.
Comentário
da resposta:
JUSTIFICATIVA
Após reconhecer a produção int x = 5;, o próximo passo é procurar por
um token de lookahead que corresponda a uma instrução dentro do
bloco main(), pois a produção int x = 5; é uma declaração de variável e o
analisador deve continuar a análise dentro do escopo da função main().
Pergunta 2
2 em 2 pontos
Considere uma gramática livre de contexto para uma linguagem de programação. Você
está construindo um analisador sintático descendente LL(1) para essa gramática. Qual
das seguintes afirmações é verdadeira sobre a análise LL(1)?
Resposta
Selecionada:
b.
A análise LL(1) é baseada em lookahead, olhando apenas um
símboloà frente.
Respostas: a.
A análise LL(1) funciona apenas para gramáticas ambíguas.
b.
A análise LL(1) é baseada em lookahead, olhando apenas um
símbolo à frente.
c.
A análise LL(1) usa a técnica de redução para construir a árvore de
análise.
d.
A análise LL(1) é sempre mais eficiente do que a análise LR(1).
e.
A análise LL(1) não permite recursão à esquerda na gramática.
Comentário da
resposta:
JUSTIFICATIVA
A análise LL(1) é baseada na análise de lookahead, que envolve a
observação de um único símbolo seguinte na entrada para determinar a
próxima ação a ser tomada, tornando-a uma técnica eficiente.
Pergunta 3
2 em 2 pontos
Dado o seguinte trecho de código na linguagem de programação Python:
if (x > 0) then
y = x + 1;
else
y = x – 1;
Suponha que você está construindo um analisador sintático descendente LL(1) para essa
linguagem. Qual é o próximo passo de análise após reconhecer a produção if (x > 0)
then?
Resposta
Selecionada:
b.
Procurar por um token de lookahead correspondente a uma instrução
dentro do bloco then.
Respostas: a.
Realizar uma redução da produção if_stmt para stmt.
b.
Procurar por um token de lookahead correspondente a uma instrução
dentro do bloco then.
c.
Procurar por um token de lookahead correspondente a else.
d.
Realizar uma redução da produção stmt para if_stmt.
e.
Realizar uma redução da produção stmt para else_stmt.
Comentário
da resposta:
JUSTIFICATIVA
Após reconhecer a produção if (x > 0) then, o próximo passo é procurar
por um token de lookahead que corresponda a uma instrução dentro do
bloco then. Isso permite que o analisador determine qual caminho de
execução seguir com base na condição do if.
Pergunta 4
2 em 2 pontos
Analise a seguinte gramática LR(1):
1. S -> E
2. E -> E + T
3. E -> T
4. T -> T * F
5. T -> F
6. F -> ( E )
7. F -> id
Considere a entrada id + id * id. Qual é a ação que o analisador LR(1) deve tomar quando
chegar ao ponto onde id * id foi reconhecido?
Resposta Selecionada: b.
Reduzir a produção T -> F.
Respostas: a.
Reduzir a produção F -> id.
b.
Reduzir a produção T -> F.
c.
Deslocar o operador *.
d.
Reduzir a produção E -> T.
e.
Entrar em um estado de erro.
Comentário da
resposta:
JUSTIFICATIVA
Quando chega ao ponto onde id * id foi reconhecido, o analisador LR(1)
deve reduzir a produção T -> F para representar a derivação correta da
entrada. Isso envolve a substituição de F por T, refletindo a hierarquia de
operadores.
Pergunta 5
2 em 2 pontos
Suponha que você está construindo um analisador sintático descendente LL(1) para uma
linguagem de programação. Quando ocorre um conflito de parsing na tabela LL(1), qual
ação é tomada?
Resposta
Selecionada:
a.
O analisador entra em um estado de erro e para a análise.
Respostas: a.
O analisador entra em um estado de erro e para a análise.
b.
O analisador escolhe aleatoriamente uma das produções em conflito.
c.
O analisador consulta a tabela de precedência de operadores para
resolver o conflito.
d.
O analisador utiliza uma regra de desempate baseada na ordem de
aparição das produções na gramática.
e.
O analisador entra em um estado de aceitação e conclui a análise.
Comentário da
resposta:
JUSTIFICATIVA
Quando ocorre um conflito de parsing na tabela LL(1), o analisador
entra em um estado de erro e interrompe a análise, pois não pode
determinar qual produção aplicar com base no lookahead.
Pergunta 1
2 em 2 pontos
Considere o trecho de código de uma linguagem de programação a seguir:
x = 10
y = "20"
z = x + y
Sobre a análise semântica desse código, avalie as seguintes assertivas e classifique-as
em verdadeiras (V) ou falsas (F):
I. Não há erros de tipo no código, pois a linguagem permite operações entre inteiros
e strings.
II. A variável z terá o valor "1020" após a execução do código.
III. O código possui um erro de tipo, pois não é permitida a operação de adição entre um
inteiro e uma string.
IV. A variável y é usada antes de ser inicializada, o que resulta em um erro semântico.
V. A atribuição z = x + y é uma operação válida e não gera erros semânticos.
Assinale a alternativa com a ordem correta:
Resposta Selecionada: c.
V, F, V, V, F.
Respostas: a.
V, V, F, F, V.
b.
F, V, V, F, V.
c.
V, F, V, V, F.
d.
V, F, V, F, V.
e.
F, V, V, V, F.
Comentário
da resposta:
JUSTIFICATIVA
A afirmação I é verdadeira, pois a linguagem permite operações entre
inteiros e strings, e a afirmação III é verdadeira, pois a operação de
adição entre tipos diferentes gera um erro de tipo. A afirmação IV é
verdadeira, pois a variável y é usada antes de ser inicializada. A
afirmação II é falsa, pois a variável z terá o valor 1020 após a execução
do código. A afirmação V é falsa, pois a atribuição z = x + y gera um erro
de tipo.
Pergunta 2
2 em 2 pontos
A você foi dada a incumbência de escrever um compilador para uma linguagem de
programação que permite a declaração de variáveis com o mesmo nome em diferentes
escopos. Sobre essa situação, avalie as seguintes assertivas:
I. Nesse caso, a tabela de símbolos pode conter várias entradas com o mesmo nome,
mas em diferentes escopos.
II. Quando uma variável é referenciada em um programa, o compilador deve usar a regra
de "escopo mais próximo" para determinar qual variável com o mesmo nome é acessada.
III. A ordem de declaração das variáveis não afeta o resultado, já que o compilador usa
apenas o escopo mais próximo para determinar a variável a ser acessada.
IV. Em linguagens que permitem sombreamento de variáveis (variáveis com o mesmo
nome em escopos diferentes), a tabela de símbolos deve manter informações sobre os
escopos em que cada variável foi declarada.
V. O uso de variáveis com o mesmo nome em diferentes escopos pode causar
ambiguidades e erros semânticos, e o compilador deve tratá-los adequadamente.
Assinale a alternativa com a ordem correta:
Resposta Selecionada: a.
V, V, F, V, V.
Respostas: a.
V, V, F, V, V.
b.
V, V, V, V, F.
c.
V, V, F, V, F.
d.
F, F, V, V, V.
e.
F, V, F, F, V.
Comentário da
resposta:
JUSTIFICATIVA
I. Em linguagens que permitem o sombreamento de variáveis, a tabela
de símbolos pode conter várias entradas com o mesmo nome, mas em
diferentes escopos.
II. Quando uma variável é referenciada em um programa, o compilador
deve usar a regra de "escopo mais próximo" para determinar qual
variável com o mesmo nome é acessada.
III. A ordem de declaração das variáveis afeta o resultado, pois o
compilador usa o escopo mais próximo para determinar a variável a ser
acessada.
IV. Em linguagens que permitem sombreamento de variáveis, a tabela
de símbolos deve manter informações sobre os escopos em que cada
variável foi declarada.
V. O uso de variáveis com o mesmo nome em diferentes escopos pode
causar ambiguidades e erros semânticos, e o compilador deve tratá-los
adequadamente.
Pergunta 3
2 em 2 pontos
Sobre a tabela de símbolos no processo de estruturação de um compilador, avalie as
seguintes assertivas e classifique-as em verdadeiras (V) ou falsas (F):
(I) A tabela de símbolos é uma estrutura de dados que armazena informações sobre
variáveis, funções e outros identificadores em um programa.
(II) Cada entrada na tabela de símbolos geralmente contém informações como o nome do
identificador, seu tipo, seu escopo e seu endereço de memória (caso aplicável).
(III) A tabela de símbolos é usada apenas durante a análise sintática para verificar a
corretude sintática do código-fonte.
(IV) Em linguagens de programação, o escopo de um identificador pode afetar sua
visibilidade e acessibilidade em diferentes partes do código.
(V) Uma tabela de símbolosbem implementada deve garantir que não haja conflitos de
nome entre diferentes identificadores.
Assinale a alternativa com a ordem correta:
Resposta Selecionada: a.
V, V, F, V, V
Respostas: a.
V, V, F, V, V
b.
F, V, V, V, V
c.
V, V, V, V, F
d.
V, V, F, V, F
e.
F, F, V, F, V
Comentário da
resposta:
JUSTIFICATIVA
(I) Verdadeira: a tabela de símbolos é uma estrutura de dados que
armazena informações sobre identificadores em um programa.
(II) Verdadeira: cada entrada na tabela de símbolos geralmente contém
informações como o nome do identificador, seu tipo, seu escopo e
outras informações relevantes.
(III) Falsa: a tabela de símbolos é usada em várias fases do
compilador, não apenas durante a análise sintática.
(IV) Verdadeira: o escopo de um identificador pode afetar sua
visibilidade e acessibilidade.
(V) Verdadeira: uma tabela de símbolos bem implementada deve
garantir que não haja conflitos de nome entre diferentes
identificadores.
Pergunta 4
2 em 2 pontos
Considere que você está escrevendo um compilador para uma linguagem de
programação. Durante a análise semântica, qual é uma das principais tarefas
relacionadas à verificação de tipos?
Resposta
Selecionada:
d.
Garantir que os operadores sejam aplicados a operandos
compatíveis em termos de tipo.
Respostas: a.
Garantir que todas as variáveis tenham nomes exclusivos.
b.
Verificar se todas as instruções do programa estão corretamente
identadas.
c.
Certificar-se de que todas as variáveis sejam declaradas antes de
serem usadas.
d.
Garantir que os operadores sejam aplicados a operandos
compatíveis em termos de tipo.
e.
Verificar se a gramática da linguagem está correta.
Comentário da
resposta:
JUSTIFICATIVA
Uma das principais tarefas relacionadas à verificação de tipos na análise
semântica é garantir que os operadores sejam aplicados a operandos
compatíveis em termos de tipo, evitando, assim, erros de tipo durante a
execução do programa.
Pergunta 5
2 em 2 pontos
Analise as alternativas a seguir e assinale qual delas indica a principal função da análise
semântica em um compilador:
Resposta
Selecionada:
d.
Detectar e reportar erros de semântica no código-fonte.
Respostas: a.
Verificar a corretude léxica dos tokens na entrada.
b.
Verificar a gramática da linguagem de programação.
c.
Garantir que a sintaxe da linguagem seja interpretada
corretamente.
d.
Detectar e reportar erros de semântica no código-fonte.
e.
Otimizar o código-objeto gerado pelo compilador.
Comentário da
resposta:
JUSTIFICATIVA
O principal objetivo da análise semântica é detectar e relatar erros de
semântica no código-fonte, como incompatibilidades de tipos, uso
indevido de variáveis, dentre outros.
Pergunta 1
3,33 em 3,33 pontos
Ao gerar código intermediário para um compilador, qual das seguintes alternativas descreve
corretamente o uso de registradores temporários?
Respostas: a.
Registradores temporários são usados para armazenar dados permanentes
durante a execução do programa.
b.
Registradores temporários são usados apenas para armazenar valores
constantes.
c.
Registradores temporários são usados para armazenar valores intermediários
durante a compilação.
d.
Registradores temporários são usados apenas para armazenar variáveis globais.
e.
Registradores temporários não são necessários em compiladores.
Comentário da
resposta:
JUSTIFICATIVA
Registradores temporários são usados para armazenar valores intermediários
durante a compilação, ajudando na geração de código intermediário eficiente
e na otimização do código final. Eles não são usados para armazenar dados
permanentes ou variáveis globais.
Pergunta 2
3,33 em 3,33 pontos
Ao gerar código intermediário para uma expressão aritmética em um compilador, qual das
seguintes alternativas apresenta uma técnica comum para lidar com a ordem das operações?
Respostas: a.
Usar notação pós-fixa (ou notação polonesa reversa).
b.
Usar notação pré-fixa (ou notação polonesa).
c.
Usar apenas uma pilha de operadores.
d.
Resolver as operações em ordem alfabética.
e.
Resolver as operações em ordem inversa.
Comentário da
resposta:
JUSTIFICATIVA
A notação pós-fixa (ou notação polonesa reversa) é uma técnica comum
para lidar com a ordem das operações em código intermediário, pois elimina
a necessidade de parênteses e permite uma avaliação direta da expressão.
Pergunta 3
3,34 em 3,34 pontos
Considere o seguinte trecho de código em uma linguagem de programação de alto nível:
x = 10
y = 20
z = x + y
Suponha que estamos gerando código intermediário para essa parte do programa. Qual das
seguintes opções representa corretamente o código intermediário para a operação de adição?
Respostas: a.
z = x + y
b.
ADD z, x, y
c.
LOAD x, R1
LOAD y, R2
ADD R1, R2, R3
STORE R3, z
d.
ADD x, y, z
e.
z = ADD(x, y)
Comentário da
resposta:
JUSTIFICATIVA
Em código intermediário, a operação de adição é frequentemente
representada por uma instrução que especifica os operandos e o destino da
operação, como ADD z, x, y.
Pergunta 1
3,34 em 3,34 pontos
Você está trabalhando em um compilador e deseja aplicar a otimização “Reordenação de
Instruções” para melhorar o desempenho de um código intermediário. Qual é o principal
objetivo dessa otimização e como você aplicaria a técnica a ao código intermediário abaixo?
1. a = 5
2. b = a * 2
3. c = 3 + b
4. d = a – 1
Respostas: a.
O objetivo é reduzir a quantidade de código gerado, eliminando instruções
desnecessárias, e a técnica pode ser aplicada removendo a instrução 4.
b.
O objetivo é melhorar a legibilidade do código intermediário, e a técnica pode ser
aplicada reorganizando as instruções na seguinte ordem: 4, 3, 2, 1.
c.
O objetivo é melhorar o desempenho do programa, reordenando as instruções de
forma a explorar paralelismo e minimizar saltos condicionais, e a técnica pode ser
aplicada mantendo a ordem atual das instruções.
d.
O objetivo é converter o código intermediário em código de máquina, e a técnica
pode ser aplicada removendo todas as variáveis.
e.
O objetivo é reduzir a complexidade das expressões no código intermediário, e a
técnica pode ser aplicada removendo a instrução 3.
Comentário
da resposta:
JUSTIFICATIVA
A otimização “Reordenação de Instruções” visa melhorar o desempenho do
programa reorganizando as instruções de forma a explorar paralelismo e
minimizar saltos condicionais. Nesse caso, manter a ordem atual das
instruções é a abordagem correta para aplicar essa técnica.
----
Pergunta 2
3,34 em 3,34 pontos
Considere o seguinte código:
1. x = 5
2. y = 3
3. z = x + y
4. w = z - 2
5. resultado = w * 4
Considere que um desenvolvedor deseja aplicar a técnica “Reordenação de Instruções" para
otimizar esse código intermediário. Qual seria a ordem das instruções após a otimização?
Respostas: a.
1, 2, 3, 4, 5
b.
2, 1, 3, 5, 4
c.
2, 1, 3, 4, 5
d.
1, 2, 4, 3, 5
e.
2, 1, 4, 3, 5
Comentário da
resposta:
JUSTIFICATIVA
A técnica “Reordenação de Instruções”, como o próprio nome indica, visa
reorganizar as instruções para melhorar o desempenho do programa. Nesse
caso, as instruções 2 e 1 são trocadas para que a ordem seja 2, 1, 3, 4 e 5,
otimizando o desempenho.
Pergunta 3
3,32 em 3,32 pontos
Ao lidar com o desenvolvimento de um compilador, o programador quer aplicar a otimização
“Eliminação de Código Morto” em um código intermediário. Qual é o principal objetivo dessa
otimização e como o programador aplicaria a técnica ao código intermediário abaixo?
1. x = 52. y = x + 3
3. z = 2 * y
4. w = z – 5
5. v = z * 2
Respostas: a.
O objetivo é melhorar a legibilidade do código intermediário e a técnica pode ser
aplicada removendo todas as instruções.
b.
O objetivo é reduzir a complexidade das expressões no código intermediário e a
técnica pode ser aplicada removendo todas as operações de adição e
multiplicação.
c.
O objetivo é reduzir a quantidade de código gerado, eliminando instruções que
não afetam o resultado do programa, e a técnica pode ser aplicada removendo as
instruções 3 e 5.
d.
O objetivo é converter o código intermediário em código de máquina, e a técnica
pode ser aplicada removendo todas as variáveis.
e.
O objetivo é identificar e remover variáveis temporárias desnecessárias, e a
técnica pode ser aplicada removendo as variáveis y e z.
Comentário da
resposta:
JUSTIFICATIVA
A otimização de “Eliminação de Código Morto” visa reduzir a quantidade de
código gerado, eliminando instruções que não afetam o resultado do
programa. Nesse caso, as instruções 3 e 5 não afetam o resultado do
programa.