Um compilador é um programa que traduz um programa escrito em uma linguagem-fonte para um programa equivalente em uma linguagem-alvo, tipicamente uma linguagem de máquina. O processo de compilação pode ser dividido em duas partes principais: Análise e Síntese.
A parte de Análise quebra o programa fonte em pedaços e constrói uma representação intermediária. A parte de Síntese constrói o programa alvo a partir dessa representação intermediária.
A arquitetura de um compilador é tradicionalmente organizada em uma série de fases. Enquanto algumas dessas fases podem ser agrupadas para serem executadas em uma única passagem (ou front-end e back-end), a representação conceitual mais usual de um compilador é a sua estrutura baseada em fases, conforme ilustrado na figura 1.
As principais fases e componentes de um compilador são:
1. Análise Léxica (ou Scanner): A primeira fase, que lê o fluxo de caracteres do programa fonte e os agrupa em sequências com significado coletivo, chamadas tokens. Os espaços em branco e comentários são tipicamente eliminados nesta fase.
2. Análise Sintática (ou Parser): Recebe o fluxo de tokens do analisador léxico e constrói uma representação intermediária hierárquica do programa, como uma árvore sintática. Esta fase verifica se os componentes do programa fonte se agrupam corretamente.
3. Análise Semântica: Nesta fase, o compilador tenta verificar se os componentes do programa se encaixam de maneira significativa. Por exemplo, a verificação de tipos é uma tarefa importante realizada aqui, garantindo que os operadores tenham operandos compatíveis.
4. Gerador de Código Intermediário: Produz uma representação intermediária do programa fonte. Esta representação deve ter duas propriedades importantes: ser fácil de produzir e ser fácil de traduzir para o programa alvo.
5. Otimização de Código: Uma fase opcional, mas frequentemente essencial em computadores modernos. Ela tenta melhorar o código intermediário para produzir um código alvo que utilize os recursos da máquina de forma mais eficiente.
6. Gerador de Código: A fase final, que recebe a representação intermediária (otimizada ou não) e mapeia-a para instruções do código alvo.
Além dessas fases, o compilador possui dois componentes que interagem com todas as fases:
• Gerenciamento da Tabela de Símbolos: Registra e coleta informações sobre os identificadores utilizados no programa fonte, como seus nomes e tipos. Ele fornece informações para as fases de análise e as utilizações de identificadores são registradas na tabela.
• Detecção de Erros e Geração de Relatórios: Cada fase pode detectar erros. Os erros detectados nas fases anteriores podem impedir que as fases posteriores realizem análises significativas.
O compilador, em conjunto com outros programas, faz parte de um sistema de processamento de linguagem, que pode incluir também o pré-processador, o montador (assembler) e o carregador (loader), para produzir o código de máquina absoluto.
Nosso curso lidará com as três primeira partes, também conhecidas como a fase de Pré-Processamento.