Geral

Compiladores

Semana 1 2

#1

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.

A

Apenas I, II e III estão corretas.

B

Apenas II e IV estão corretas.

C

Apenas I e II estão corretas.

D

Apenas I e III estão corretas.

E

Apenas II e III estão corretas.

#2

Considere as alternativas a seguir e escolha apenas aquela que define o que é um "analisador léxico" em um compilador.

A

Um componente que otimiza o código-fonte para melhor desempenho.

B

Um componente que verifica se as variáveis no código-fonte estão declaradas.

C

Um componente que verifica a sintaxe do código-fonte.

D

Um componente que remove comentários e espaços em branco do código-fonte.

E

Um componente que gera o código executável a partir do código-fonte.

Semana 2 2

#1

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"? 

A

Identificador. 

B

Tipo de dado.

C

Delimitador.

D

Número.

E

Operador de atribuição.

#2

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 é otoken gerado pelo analisador léxico para o operador "else"? 

A

Palavra-chave

B

Identificador.

C

Operador aritmético.

D

Delimitador.

E

Operador relacional.

Semana 3 2

#1

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? 

A

<stmt> ::= if (<expr>) { <stmt> }

B

<expr> ::= if (<stmt>) { <stmt> }

C

<stmt> ::= if { <stmt> } else { <stmt> }

D

<expr> ::= if (<stmt>)

E

<stmt> ::= if (<expr>) { <stmt> } else { <stmt> }

#2

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? 

A

2 * (3 + 4)

B

(2 * (3 + 4))

C

2 * (3 + 4))

D

2 * (3 + 4

E

2 * 3 + 4

Semana 4 5

#1

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? 

A

Deslocar o operador *.

B

Reduzir a produção F -> id.

C

Entrar em um estado de erro.

D

Reduzir a produção E -> T.

E

Reduzir a produção T -> F.

#2

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? 

A

Procurar por um token de lookaheadcorrespondente a uma instrução dentro do bloco then.

B

Realizar uma redução da produção if_stmt para stmt.

C

Realizar uma redução da produção stmt para else_stmt.

D

Realizar uma redução da produção stmt para if_stmt.

E

Procurar por um tokende lookaheadcorrespondente a else.

#3

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)? 

A

A análise LL(1) não permite recursão à esquerda na gramática.

B

A análise LL(1) funciona apenas para gramáticas ambíguas.

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) é baseada em lookahead, olhando apenas um símbolo à frente.

E

A análise LL(1) é sempre mais eficiente do que a análise LR(1). 

#4

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? 

A

O analisador entra em um estado de aceitação e conclui a análise.

B

O analisador entra em um estado de erro e para a análise.

C

O analisador escolhe aleatoriamente uma das produções em conflito.

D

O analisador consulta a tabela de precedência de operadores para resolver o conflito.

E

O analisador utiliza uma regra de desempate baseada na ordem de aparição das produções na gramática.

#5

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;? 

A

Realizar uma redução da produção declaration para stmt.

B

Realizar uma redução da produção stmt para declaration.

C

Procurar por um tokende lookaheadcorrespondente ao símbolo x.

D

Realizar uma redução da produção stmt para expression_stmt.

E

Procurar por um token de lookaheadcorrespondente a uma instrução dentro do bloco main(). 

Semana 5 5

#1

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: 

A

F, F, V, V, V.

B

F, V, F, F, V.

C

V, V, F, V, V.

D

V, V, V, V, F.

E

V, V, F, V, F.

#2

Analise as alternativas a seguir e assinale qual delas indica a principal função da análise semântica em um compilador: 

A

Verificar a corretude léxica dos tokens na entrada.

B

Otimizar o código-objeto gerado pelo compilador.

C

Detectar e reportar erros de semântica no código-fonte.

D

Garantir que a sintaxe da linguagem seja interpretada corretamente.

E

Verificar a gramática da linguagem de programação.

#3

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: 

A

F, V, V, V, F.

B

F, V, V, F, V.

C

V, V, F, F, V.

D

V, F, V, F, V.

E

V, F, V, V, F.

#4

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? 

A

Certificar-se de que todas as variáveis sejam declaradas antes de serem usadas.

B

Garantir que todas as variáveis tenham nomes exclusivos.

C

Garantir que os operadores sejam aplicados a operandos compatíveis em termos de tipo.

D

Verificar se a gramática da linguagem está correta.

E

Verificar se todas as instruções do programa estão corretamente identadas.

#5

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ímbolos bem implementada deve garantir que não haja conflitos de nome entre diferentes identificadores. 

Assinale a alternativa com a ordem correta: 

 

A

V, V, V, V, F

B

F, V, V, V, V 

C

V, V, F, V, F

D

F, F, V, F, V

E

V, V, F, V, V 

Semana 6 2

#1

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? 

A

ADD x, y, z

B

z = ADD(x, y)

C

LOAD x, R1
LOAD y, R2 
ADD R1, R2, R3
STORE R3, z 

D

z = x + y

E

ADD z, x, y

#2

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? 

A

Usar notação pré-fixa (ou notação polonesa).

B

Resolver as operações em ordem inversa.

C

Resolver as operações em ordem alfabética.

D

Usar apenas uma pilha de operadores.

E

Usar notação pós-fixa (ou notação polonesa reversa).

Semana 7 2

#1

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? 

A

1, 2, 3, 4, 5

B

1, 2, 4, 3, 5

C

2, 1, 3, 5, 4

D

2, 1, 3, 4, 5

E

2, 1, 4, 3, 5

#2

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 = 5
 2.  y = x + 3
 3.  z = 2 * y
 4.  w = z - 5
 5.  v = z * 2 

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 é converter o código intermediário em código de máquina, e a técnica pode ser aplicada removendo todas as variáveis. 

D

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. 

E

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.