Baixe o app para aproveitar ainda mais
Prévia do material em texto
Geração de código intermediário - Compiladores Exercícios 1. Os compiladores são organizados em uma sequência de fases. À medida que o compilador deriva conhecimento sobre o código que compila, precisa transmitir essa informação de uma fase para outra. Ele necessita, então, de uma representação para todas as informações que deriva sobre o programa-fonte. Chama-se isso de representação intermediária (IR). Sobre as IRs geradas por um compilador, considere as seguintes afirmações: I — A árvore sintática é a forma de representação intermediária mais próxima da estrutura do código-alvo. II — A árvore sintática abstrata é uma representação contendo mais informações sobre as produções gramaticais realizadas, se comparada com a árvore sintática comum. III — Um dos motivos de se utilizar o código de três endereços como representação intermediária é a sua facilidade de tradução para linguagens de máquina. Assinale a alternativa que indica as afirmações corretas: Você acertou! C. Apenas a afirmação III está correta. Sobre as afirmações feitas, apenas a afirmação III é correta. O código de três endereços é muito parecido com os tipos de operação em linguagem Assembly, o que o torna uma boa forma de código intermediário. Assim, um dos motivos de se utilizar o código de três endereços como IR é a sua facilidade de tradução para linguagens de máquina. A afirmação I é incorreta, pois uma árvore sintática é uma representação do código-fonte, e não do código-alvo. A afirmação II também está incorreta, pois é justamente o contrário: a árvore sintática comum tem mais nós relativos aos símbolos das produções gramaticais do que a árvore sintática abstrata, que representa apenas os símbolos terminais usados nas produções. 2. A função de um compilador é traduzir programas escritos em uma linguagem- fonte em um dos programas equivalentes em outra linguagem-alvo. Para isso, o compilador é dividido em fases, que implementam diversas técnicas. A ___________________ é uma técnica de tradução aplicada em compiladores que consiste em inserir regras de tradução nas produções gramaticais da linguagem- fonte, de modo que o percurso na árvore sintática executa a tradução desejada. Qual das alternativas a seguir preenche melhor a lacuna na afirmação? Você acertou! D. Tradução dirigida pela sintaxe. A frase correta é: A tradução dirigida pela sintaxe é uma técnica de tradução aplicada em compiladores que consiste em inserir regras de tradução nas produções gramaticais da linguagem-fonte, de modo que o percurso na árvore sintática executa a tradução desejada. A análise léxica consiste em identificar tokens da linguagem-fonte do texto do programa-fonte. Os tokens reconhecidos são usados na análise sintática para validar essa sequência com a gramática da linguagem-fonte. Entretanto, nenhuma tradução é feita. A otimização de código consiste em tornar o código-alvo mais eficiente, mas isso independe da linguagem-fonte. A interpretação de código consiste em executar instruções na máquina-alvo a partir da análise das instruções do código-fonte. 3. Compiladores podem gerar uma variedade de representações intermediárias para representar as construções sintáticas da linguagem-fonte. Cada representação tem a finalidade de registrar informações de uma fase da compilação para as fases seguintes. ___________________ é uma representação intermediária que consiste em representar as produções gramaticais de forma mais sucinta, de modo que apenas os símbolos terminais das produções gramaticais compõem suas construções. Qual das opções a seguir completa apropriadamente a lacuna da afirmação? Você acertou! B. Árvore sintática abstrata. A árvore sintática abstrata é uma representação intermediária que consiste em representar as produções gramaticais de forma mais sucinta, de modo que apenas os símbolos terminais das produções gramaticais compõem suas construções. Ela é uma versão resumida da árvore sintática. A árvore sintática também representa símbolos não terminais em suas construções. A árvore sintática anotada consiste em uma árvore sintática contendo em suas ramificações regras de tradução, além de terminais e não terminais. Um grafo de dependências é um grafo que modela o fluxo de valores desde suas definições até seus usos em um fragmento de código. O código de três endereços é uma representação de código intermediário já voltada para geração de linguagem-alvo. 4. Na notação tradicional para as expressões aritméticas (notação infixa), o operador aparece entre os seus dois operandos. Já na notação pós-fixa, também conhecida como notação polonesa inversa, o operador é colocado após os seus dois operandos. Considere o esquema de tradução de expressões para a forma pós-fixa para a gramática a seguir: EXPR → EXPR + TERMO { imprimir (“+”) } EXPR → EXPR – TERMO { imprimir (“-”) } EXPR → TERMO TERMO → TERMO * FATOR {imprimir (“*”) } TERMO → TERMO / FATOR {imprimir (“/”) } TERMO → FATOR FATOR → ( EXPR ) FATOR → 0 { imprimir (“0”) } ... ... FATOR → 9 { imprimir (“9”) } Qual será o resultado da sua execução para a entrada 2 + 4 * (5 - 3)? Você acertou! D. 2 4 5 3 - * +. A árvore sintática anotada para a entrada 2 + 4 * (5 - 3), usando a gramática proposta, é mostrada na figura abaixo: Ao se percorrer a árvore sintática contendo as regras de tradução no percurso em profundidade, a expressão pós-fixa será gerada após a execução das regras de tradução da gramática, na seguinte ordem: 1. { imprimir (“2”) } 2. { imprimir (“4”) } 3. { imprimir (“5”) } 4. { imprimir (“3”) } 5. { imprimir (“-”) } 6. { imprimir (“*”) } 7. { imprimir (“+”) } O que torna incorretas as saídas: • 2 4 + 5 * 3 - • 2 4 5 3 + * - • + 2 4 * - 5 3 • 2 4 3 5 - * + Isso porque elas não poderiam ser geradas pela execução das regras de tradução na ordem de avaliação da árvore sintática. Nesse caso, a única saída correta seria 2 4 5 3 - * +. 5. As fases de um compilador podem ser classificadas em dois grupos: análise e síntese. Na fase de análise, encontram-se as fases de análise léxica, análise sintática e análise semântica. Já na fase de síntese, encontram-se as fases de geração de código intermediário, otimização e geração de código. Sobre a fase de geração de código intermediário de um compilador, assinale a alternativa correta: Você acertou! C. A fase de geração de código intermediário de um compilador é a fase em que ocorre a transformação da árvore sintática em uma linguagem intermediária, que é mais próxima da linguagem-objeto do que o código-fonte, mas ainda não se trata do código-final. Análise léxica é a fase em que se reconhecem os tokens da linguagem-fonte por meio da leitura dos caracteres do código-fonte. Análise sintática é a fase em que se constrói uma árvore sintática para validar a estrutura dos tokens reconhecidos do código-fonte. Geração de código intermediário é a fase em que ocorre a transformação da árvore sintática em uma linguagem intermediária, que é mais próxima da linguagem-objeto do que o código-fonte, mas ainda não se trata do código final. Otimização de código é a fase em que se procura produzir um código que execute com mais eficiência. Geração de código final é a fase em que se gera o código para ser executado diretamente na máquina-alvo. Geração de código intermediário - Compiladores Exercícios
Compartilhar