Síntese: Geração de código
Last updated
Last updated
Podemos definir o objectivo de um compilador como sendo traduzir o código fonte de uma linguagem para outra linguagem.
A geração do código para a linguagem destino pode ser feita por diferentes fases (podendo incluir fases de optimização), mas nós iremos abordar apenas uma única fase.
A estratégia geral consiste em identificar padrões de geração de código, e após a análise semântica percorrer novamente a árvore sintáctica (mas já com a garantia muito importante de inexistência de erros sintácticos e semânticos) gerando o código destino nos pontos apropriados.
Código fonte:
1+2*3:4
Uma possível compilação para Java:
Tradicionalmente, o ensino de processadores de linguagens tende a dar primazia à geração de código baixo nível (linguagem máquina, ou assembly).
A larga maioria da bibliografia mantém esse enfoque.
No entanto, do ponto de vista prático serão poucos os programadores que, fazendo uso de ferra- mentas para gerar processadores de linguagens, necessitam ou ambicionam este tipo de geração de código.
Nesta disciplina vamos, alternativamente, discutir a geração de código numa perspectiva mais abrangente, incluindo a geração de código em linguagens de alto nível.
No que diz respeito à geração de código em linguagens de baixo nível, é necessário um conheci- mento robusto em arquitectura de computadores e lidar com os seguintes aspectos:
Representação e formato da informação (formato para números inteiros, reais, estruturas, array, etc.);
Gestão e endereçamento de memória;
Implementação de funções (passagem de argumentos e resultado, suporte para recursividade com pilha de chamadas e frame pointers);
Alocação de registos do processador.
(Consultar a bibliografia recomendada para estudar este tipo de geração de código.)
Seja qual for o nível da linguagem destino, uma possível estratégia para resolver este problema consiste em identificar sem ambiguidade padrões de geração de código associados a cada elemento gramatical da linguagem.
Para esse fim, é necessário definir o contexto de geração de código para cada elemento (por exemplo, geração de instruções na linguagem destino, ou atribuir a valor a uma variável), e depois garantir que o mesmo é compatível com todas as utilizações do elemento.
Como a larguíssima maioria das linguagens destino são textuais, esses padrões de geração de código consistem em padrões de geração de texto.
Assim sendo, em Java, poderíamos delegar esse problema no tipo de dados String, StringBuilder, ou mesmo na escrita directa de texto em em ficheiro (ou no standard output).
No entanto, também aí o ambiente ANTLR4 fornece uma ajuda mais estruturada, sistemática e modular para lidar com esse problema.