Possivelmente, é um dos compiladores mais famosos. Você já deve ter ouvido falar nele enquanto estudava Java, .NET ou até Python. É um método de compilação que converte o código dessas linguagens para um código de meio termo chamado bytecode. Nesse caso, o código não é entendido pela máquina em si e é preciso contar com uma máquina virtual para a execução desse código. Também pode ser conhecido como um interpretador.
Com isso, temos o programa rodando logo após o início da compilação e é comum que o código gerado anteriormente contribua para a compilação final. Como o código será compilado várias vezes, esse método não é muito bom em fazer otimizações, já que se perde muito tempo nesse processo.
Entenda como funcionam as fases do compilador!
Vamos agora destrinchar todos os passos de um compilador:
Vamos agora destrinchar todos os passos de um compilador:
Analisador Léxico
Nessa primeira fase, temos a separação dos textos em pequenos pedaços chamados de tokens léxicos. Isso é feito por meio de um analisador chamado scanner. Toda a leitura é feita caractere por caractere tendo como objetivo a separação e identificação de cada componente do programa.
Também é de responsabilidade dessa etapa a eliminação de espaços vazios, formatações e comentários do código. Existem alguns programas famosos que servem só para atuar na parte de análise léxica.
Analisador de Sintaxe
Logo após a análise léxica, é feita a verificação sintática das cadeias dos tokens para que seja confirmado se as regras e a estrutura seguem a gramática formal. Isso é, verifica-se se não existe nenhum erro na sintaxe do programa.
Também é conhecido como árvore de análise sintática ou apenas árvore sintática. Essa árvore é desenvolvida para definir a gramática da linguagem criada. Com isso, as regras são embutidas nesse processo e, se o programa não apresentar nenhum erro, é continuado o fluxo do compilador, se não, é apresentado uma mensagem de erro.
Analisador Semântico
Na análise semântica, temos a verificação de algumas outras regras, como o tipo de cada variável. Nesse passo é feita a validação da lógica do código da linguagem de programação em si, também é papel do analisador checar se todas as variáveis foram iniciadas.
Gerador de código intermediário
Tem o propósito de criar um código de objeto que ainda não foi concluído, porém, já é possível ser executado através de máquinas virtuais. Existem diversos tipos de códigos intermediários, sendo o mais famoso o código de três endereços. Também temos as triplas e quadruplas para representar esse nível de código.
Temos uma lista de linguagens que podem ser consideradas como código intermediário, já que são rodadas em máquinas virtuais:
- Java – Bytecode;
- TIMI – Usado em compiladores da plataforma IBM i;
- Matlab;
- O-code – Feito pelo BCPL (Linguagem de Programação Básica Combinada).
Otimizador de código
Nessa etapa, temos a examinação do código intermediário com o propósito de otimizá-lo, utilizando várias técnicas. Mesmo o mais moderno dos compiladores não consegue otimizar totalmente o código. Isso porque não é possível agradar todos os diferentes casos de design. Mesmo assim, essa parte é fundamental para a geração do código binário.
Entre as técnicas de substituição de códigos padrões, temos a eliminação de subexpressões excessivas, substituição das operações matemáticas e a repartição de laços, já que eles são estruturas que cabem uma certa otimização.
Gerador de código final
A última fase do compilador, sem nenhum segredo, é feita a geração do código para que a máquina consiga executá-lo. É uma das partes mais importantes na hora de se programar, pois, dependendo da forma que é programada pode durar até o dobro do tempo de um código ineficiente.
Nessa fase temos algumas etapas que o gerador deve passar:
- seleção da instrução – É feita a definição de cada instrução do nível da máquina para cada lógica do programa,
- ordem da instrução – Em que ordem colocar as instruções para a execução. É um dos principais pontos de otimização;
- alocação do registro – Etapa onde é feita a alocação das variáveis no registrador do processador;
- data depurada – Opcional, porém se necessário é gerado o código para a depuração.
Quais as ferramentas de construção dos compiladores?
Existem diversos tipos de ferramentas nos compiladores, todos introduzidos em tecnologias relacionadas ao computador. Esses instrumentos são criados a partir de uma linguagem específica ou feitos a partir de um algoritmo e acabam implementando algum componente do compilador.
Abaixo temos alguns exemplos:
Scanner generators
Serve para gerar analisadores léxicos a partir da entrada de dados, que são as descrições de várias expressões regulares baseadas nos tokens da linguagem. Em resumo, ele gera um autômato finito para reconhecer a expressão regular. Um exemplo disso é o programa Lex.
Mecanismos de tradução de sintaxe
É uma ferramenta para gerar códigos intermediários com três formatos de endereço na sua entrada, que contém uma árvore de análise. Esses mecanismos têm rotinas que percorrem a árvore e, em seguida, produzem o código intermediário. Sendo nesse caso, cada nó é associado a uma ou mais traduções.
Geradores de analisador
Ele produz analisadores de sintaxe (parsers) a partir da entrada que é baseada em uma descrição gramatical de linguagem de programação, até mesmo uma gramática livre de contexto. É muito útil, pois a fase de análise de sintaxe é muito complexa e consomem mais tempo manual e de compilação. Alguns desses programas são o PIC e o EQM.
Geradores de código automáticos
O código de máquina é gerado a partir de uma linguagem intermediária, sendo que cada operação deve obedecer a um conjunto de regras e, se não ocorrer erros, é gerado o código final. Nesse processo se utiliza uma comparação de templates entre as linguagens para que ocorra a substituição das instruções do código intermediário para o código de máquina.
Mecanismos de fluxo de dados
Usado na otimização do código. Aqui, as informações são coletadas a partir do usuário e do código intermediário. Logo após, é feita a análise do fluxo de dados para que seja mostrado como os valores são transmitidos de um lugar do código para outro.
Quais as diferenças entre compilador e interpretador ?

Um compilador é um programa que traduz o código escrito em uma linguagem de alto nível para código de máquina. Em resumo, traduz o código legível para os seres humanos e converte para a linguagem binária que o processador entende. Além disso, o compilador deve obedecer as regras de sintaxe da linguagem, no caso, se ocorrer algum erro você deve corrigi-los.
Alguns exemplos de linguagens que utilizam compiladores:
O interpretador também é um programa, porém, ele não tem o processo de traduzir todo o programa em um arquivo para conseguir rodar, e sim, ele inclui cada instrução da sua linguagem de alto nível no código de máquina. Com isso, o papel de tradução é feito de uma maneira muito mais dinâmica e que consegue incluir alguns tipos de código, tais como, scripts, códigos pré-compilados e o próprio código fonte.
Alguns exemplos de linguagens que utilizam interpretadores:
- PHP;
- JavaScript;
- Lisp;
- Matlab;
- Perl.
Vantagens e desvantagens dos compiladores
Vantagens dos compiladores:
- o código já é traduzido para a linguagem de máquina, com isso, se obtém um tempo menor de execução;
- a confiabilidade do código final, já que os processos do compilador são bem severos e conseguem validar e otimizar muito bem o código.
Desvantagens dos compiladores:
- você não pode mudar o código sem ter que recompilar todo o programa;
- mesmo com diversas otimizações, o compilador acaba sofrendo com o seu tempo de finalização do código;
- outro problema que podemos ter é no suporte de várias versões de um programa que é gerado a partir do mesmo compilador.
Vantagens e desvantagens dos interpretadores
Vantagens dos interpretadores:
- são fáceis de usar, especialmente para iniciantes;
- a execução é linha por linha, sendo assim fica mais fácil de encontrar o erro;
- nenhum código intermediário, por tanto, utiliza a memória de maneira mais inteligente.
Desvantagens dos interpretadores:
- o tempo de execução é muito grande, devido a forma de que se é traduzido;
- para ser executado deve-se ter um programa correspondente ao interpretador;
- menos seguro.
Qual usar, afinal? Compilador ou interpretador?
Para responder essa pergunta você deve entender qual o problema que a sua linguagem tenta resolver, já que, em alguns casos, faz sentido o programa ser compilado e em outros, interpretado.
Podemos pegar o exemplo do JavaScript, que é uma linguagem mais utilizada com interpretadores. Podemos então pensar que isso acontece porque os sites precisam carregar os seus conteúdos de uma maneira simples e prática por meio de pequenos ou até grandes scripts. Se algum erro for cometido no meio tempo, o programa acaba não se importando muito e continua a executar as outras tarefas.
Já em programas que não precisam ser carregados de diversas formas ou formatos, é mais prático a utilização de um compilador, um exemplo é a linguagem C++. Nela podemos escrever um programa com o objetivo de apenas resolver a tarefa que nos foi dada. Sendo assim, conseguimos gerar um código mais compacto e com poucas alternativas de execução, consequentemente, a segurança e a otimização do código compilado é superiormente mais eficiente do que o interpretado.
Compiladores e interpretadores podem ser usados juntos?
A resposta é bem simples: Podem! E uma das linguagens mais famosas que faz uso dessa estratégia é o Java. Por utilizar a compilação no seu processo de desenvolvimento e na fase do código intermediário que é gerado o bytecode, a JVM (Máquina virtual do Java) interpreta o código.
Simplificando, o bytecode é o código de máquina da máquina virtual do Java e, com isso, ela consegue algumas vantagens dos dois mundos, sendo a principal delas a portabilidade de código, já que só é necessário uma JVM em cada computador para que ocorra a execução do código.
E os Scripts, podem ser compilados?
Resumidamente, sim. No entanto, deve-se ver a necessidade do seu projeto para que faça sentido ele ser compilado. Atualmente, tanto linguagens como o JavaScript, PHP e Python podem ser compiladas com o auxílio de programas, tais como o Brython, PyDev, Kite, Komodo e WebStorm.
Porém, em alguns casos não é possível utilizar códigos compilados. Em scripts web, a execução do código é feita a partir de um interpretador do navegador e, com isso, infelizmente não pode ser diferente (pelo menos atualmente). Em outros casos também não é possível executar um script web diretamente da área de trabalho.
Quais os 4 compiladores mais usados?
Borland Turbo C
Turbo C é um dos mais básicos e populares compiladores para a linguagem C. Foi introduzido em 1987. Foi muito famoso pelo seu pequeno tamanho, velocidade de compilação e baixo preço. Quando o Turbo C++ foi lançado, em 1990, ambos os compiladores foram unidos e o nome Turbo C foi descontinuado. Em 2006, ele foi relançado como um software de graça.
Tiny C Compiler
Esse compilador foi desenhado para funcionar em computadores lentos com pouco espaço e também é um compilador da linguagem C. Foi em 2005, com suporte para o Windows e algumas das suas vantagens estão listadas abaixo:
- o tamanho do arquivo é muito pequeno e de acordo com o seu criador (Fabrice Bellard) ele roda 9 vezes mais rápido que o GCC;
- inclui ferramentas que possibilitam o aumento opcional das memórias, verificador de limites e uma melhora na estabilidade do código;
- permite também a execução automática de programas durante o tempo de compilação usando apenas argumentos na linha de comando. Dessa forma, os programas são executados no UNIX, usando scripts do shell.
Portable C Compiler (PCC)
Esse outro compilador foi estabelecido muito cedo como o compilador do C em meados de 1970. Teve uma longa vida útil e foi muito famoso na época que a maioria dos compiladores eram baseados nele.
As principais vantagens do PCC dependiam da sua capacidade e previsão de probabilidade. Além disso, foi feito de uma forma que os arquivos de origem dependessem da máquina, mas nem todos, apenas alguns. Também consegue detectar erros de sintaxe e realizar validações perfeitas. A última versão lançada até o momento dessa postagem é do dia 10 de dezembro de 2014.
GCC
GNU Compiler Collection é o compilador criado pelo projeto GNU que suporta várias linguagens de programação e tem como principal objetivo ser totalmente gratuito e de código aberto. Foi lançado em 1987 com o suporte de apenas a linguagem C. Logo depois foi se expandindo lentamente para C++, Java, Android e IOS. Aqui, cada compilador de cada linguagem tem a sua própria lógica e processo para a geração dos programas.
Algumas das vantagens do GCC são:
- consegue eliminar pedaços de código morto;
- consegue remover redundâncias de código;
- melhora a otimização de Arrays.
Vimos que o compilador exerce um grande papel na vida dos desenvolvedores e que também ocorre um grande trabalho e esforço para que os códigos possam ser executados de uma maneira segura e otimizada. Sem o compilador, precisaríamos escrever o código todo em linguagem de máquina Assembly e isso causaria uma série de problemas na estrutura e padronização dos códigos.
Por isso, existem várias linguagens e vários tipos de linguagens, algumas até não utilizam o compilador e sim o interpretador, como no caso de sites que acessamos pelo navegador. Em outros casos podemos também compilar um código interpretado. Em suma, percebemos que o compilador e o interpretador exercem um grande papel no fluxo de desenvolvimento de novas aplicações e que é interessante entender o funcionamento dessas etapas.