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ães1. 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