Como construir um compilador utilizando ferramentas Java Aula 1 - Introdução Prof. Márcio Delamaro [email protected] Como construir um compilador utilizando ferramentas Java – p. 1/2 O livro http://www.novatec.com.br/livros/compilador/ http://www.novateceditora.com.br/downloads.php Como construir um compilador utilizando ferramentas Java – p. 2/2 Conteúdo Introdução à compilação. Descrição da linguagem X++, utilizada como estudo de caso. Apresenta conceitos básicos sobre linguagens e como defini-las. Análise léxica. Mostra como se utiliza a ferramenta JavaCC para criar um analisador léxico para a linguagem X++. Análise sintática. Mostra como construir um analisador sintático para X++ utilizando JavaCC. Como construir um compilador utilizando ferramentas Java – p. 3/2 Conteúdo Árvore sintática. Mostra como construir a árvore sintática usando o JavaCC e como utilizá-la nas etapas seguintes. Tabela de símbolos e análise semântica. Mostra como implementar uma tabela de símbolos utilizada na checagem de tipos e validação semântica. Geração de código. Mostra como utilizar a ferramenta Jasmin para gerar o código-objeto (bytecode) Java. Como construir um compilador utilizando ferramentas Java – p. 4/2 O que é um programa? Seqüência de 0s e 1s. CPU Memória A B C D 000 001 002 003 004 005 006 007 Como construir um compilador utilizando ferramentas Java – p. 5/2 Operações simples Programa é armazenado na memória. Como construir um compilador utilizando ferramentas Java – p. 6/2 Operações simples Programa é armazenado na memória. Programa é executado dentro da CPU por meio de instruções muito simples. Como construir um compilador utilizando ferramentas Java – p. 6/2 Operações simples Programa é armazenado na memória. Programa é executado dentro da CPU por meio de instruções muito simples. “Somar posição de memória 100 com posição 101 e colocar resultado em 102.” copiar o conteúdo da posição de memória 100 para o registrador A; copiar o conteúdo da posição de memória 101 para o registrador B; somar o conteúdo de B em A; copiar o conteúdo de A para a posição de memória 102. Como construir um compilador utilizando ferramentas Java – p. 6/2 Linguagens de alto nível Necessário desenvolver programas num nível de abstração um pouco mais elevado. Como construir um compilador utilizando ferramentas Java – p. 7/2 Linguagens de alto nível Necessário desenvolver programas num nível de abstração um pouco mais elevado. Menos dependente das instruções de uma determinada máquina. Como construir um compilador utilizando ferramentas Java – p. 7/2 Linguagens de alto nível Necessário desenvolver programas num nível de abstração um pouco mais elevado. Menos dependente das instruções de uma determinada máquina. As linguagens de alto nível substituem as instruções dos computadores por comandos cujas utilização e compreensão são mais fáceis Como construir um compilador utilizando ferramentas Java – p. 7/2 Linguagens de alto nível Necessário desenvolver programas num nível de abstração um pouco mais elevado. Menos dependente das instruções de uma determinada máquina. As linguagens de alto nível substituem as instruções dos computadores por comandos cujas utilização e compreensão são mais fáceis a=b+c Como construir um compilador utilizando ferramentas Java – p. 7/2 Processo de compilação As linguagens de programação evoluíram Como construir um compilador utilizando ferramentas Java – p. 8/2 Processo de compilação As linguagens de programação evoluíram Máquinas continuam as mesmas ou seja, continuam usando instruções de baixo nível Como construir um compilador utilizando ferramentas Java – p. 8/2 Processo de compilação As linguagens de programação evoluíram Máquinas continuam as mesmas ou seja, continuam usando instruções de baixo nível Como usar então uma linguagem de alto nível numa máquina que não a compreende? Como construir um compilador utilizando ferramentas Java – p. 8/2 Processo de compilação As linguagens de programação evoluíram Máquinas continuam as mesmas ou seja, continuam usando instruções de baixo nível Como usar então uma linguagem de alto nível numa máquina que não a compreende? PROGRAMA PROGRAMA FONTE OBJETO COMPILADOR Como construir um compilador utilizando ferramentas Java – p. 8/2 Os componentes de um compilador o analisador léxico; o analisador sintático; o analisador semântico; o gerador de código. Como construir um compilador utilizando ferramentas Java – p. 9/2 Analisador léxico O analisador léxico (AL) encarrega-se de separar no programa fonte cada símbolo que tenha algum significado para a linguagem ou de avisar quando um símbolo que não faz parte da linguagem é encontrado. Como construir um compilador utilizando ferramentas Java – p. 10/2 Análise léxica 123 x1 ; y2 true begin Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; y2 – nome de variável ou procedimento; Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; y2 – nome de variável ou procedimento; true – constante booleana; Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; y2 – nome de variável ou procedimento; true – constante booleana; begin – palavra reservada. Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; y2 – nome de variável ou procedimento; true – constante booleana; begin – palavra reservada. A descrição da linguagem diz quais são os símbolos válidos e o que significam Como construir um compilador utilizando ferramentas Java – p. 11/2 Análise léxica 123 x1 ; y2 true begin 123 – constante inteira; x1 – nome de variável ou procedimento; ; – símbolo especial “ponto-e-vírgula”; y2 – nome de variável ou procedimento; true – constante booleana; begin – palavra reservada. A descrição da linguagem diz quais são os símbolos válidos e o que significam Erros léxicos Como construir um compilador utilizando ferramentas Java – p. 11/2 Nem tudo é tão simples 123x1begin(end Como construir um compilador utilizando ferramentas Java – p. 12/2 Nem tudo é tão simples 123x1begin(end 123 – constante inteira; Como construir um compilador utilizando ferramentas Java – p. 12/2 Nem tudo é tão simples 123x1begin(end 123 – constante inteira; x1begin – nome de variável ou procedimento; Como construir um compilador utilizando ferramentas Java – p. 12/2 Nem tudo é tão simples 123x1begin(end 123 – constante inteira; x1begin – nome de variável ou procedimento; ( – símbolo especial “abre parênteses”; Como construir um compilador utilizando ferramentas Java – p. 12/2 Nem tudo é tão simples 123x1begin(end 123 – constante inteira; x1begin – nome de variável ou procedimento; ( – símbolo especial “abre parênteses”; end – palavra reservada. Como construir um compilador utilizando ferramentas Java – p. 12/2 Estados do analisador léxico "Aqui @ temos uma arroba" /* Isso é um comentário */ Como construir um compilador utilizando ferramentas Java – p. 13/2 Analisador sintático O AL não se preocupa em verificar se a ordem em que os símbolos aparecem é válida ou não. Como construir um compilador utilizando ferramentas Java – p. 14/2 Analisador sintático O AL não se preocupa em verificar se a ordem em que os símbolos aparecem é válida ou não. O analisador sintático é o “coração” do compilador, responsável por verificar se a seqüência de símbolos contida no programa fonte forma um programa válido ou não. Como construir um compilador utilizando ferramentas Java – p. 14/2 Análise sintática if (a - 10 > b * 2) a = b; O AS deve ser capaz de analisar esse programa e reconhecê-lo como válido. Após a palavra reservada if deve vir um “(” Uma expressão Um “)” Um comando qualquer (por exemplo “a = b”) Como construir um compilador utilizando ferramentas Java – p. 15/2 Descrição da linguagem O AS é construído sobre uma gramática livre de contexto que descreve a linguagem fonte. Essa gramática é composta de uma série de regras que descrevem quais são as construções válidas da linguagem. O AS deve aceitar aqueles programas que seguem essas regras e rejeitar – indicando a ocorrência de um erro sintático – aqueles que as violam. Como construir um compilador utilizando ferramentas Java – p. 16/2 árvore sintática O AS desempenha ainda outra importante função que é a construção da árvore sintática(árvore de derivação) do programa fonte. Uma árvore sintáticaé uma estrutura em forma de árvore que descreve as construções da linguagem reconhecidas pelo AS no programa fonte. Se o programa fonte possui um comando if como aquele visto há pouco, sua árvore sintática deve espelhar esse fato e descrever como esse comando é formado. Como construir um compilador utilizando ferramentas Java – p. 17/2 árvore sintática if > - a = * 10 b a b 2 Como construir um compilador utilizando ferramentas Java – p. 18/2 O analisador semântico O analisador semântico (ASem) verifica se os aspectos semânticos do programa estão corretos, ou seja, se não existem incoerências quanto ao significado das construções utilizadas pelo programador. Como construir um compilador utilizando ferramentas Java – p. 19/2 O analisador semântico O analisador semântico (ASem) verifica se os aspectos semânticos do programa estão corretos, ou seja, se não existem incoerências quanto ao significado das construções utilizadas pelo programador. Não utiliza mais o programa fonte para fazer tal verificação. Em vez disso, utiliza a árvore sintática como representação do programa. Como construir um compilador utilizando ferramentas Java – p. 19/2 Análise semântica Tipos de operandos incompatíveis com operadores. Se tivermos o comando a = b * c e a variável c foi declarada do tipo string, então o analisador semântico deve apontar um erro semântico, pois esse tipo de operando não é compatível com o operador * Como construir um compilador utilizando ferramentas Java – p. 20/2 Análise semântica Tipos de operandos incompatíveis com operadores. Se tivermos o comando a = b * c e a variável c foi declarada do tipo string, então o analisador semântico deve apontar um erro semântico, pois esse tipo de operando não é compatível com o operador * Variáveis não declaradas. Como construir um compilador utilizando ferramentas Java – p. 20/2 Análise semântica Tipos de operandos incompatíveis com operadores. Se tivermos o comando a = b * c e a variável c foi declarada do tipo string, então o analisador semântico deve apontar um erro semântico, pois esse tipo de operando não é compatível com o operador * Variáveis não declaradas. Redeclaração de variáveis. Como construir um compilador utilizando ferramentas Java – p. 20/2 Análise semântica Tipos de operandos incompatíveis com operadores. Se tivermos o comando a = b * c e a variável c foi declarada do tipo string, então o analisador semântico deve apontar um erro semântico, pois esse tipo de operando não é compatível com o operador * Variáveis não declaradas. Redeclaração de variáveis. Chamadas de funções ou métodos com o número incorreto de parâmetros. Como construir um compilador utilizando ferramentas Java – p. 20/2 Análise semântica Tipos de operandos incompatíveis com operadores. Se tivermos o comando a = b * c e a variável c foi declarada do tipo string, então o analisador semântico deve apontar um erro semântico, pois esse tipo de operando não é compatível com o operador * Variáveis não declaradas. Redeclaração de variáveis. Chamadas de funções ou métodos com o número incorreto de parâmetros. Comandos colocados fora de contexto. Por exemplo, a utilização de um comando continue fora de um comando de laço deve ser apontada como um erro semântico. Como construir um compilador utilizando ferramentas Java – p. 20/2 Erros semânticos Esses erros não são detectados pelo AS, pois não constituem erros sintáticos. De acordo com a gramática da linguagem fonte, uma variável c pode ser utilizada em uma expressão como a = b * c, não importando se foi declarada anteriormente ou não, ou qual é o seu tipo. Como construir um compilador utilizando ferramentas Java – p. 21/2 Tabela de símbolos Para desempenhar seu papel, o ASem depende de uma tabela de símbolos. Nela são armazenadas informações de variáveis declaradas, funções ou métodos, tipos ou classes. Ao analisar o comando a = b * c (ou melhor, a árvore sintática correspondente a esse comando), o ASem precisa saber se cada uma das variáveis envolvidas foi previamente declarada e o tipo de cada uma delas. O ASem deve, ao analisar um comando de declaração como int c, incluir na tabela de símbolos a variável c, indicando, entre outras coisas, que seu tipo é int. Como construir um compilador utilizando ferramentas Java – p. 22/2 O gerador de código Uma vez verificado que não existem erros sintáticos ou semânticos, o compilador pode realizar sua tarefa, que é a criação do programa objeto. Como construir um compilador utilizando ferramentas Java – p. 23/2 O gerador de código Uma vez verificado que não existem erros sintáticos ou semânticos, o compilador pode realizar sua tarefa, que é a criação do programa objeto. O programa objeto reflete, mediante instruções de baixo nível, os comandos do programa fonte. Como cada máquina ou cada plataforma possui um conjunto diferente de instruções e de meios de acesso ao sistema operacional, em geral é necessário que exista um gerador de código distinto para cada plataforma. Como construir um compilador utilizando ferramentas Java – p. 23/2 JavaCC Programa é um gerador de compiladores, ou mais precisamente um gerador de analisador sintático. Ele toma como entrada uma gramática e transforma-a num programa Java capaz de analisar um arquivo e dizer se satisfaz ou não as regras especificadas nessa gramática. Ele também oferece facilidades para a construção da árvore sintática. Ao descrever a gramática, pode-se também indicar como a árvore sintática deve ser construída, incorporando-se código para realizar tal tarefa ao analisador sintático gerado. Como construir um compilador utilizando ferramentas Java – p. 24/2 Próximo passo Vamos definir uma linguagem de programação que será usada como estudo de caso durante o curso. Ver Capítulo 2 do livro. Como construir um compilador utilizando ferramentas Java – p. 25/2