Desenvolvimento - C/C++

Compiladores: Revisão dos Princípios, Técnicas e Ferramentas

O artigo tratará de um resumo abordando sobre o tema: Compiladores. Três exemplos de analisadores (léxico semântico e sintático) estão disponibilizados.

por Nilton Sango Guimarães



1. Resumo:

O Avanço da tecnologia e dos sistemas informatizados trouxe a toda comunidade de TI uma completa automação nos processos de desenvolvimento de softwares. Hoje, novas tecnologias estão sendo lançadas e o processo de programação e desenvolvimento de sistemas para computadores tornou-se bem mais ágeis. Contudo, se esquecemos que para o código fonte, desenvolvido pelos programadores, se tornar um código objeto, temos o integrador chamado de Compilador, que nada mais é que um programa que converte código fonte em código objeto. Foi pensando nisso, que esse artigo tratará de um resumo abordando sobre o tema: Compiladores. Estarei disponibilizando 3 exemplos de analisadores (léxico semântico e sintático).

2. Definições:

- Tradutor – São programas que convertem linguagem fonte em qualquer outra linguagem de máquina equivalente.

- Compilador – São tradutores que mapeiam instruções em linguagem de máquina, viabilizando seu tempo de execução. Possuem facilidade em manipulação, ágeis, corrigem erros, comentários, otimizam e geram códigos intermediários.

- Montador – Converte textos em mneumônios

- Interpretadores – interpretam trechos de comandos linha a linha, encontrando o ponto exato de um erro no programa. São mais demorados.

- Filtros, pré-processador, pré-compilador – São tradutores que efetuam conexões em alto nível.

- Macro Assembly – São tradutores que convertem linguagem simbólica em linguagem de maquina

3. Gerações de computadores:

- 1ª Geração – Linguagem simbólica – linguagens de baixo nível.

- 2ª Geração – Linguagem de máquina – linguagem de baixo nível.

- 3ª Geração – Linguagem orientada ao usuário – são as linguagens procedimentais: Pascall, C, Clipper.

- 4ª Geração – São as linguagens orientadas as aplicações: Databasic.

- 5ª Geração – São as linguagens orientadas a IA. Linguagens do conhecimento – Prolog.

4. Compiladores:

Gerador da TS – É uma estrutura de registros organizada por campos onde são armazenados os dados e informações de variáveis e constantes.

Tratador de erros – Ele verifica aonde se encontra o erro a ser tratado. O tratador de erros depende da análise empregada.

Analisador Léxico – O tratador de erros do analisador léxico não reconhece caracteres especiais. Quando ele encontra, ele remove o caractere especial, insere um novo caractere e altera o caractere errado pelo certo.

Analisador Sintático – o tratador de erros não para a execução, quando encontra um erro e trata o erro e continua a execução. O tratador de erros do analisador sintático ele trata os erros nas seguintes condições.

1. Método do Desespero – É o mais simples porque trata somente um erro por linha. Encontrando o erro, ele descarta o símbolo lido.

2. Recuperação de Frases – Faz se a correção local, encontrando o erro troca-o por um token voltando a ser executado o tratador de erros.

3. Produção de Erros – suponhamos que naquela frase exista o erro, tratamos.

4. Correção global – É uma técnica teórica, faz-se a correção global.

Analisador Semântico – Verifica o tipo de variáveis, se elas são compatíveis com a declaração de escopo, que estão declaradas na TS; verifica o escopo através de hierarquias empilhando os escopos e desempilhando os escopos, se ao final do programa a pilha resultar em NULL (programa ok). Organiza em arvores de derivação.

- Gerador de código intermediário – utiliza a representação interna do analisador léxico e fornece como saída uma seqüência de códigos. Suas vantagens: - facilidade na otimização do código; - útil na passagem para o código objeto. Desvantagem: é mais uma etapa na compilação do programa.

- Otimizador de Código – ele otimiza o código fazendo com que torne mais rápido com menor tamanho em menor tempo de execução. Ele deve preservar a semântica do programa e suas alterações devem conceder leveza e rapidez ao algoritmo.

- Suas aplicações são:

o Eliminação de repetições de subprogramas;

o Eliminação de código morto;

o Eliminação  de cópias desnecessárias; 

o Otimizador de laços e movimentação do código.

Trabalham com 2 gerações:

- Top down (descendente)

- Bottom up (redutiva)

1. Top down – a partir de um símbolo inicial vai se construindo a arvore até atingir suas falhas.

Método de tentativa e erro – é o mais simples e o primeiro; é ineficiente; o analisador verifica até encontrar o erro, encontrando trata e tenta de novo;

Analise preditiva LLK – Contam-se quantos K até o ponto em que se deseja chegar.

2. Bottom-up – a partir das folhas de ramificação faz se analise até chegar ao símbolo inicial. Vai reduzindo da direita para a esquerda. É o inverso da top-down.

5. Máquinas Abstratas

São máquinas teóricas que fornecem condições para a execução de um programa. Trabalham com linguagens em códigos de instruções teóricas.

6. Síntese do Programa Objeto

- Possuem 3 aspectos importantes para seus requisitos:

1 – O código gerado deve ser fácil e de alta qualidade;

2 – O programa deve executar efetivamente;

3 – Deve ter uso efetivo na CPU;

- Aspectos na representação do projeto do programa objeto:

1 – Forma do código objeto:

- Linguagem absoluta (armazenam variáveis em áreas fixas tornando o processo mais rápido, contudo, essas regiões podem ser bloqueadas);

-  Relocável (permite que o compilador execute subprogramas);

- Assembly (trabalham com instruções de máquina – 3 endereços).

2 – Alocação de registradores;

3 – Determinação do tipo de avaliação  - Permite a escolha da ordem  de execução de instruções no programa.

4 – Seleção de instruções de máquina – a escolha de conjuntos de instruções pode determinar numa agilidade e facilidade melhor.

7. Ambiente de Tempo de Execução

São as ações que precisam ocorrer em tempo de execução para implementar o programa.

Gerencia de Memória - Refere-se à alocação e a liberação de memória para variáveis e constantes em tempo de execução e compilação.

8. Estratégias de Alocação de Memória

Organização:                             código objeto

                                                         Área de dados estática

                                                         Pilha

                                                         HEAP

Heap – Área de dados  alocados controlada pelo programa;

Pilha – Armazena dados locais de procedimentos. Armazena o RA

A alocação de memória pode ser:

- Alocação Estática – se o tipo de variável é conhecido durante o tempo de execução e seu valor não é alterado no tempo de compilação, reserva-se memória de forma estática.

- Alocação em Pilha – são armazenado dinamicamente os dados locais de parâmetros e procedimentos.

- Alocação Dinâmica – para estruturas de dados referenciados por ponteiros. Estas áreas são alocadas e liberadas pelo HEAP.

8.1. Alocação de memória em Pilha

- Utiliza para os procedimentos – para cada chamada armazena os dados e informações de variáveis  num registro de ativação – RA. Em cada retorno desempilha um RA.

8.2. Passagem de Parâmetro

 A comunicação entre dados e procedimentos é feita através de variáveis globais ou de parâmetros.

Os principais métodos são:

- Por valor – os parâmetros são avaliados  e seus valores são passados para o procedimento chamado. Pode ser implementado como:

1 – um parâmetro formal é tratado como um nome local de maneira que sua memória é armazenada num RA.

2 – Os parâmetros reais são avaliados e armazenado  seus valores na memória reservada para os parâmetros formais.

- Por endereço – São passados os endereços de cada parâmetro real.

8.3. Alocação Dinâmica

São armazenados os dados locais de procedimentos e estados da CPU. São alocados no HEAP. A alocação pode ser: Explicita – o programador deve armazenar e liberar espaços de memória através de instruções de linguagens de máquina.

Implícita – o programador não se preocupa com alocação de variáveis, é declarado à variável e automaticamente reservado o seu espaço de memória; quando executado esta variável é automaticamente liberado seu espaço.

9. Geração de Código

- ASPECTOS importantes:

1 – Implicações de hardware – o compilador deve escolher o tipo adequado de conjuntos de instruções.

2 – Tratamento de variáveis – são acrescentados na TS informações adicionais sobre informações de uma determinada variável.

3 – Tratamentos de estruturas de programação – São incrementados 2 novas instruções:  - testar o valor da condição;  - verificar o salto, se ela está saindo de um determinado ponto e atingindo outro bloco de comando.                           

4 – Tratamento de Sub-rotinas – Retornam para a posição de onde ocorreu o desvio.

10. Bibliografia

AHO, A. V., LAM, M. S., SETHI, R.  Compiladores Princípios, Técnicas e Ferramentas. 2ª Ed. Pearson, 2007.

11. Anexos

Baixe os anexos, clicando aqui.

Nilton Sango Guimarães

Nilton Sango Guimarães - Analista de TI / Professor Universitário. Pós-Graduado em MBA em Tecnologias ERP, Graduado em Ciência da Computação. Atua no Levantamento das informações para Tomadas de Decisão e Administração de TI.