Quais são as fases do projeto do compilador?
O compilador opera em várias fases, cada fase transforma o programa de origem de uma representação para outra. Cada fase recebe entradas de seu estágio anterior e alimenta sua saída para a próxima fase do compilador.
Existem 6 fases em um compilador. Cada uma dessas fases ajuda a converter a linguagem de alto nível em código de máquina. As fases de um compilador são:
- Análise lexical
- Análise de sintaxe
- Análise semântica
- Gerador de código intermediário
- Otimizador de código
- Gerador de código
Todas essas fases convertem o código-fonte dividindo-o em tokens, criando árvores de análise e otimizando o código-fonte em diferentes fases.
Neste tutorial, você aprenderá:
- Quais são as fases do projeto do compilador?
- Fase 1: Análise Lexical
- Fase 2: Análise de sintaxe
- Fase 3: Análise Semântica
- Fase 4: Geração de código intermediário
- Fase 5: Otimização de Código
- Fase 6: Geração de Código
- Gestão da Tabela de Símbolos
- Rotina de tratamento de erros:
Fase 1: Análise Lexical
A análise lexical é a primeira fase quando o compilador verifica o código-fonte. Esse processo pode ser da esquerda para a direita, caractere por caractere, e agrupar esses caracteres em fichas.
Aqui, o fluxo de caracteres do programa de origem é agrupado em sequências significativas, identificando os tokens. Ele faz a entrada dos tickets correspondentes na tabela de símbolos e passa esse token para a próxima fase.
As funções principais desta fase são:
- Identifique as unidades lexicais em um código-fonte
- Classifique as unidades lexicais em classes como constantes, palavras reservadas e insira-as em tabelas diferentes. Irá ignorar comentários no programa fonte
- Identifique o token que não faz parte da linguagem
Exemplo :
x = y + 10
Tokens
X | identificador |
= | Operador de atribuição |
Y | identificador |
+ | Operador de adição |
10 | Número |
Fase 2: Análise de sintaxe
A análise de sintaxe trata de descobrir a estrutura do código. Ele determina se um texto segue ou não o formato esperado. O objetivo principal desta fase é ter certeza de que o código-fonte escrito pelo programador está correto ou não.
A análise de sintaxe é baseada nas regras baseadas na linguagem de programação específica, construindo a árvore de análise com a ajuda de tokens. Também determina a estrutura do idioma de origem e gramática ou sintaxe do idioma.
Aqui está uma lista das tarefas realizadas nesta fase:
- Obtenha tokens do analisador léxico
- Verifica se a expressão está sintaticamente correta ou não
- Reportar todos os erros de sintaxe
- Construir uma estrutura hierárquica conhecida como árvore de análise
Exemplo
Qualquer identificador / número é uma expressão
Se x é um identificador ey + 10 é uma expressão, então x = y + 10 é uma declaração.
Considere a árvore de análise para o seguinte exemplo
(a+b)*c
Na árvore de análise
- Nó interior: registro com um operador arquivado e dois arquivos para crianças
- Folha: registros com 2 / mais campos; um para token e outras informações sobre o token
- Certifique-se de que os componentes do programa se encaixam de forma significativa
- Reúne informações de tipo e verifica a compatibilidade de tipo
- Operandos de verificação são permitidos pelo idioma de origem
Fase 3: Análise Semântica
A análise semântica verifica a consistência semântica do código. Ele usa a árvore de sintaxe da fase anterior junto com a tabela de símbolos para verificar se o código-fonte fornecido é semanticamente consistente. Ele também verifica se o código está transmitindo um significado apropriado.
O Semantic Analyzer verificará se há incompatibilidades de tipo, operandos incompatíveis, uma função chamada com argumentos impróprios, uma variável não declarada, etc.
As funções da fase de análise semântica são:
- Ajuda a armazenar informações de tipo coletadas e salvá-las na tabela de símbolos ou árvore de sintaxe
- Permite que você execute verificação de tipo
- No caso de incompatibilidade de tipo, onde não há regras de correção de tipo exatas que satisfaçam a operação desejada, um erro semântico é mostrado
- Coleta informações de tipo e verifica a compatibilidade de tipo
- Verifica se o idioma de origem permite os operandos ou não
Exemplo
float x = 20.2;float y = x*30;
No código acima, o analisador semântico irá typecast o inteiro 30 para flutuar 30,0 antes da multiplicação
Fase 4: Geração de código intermediário
Depois que a fase de análise semântica termina, o compilador gera um código intermediário para a máquina de destino. Ele representa um programa para alguma máquina abstrata.
O código intermediário está entre a linguagem de alto nível e a linguagem de nível de máquina. Esse código intermediário precisa ser gerado de maneira que seja fácil traduzi-lo no código da máquina de destino.
Funções na geração de código intermediário:
- Deve ser gerado a partir da representação semântica do programa fonte
- Contém os valores calculados durante o processo de tradução
- Ajuda a traduzir o código intermediário para o idioma de destino
- Permite que você mantenha a ordem de precedência do idioma de origem
- Ele contém o número correto de operandos da instrução
Exemplo
Por exemplo,
total = count + rate * 5
O código intermediário com a ajuda do método do código de endereço é:
t1 := int_to_float(5)t2 := rate * t1t3 := count + t2total := t3
Fase 5: Otimização de Código
A próxima fase é a otimização do código ou código intermediário. Esta fase remove a linha de código desnecessária e organiza a sequência de instruções para acelerar a execução do programa sem desperdiçar recursos. O objetivo principal desta fase é aprimorar o código intermediário para gerar um código que rode mais rápido e ocupe menos espaço.
As funções principais desta fase são:
- Ajuda a estabelecer uma compensação entre a velocidade de execução e compilação
- Melhora o tempo de execução do programa alvo
- Gera código simplificado ainda em representação intermediária
- Remover código inacessível e livrar-se de variáveis não utilizadas
- Removendo declarações que não foram alteradas do loop
Exemplo:
Considere o seguinte código
a = intofloat(10)b = c * ad = e + bf = d
Pode se tornar
b =c * 10.0f = e+b
Fase 6: Geração de Código
A geração de código é a última e última fase de um compilador. Ele obtém entradas das fases de otimização do código e produz o código da página ou o código do objeto como resultado. O objetivo desta fase é alocar armazenamento e gerar código de máquina realocável.
Ele também aloca locais de memória para a variável. As instruções no código intermediário são convertidas em instruções de máquina. Esta fase cobre o código de otimização ou intermediário no idioma de destino.
O idioma de destino é o código de máquina. Portanto, todos os locais de memória e registros também são selecionados e alocados durante esta fase. O código gerado por esta fase é executado para obter entradas e gerar saídas esperadas.
Exemplo:
a = b + 60,0
Possivelmente seria traduzido para registradores.
MOVF a, R1MULF #60.0, R2ADDF R1, R2
Gestão da Tabela de Símbolos
Uma tabela de símbolos contém um registro para cada identificador com campos para os atributos do identificador. Este componente torna mais fácil para o compilador pesquisar o registro do identificador e recuperá-lo rapidamente. A tabela de símbolos também ajuda no gerenciamento do escopo. A tabela de símbolos e o manipulador de erros interagem com todas as fases e atualização da tabela de símbolos de forma correspondente.
Rotina de tratamento de erros:
No processo de design do compilador, o erro pode ocorrer em todas as fases fornecidas abaixo:
- Analisador léxico: tokens escritos incorretamente
- Analisador de sintaxe: parêntese ausente
- Gerador de código intermediário: operandos incompatíveis para um operador
- Otimizador de código: quando a instrução não está acessível
- Gerador de código: declarações inacessíveis
- Tabelas de símbolos: Erro de vários identificadores declarados
Os erros mais comuns são sequência de caracteres inválida na varredura, sequências de token inválidas no tipo, erro de escopo e análise na análise semântica.
O erro pode ser encontrado em qualquer uma das fases acima. Depois de encontrar os erros, a fase precisa lidar com os erros para continuar com o processo de compilação. Esses erros precisam ser relatados ao manipulador de erros que trata do erro para realizar o processo de compilação. Geralmente, os erros são relatados na forma de mensagem.
Resumo
- O compilador opera em várias fases, cada fase transforma o programa fonte de uma representação para outra
- Seis fases do projeto do compilador são 1) Análise lexical 2) Análise de sintaxe 3) Análise semântica 4) Gerador de código intermediário 5) Otimizador de código 6) Gerador de código
- A análise lexical é a primeira fase quando o compilador verifica o código-fonte
- A análise de sintaxe trata de descobrir a estrutura do texto
- A análise semântica verifica a consistência semântica do código
- Depois que a fase de análise semântica terminar o compilador, gere o código intermediário para a máquina de destino
- A fase de otimização de código remove a linha de código desnecessária e organiza a sequência de instruções
- A fase de geração de código obtém entradas da fase de otimização de código e produz o código da página ou código do objeto como resultado
- Uma tabela de símbolos contém um registro para cada identificador com campos para os atributos do identificador
- A rotina de tratamento de erros lida com erros e relatórios durante muitas fases