Construção de um compilador para a linguagem Panda

Documentos relacionados
Compilação da linguagem Panda

Identificadores Nome de variáveis, constantes, métodos, etc...

Compiladores I Prof. Ricardo Santos (cap 3 Análise Léxica: Introdução, Revisão LFA)

IV.2 Aspectos Léxicos Convencionais

Programas Interativos

Universidade Estadual da Paraíba - UEPB Curso de Licenciatura em Computação

Compiladores Análise Semântica

Simulação de Caixa Automático

Universidade Federal de Goiás Bacharelado em Ciências da Computacão Compiladores

Compiladores. Conceitos Básicos

Compiladores - Especificando Sintaxe

FACULDADE LEÃO SAMPAIO

Análise Sintática Introdução

Compiladores. Análise Semântica

Compiladores 04 Analise léxica Jflex. Prof José Rui

Compiladores Análise Semântica

Ambiente de desenvolvimento

Compiladores. Análise Léxica

Introdução à Programação

Compiladores 02 Analise léxica

Compiladores - JFlex. Fabio Mascarenhas

Compiladores - JFlex. Fabio Mascarenhas Monday, April 15, 13

Análise Sintática. Eduardo Ferreira dos Santos. Outubro, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 18

Esta categoria mais geral, à qual cada objeto pertence, denominamos de classe; IFSC/POO + JAVA - prof. Herval Daminelli

Compiladores I Prof. Ricardo Santos (cap 1)

Análise Sintática I. Eduardo Ferreira dos Santos. Abril, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 42

Compiladores. Motivação. Tradutores. Motivação. Tipos de Tradutores. Tipos de Tradutores

Classes e Objetos. Sintaxe de classe em Java

Universidade de Santa Cruz do Sul UNISC Departamento de informática COMPILADORES. Introdução. Geovane Griesang

Tokens, Padroes e Lexemas

Aula 4: Introdução à Linguagem C++

Programação: Vetores

Introdução parte II. Compiladores. Mariella Berger

15/03/2018. Professor Ariel da Silva Dias Aspectos sintáticos e semânticos básicos de linguagens de programação

Linguagens de Domínio Específico

Linguagem de Programação III

Estrutura de Dados Básica

Computação L2. Linguagem C++ Observação: Material Baseado na Disciplina Computação Eletrônica.

Como construir um compilador utilizando ferramentas Java

Analisador Léxico parte II

Aula de hoje. Tipos de Dados e Variáveis. Constantes literais. Dados. Variáveis. Tipagem dinâmica. SCC Introdução à Programação para Engenharias

Compiladores. Bruno Lopes. Bruno Lopes Compiladores 1 / 31. Instituto de C

Como construir um compilador utilizando ferramentas Java

CAP. VI ANÁLISE SEMÂNTICA

INE5421 LINGUAGENS FORMAIS E COMPILADORES

Pró-Reitoria Acadêmica Diretoria Acadêmica Assessoria Pedagógica da Diretoria Acadêmica

CP Compiladores I Prof. Msc.. Carlos de Salles

Linguagens de Domínio Específico

Linguagem de Programação III

Folha 3 - Análise léxica

Função, interação com o compilador Especificação e reconhecimento de tokens Implementação Tratamento de erros. Prof. Thiago A. S.

Implementando classes em C# Curso Técnico Integrado em Informática Fundamentos de Programação

Lição 4 Fundamentos da programação

Compiladores Análise de Tipos

Linguagem Técnica I. Prof. Jonatas Bastos

Tratamento dos Erros de Sintaxe. Adriano Maranhão

Compiladores Análise de Tipos

COMPILAÇÃO. Ricardo José Cabeça de Souza

Algoritmos. Algoritmos e Linguagem de Programação - Prof Carlos Vetorazzi

Conceitos de Linguagens de Programação

Compiladores. Introdução

Lista 05 Herança. public class PessoaFisica extends Pessoa { private String RG; public PessoaFisica(){ super(); } public String getrg(){ return RG; }

Linguagem de Programação III

Tipos Algébricos. Programação Funcional. Capítulo 11. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto

Compiladores. Fabio Mascarenhas

Estrutura geral de um compilador programa-fonte

PORTUGUÊS ESTRUTURADO: INTRODUÇÃO INTRODUÇÃO À PROGRAMAÇÃO PROF. ALEXANDRO DOS SANTOS SILVA

Programação para Games II. Professor Ariel da Silva Dias Orientação a Objetos

Fundamentos de Programação. Linguagem C++ aula II - Variáveis e constantes. Prof.: Bruno Gomes

Compiladores Aula 3. Celso Olivete Júnior.

Linguagem Java. Introdução. Rosemary Silveira Filgueiras Melo

Prof. Adriano Maranhão COMPILADORES

Working 03 : Conceitos Básicos I

Familiarização com a ferramenta JavaCC

Programação em C. Variáveis e Expressões. Universidade Federal do Rio Grande do Norte Departamento de Engenharia de Computação e Automação

Programação de Computadores I Dados, Operadores e Expressões PROFESSORA CINTIA CAETANO

Introdução. Compiladores Análise Semântica. Introdução. Introdução. Introdução. Introdução 11/3/2008

Linguagens de Domínio Específico

Compiladores. Análise Léxica

3. Linguagem de Programação C

Compiladores - Análise Léxica

Linguagens de Domínio Específico

Compiladores - Análise Léxica

Compiladores Análise de Tipos

3. Tipos de dados e variáveis

Compiladores. Parser LL 10/13/2008

Compiladores. Lex e Yacc / Flex e Bison. Ferramentas Flex/Bison

Compiladores - Gramáticas

Algoritmos e Estrutura de Dados I Conceitos de Algoritmos. Prof. Elyssandro Piffer

Noçõ linguagem Java. Profs. Marcel Hugo e Jomi Fred Hübner. Departamento de Sistemas e Computação Universidade Regional de Blumenau - FURB

Algoritmos e Técnicas de Programação

TCC 00308: Programação de Computadores I Organização de programas em Python

Aula 3 Conceitos de memória, variáveis e constantes Cleverton Hentz

Puca Huachi Vaz Penna

Transcrição:

Construção de Compiladores I UFOP DECOM 2014 1 Atividades Práticas Construção de um compilador para a linguagem Panda Etapa 1 Sumário José Romildo Malaquias Resumo Nesta série de atividades vamos implementar várias construções da linguagem Panda no compilador. Ao submeter uma atividade, deve ser incluído um documento explicando como as tarefas foram realizadas. Em relação à análise semântica, as regras implementadas devem ser explicadas de forma clara. 1 Mensagens de erro 1 2 Representação de tipos 2 3 Símbolos 2 4 Tabelas de símbolos 2 5 Os analisadores léxico, sintático e semântico 3 6 Comentários 4 7 Identificadores 4 8 Literais booleanos 4 9 Literais inteiros 5 10 Literais reais 6 11 Literais string 7 1 Mensagens de erro O projeto contém algumas classes para reportar erros encontrados durante a compilação. Estas classes fazem parte do pacote ErrorMsg e serão comentadas a seguir. Em todo compilador é desejável que os erros encontrados sejam reportados com uma indicação da localização do erro, acompanhada por uma mensagem explicativa do problema ocorrido. Para tanto tornase necessário manter a informação da localização em que cada frase do programa (cada nó da árvore abstrata construída para representar o programa) foi encontrada. Neste projeto as localizações no código fonte são dados em função do número de caracteres desde o começo do arquivo fonte até a posição desejada. Para que seja possível informar a posição usando número de linhas e colunas nas mensagens de erro, precisamos manter uma lista com informações da localização do começo de cada linha do arquivo fonte. Uma instância da classe ErrorMsg.Source possui basicamente três informações sobre o programa fonte sendo compilado: o nome do arquivo fonte, uma lista contendo a posição do início de cada linha já lida do arquivo fonte, e a contagem de linhas do arquivo fonte O analisador léxico deverá usar o método newline desta classe toda vez que for encontrada uma nova linha no arquivo fonte. A classe ErrorMsg.Loc é usada para representar uma localização no arquivo fonte. Uma localização é caracterizada por: 1

uma indicação do arquivo fonte (uma instância de Error.Source ), uma posição inicial (equerda), e uma posição final (direita) Assim através da localização de uma frase conhece-se o arquivo fonte onde a frase foi encontrada, a posição em que ela começou e a posição em que ela terminou. A classe ErrorMsg.ErrorMsg deve ser usada para emissão de mensagens de erro através do método error, que recebe como argumentos a localização do erro e a mensagem de diagnóstico. Esta classe possui também um atributo anyerror usado para sinalizar se houve algum erro durante a compilação. 2 Representação de tipos O pacote Types contém classes para a representação dos tipos da linguagem no compilador. A classe Types.Type é uma classe abstrata. Ele deve ser uma superclasse de todas as outras classes que representam tipos da linguagem sendo compilada. O método actual é usado para determinar o tipo realmente representado na presença de definições de tipos e recursividade, e será explicado oportunamaente. O método coerceto permite verificar se um tipo é compatível com outro tipo, dado como argumento para o método. A inteface Types.Types declara algumas contantes para representar os tipos mais comuns da linguagem sendo compilada, com o objetivo de facilitar a programação do restante do compilador. 3 Símbolos Linguagens de programação usam identificadores para nomear entidades da linguagem, como variáveis, funções, classes, módulos, etc. Símbolos léxicos que são identificadores tem um valor semântico que é o nome do identificador, e que a princípio pode ser representado por uma String. Porém o tipo String tem algumas incoveniências para o compilador: Geralmente o mesmo identificador pode ocorrer várias vezes em um programa. Se cada ocorrência for representada por string (ou seja, por uma sequência de caracteres), o uso de memória poderá ser grande. Normalmente existem dois tipos de ocorrência de identificadores em um programa: uma declaração do identificador, e um uso do identificador já declarado. Durante a compilação cada ocorrência de uso de um identificador deve ser associada com um ocorrência de declaração. Para tanto os identificadores devem ser comparados para determinar se são iguais (isto é, tem o mesmo nome). O uso de strings pode ser ineficiente, por pode ser necessário comparar todos os caracteres da string para determinar se elas são iguais ou não. Por estas razões o compilador utiliza um outro tipo ( Symbol.Symbol ) para representar os nomes dos identificadores. Basicamente mantém-se uma tabela com todas os identificadores já encontrados, e todas as vezes que o analisador léxico encontrar um identificador, deve-se verificar se o seu nome já está na tabela. Em caso afirmativo, usa-se o símbolo encontrado na tabela. Caso contrário cria-se um novo símbolo, que é adicionado à tabela, e usado pelo analisador léxico. A comparação de igualdade de símbolos se resumo a uma comparação de referências, já que o mesmo identificador estará sempre sendo representado pelo mesmo símbolo (mesmo objeto na memória). O método Symbol.Symbol.symbol cria um símbolo a partir de uma string. Observação: Não confunda o tipo Symbol.Symbol (o tipo dos símbolos que representam identificadores) com o tipo java_cup.runtime.symbol (o tipo dos símbolos gramaticais terminais e não-terminais). 4 Tabelas de símbolos Em Panda identificadores são usados para nomear entidades como tipos, variáveis e funções. Quando um identificador é usado, é necessário que ele tenha sido previamente definido, e informações sobre como ele foi definido devem ser recuperadas para compilar a frase em que o identificador é usado. Por exemplo, quando compilamos uma expressão que é uma variável simples, é necessário saber o tipo da variável. 2

uma expressão que é uma chamada de função, é necessário saber o número de argumentos e o tipo de cada argumento que a função espera, bem como o tipo do resultado da função. As informações disponíveis no momento em que um identificador é declarado são guardados em uma estrutura de dados chamada tabela de símbolos, que mapeia o nome (símbolo) à informação relevante a ele. Posteriormente estas tabelas podem ser usadas para recuperar estas informações. A classe Symbol.Symbol contém código para manipular tabelas de símbolo (também chamadas de ambiente). As tabelas de símbolo usadas pelo compilador de Panda e definidas como atributos na classe Env.Env são: Env.Env.venv é a tabela de variáveis e funções, e Env.Env.tenv é a tabela de tipos. As entradas na tabela de variáveis e funções são do tipo Env.Entry, que possui duas subclasses: Env.VarEntry, usada para definições de variáveis, contendo o atributo ty que representa o tipo da variável Env.FunEntry, usada para definições de funções, contendo os atributos formals representando os tipos dos parâmetros formais da função, e result representando o tipo do resultado da função 5 Os analisadores léxico, sintático e semântico O pactye Abs contém as classes que representam as árvores abstratas para as construções da linguagem. O pacote Parse contém as classes que implementam os analisadores léxico e sintático do compilador. O analisador léxico (classe Parse.Lexer ) é gerado automaticamente pela ferramenta jflex. A especificação léxica é feita no arquivo panda.jflex usando expressões regulares. O analisador sintático (classe Parse.Parser ) é gerado automaticamente pela ferramenta JavaCUP. A especificação sintática é feita no arquivo panda.cup usando uma gramática livre de contexto. O JavaCUP gera também uma classe Parse.sym contendo definições de constantes para representar os diversos símbolos terminais da gramática. Esta classe é usada pelos analisadores léxico e sintático. A classe Parse.Tokens contém o método dumptoken que obtém a descrição de um símbolo léxico (token) na forma de uma string, e é útil quando precisarmos exibir um token. A análise semântica é feita por meio de métodos definidos nas classes que representam as árvores abstratas das construões da linguagem. Ao acrescentar uma nova construção na implementação da linguagem: defina as classes necessárias para representar a árvore abstrata para a construção no pacote Absyn ; uma classe que representa uma árvore abstrata deverá ser uma subclasse de Absyn.Absyn ; lembrese de: definir os campos necessários para as sub-árvores da árvore abstrata, definir o construtor que inicializa estes campos com valores passados como argumentos, definir o método tostring que permite converter para string, definir o método totree que permite converter para uma árvore de string, útil para visualização gráfica a árvore abstrata, definir o método adequado para análise semântica declare novos símbolos terminais e não-terminais na gramática livre de contexto da linguagem, necessários para as especificações léxica e sintática da construção, acrescente as regras de produção para a construção na gramática livre de contexto da linguagem, tomando o cuidado de escrever ações semânticas adequadas para a construção da árvore abstrata correspondente, se necessário acrescente regras léxicas que permitam reconhecer os novos símbolos terminais na especificação léxica da linguagem, e 3

se necessário modifique o método dumptoken (que converte um símbolo léxico para String ) da classe Parse.Tokens para considerar os novos símbolos terminais. 6 Comentários Um comentário de linha em Panda começa com a sequência de caracteres // e termina no final da linha. Um comentário de bloco em Panda é delimitado por /* e por */. Comentários de bloco podem ser aninhados. Tarefa 1: Comentários Análise léxica Acrescentar regras léxicas para reconhecer (e descartar) comentários de linha e de bloco em Panda. Se um comentário de bloco não terminar deve ser reportado um erro. Tarefa 2: Comentários Testes // isto é um comentário de linha /* isto é um comentário de bloco */ /* isto é um comentário de bloco /* aninhado */ percebeu */ /* Este comentário de bloco não terminou /* Este comentário de bloco /* com aninhamento */ não terminou 7 Identificadores Os identificadores de Panda são formados por uma sequência não vazia de letras (maiúsuclas ou minúsculas), dígitos decimais e sublinhado ( _ ), começando com uma letra. Letras maiúsculas e minúsculas são consideradas diferentes. Tarefa 3: Identificadores Análise léxica 1. Modifique a gramática de Panda acrescentando um símbolo terminal ID para os tokens dos identificadores. Use um valor semântico do tipo Symbol.Symbol para estes tokens. classe Parse.Tokens para considerar o novo símbolo terminal ID. 3. Acrescente regras léxicas para o símbolo terminal ID. 8 Literais booleanos Implementar no projeto de compilador da linguagem Panda o tratamento de literais booleanos. Os literais booleanos são #t (verdadeiro) e #f (falso). 4

Tarefa 4: Literais booleanos Árvore abstrata Definir a classe Absyn.BoolExp para representar a árvore abstrata de uma constante booleana. 1. Defina as variáveis de instância necessárias para representar a estrutura da expressão. 2. Defina o construtor para a classe. 3. Redefina o método totree para converter um objeto desta classe para Tree<String>. Tarefa 5: Literais booleanos Análise léxica 1. Modifique a gramática de Panda acrescentando um símbolo terminal BOOLLIT para os tokens dos literais booleanos. Use um valor semântico do tipo Boolean para estes tokens. classe Parse.Tokens para considerar o novo símbolo terminal BOOLLIT. 3. Acrescente regras léxicas para o símbolo terminal BOOLLIT. Tarefa 6: Literais booleanos Análise sintática Acrescente na gramática de Panda uma regra de produção para a expressão literal booleano. Tarefa 7: Literais booleanos Análise semântica 1. Defina a classe Types.BOOL para representar o tipo dos valores booleanos. 2. Acrescte uma constante BOOL na classe Types.Types cujo valor é uma instância da classe Types.BOOL. 3. Redefina o método typecheck na classe Absyn.BoolExp que calcula o tipo de uma expressão literal booleano. 4. Adicione na tabela de símbolos de tipos do compilador o símbolo bool. 5. Adicione na tabela de símbolos de variávaeis e funções do compilador as funções da biblioteca padrão que manipulam booleanos. As assinaturas das funções são: function print_bool(x: bool): unit function not(b: bool): bool Tarefa 8: Literais booleanos Testes #t #f #F // erro léxico 9 Literais inteiros Implementar no projeto de compilador da linguagem Panda o tratamento de literais inteiros. Um literal inteiro é uma sequência não vazia de dígitos decimais. O literal só poderá começar com o dígito 0 se ele for o próprio literal 0. 5

Tarefa 9: Literais inteiros Árvore abstrata Definir a classe Absyn.IntExp para representar a árvore abstrata de uma constante inteira. 1. Defina as variáveis de instância necessárias para representar a estrutura da expressão. 2. Defina o construtor para a classe. 3. Redefina o método totree para converter um objeto desta classe para Tree<String>. Tarefa 10: Literais inteiros Análise léxica 1. Modifique a gramática de Panda acrescentando um símbolo terminal INTLIT para os tokens dos literais inteiros. Use um valor semântico do tipo Long para estes tokens. classe Parse.Tokens para considerar o novo símbolo terminal INTLIT. 3. Acrescente regras léxicas para o símbolo terminal INTLIT. Tarefa 11: Literais inteiros Análise sintática Acrescente na gramática de Panda uma regra de produção para a expressão literal inteiro. Tarefa 12: Literais inteiros Análise semântica 1. Defina a classe Types.INT para representar o tipo dos valores inteiros. 2. Acrescte uma constante INT na classe Types.Types cujo valor é uma instância da classe Types.INT. 3. Redefina o método typecheck na classe Absyn.IntExp que calcula o tipo de uma expressão literal inteiro. 4. Adicione na tabela de símbolos de tipos do compilador o símbolo int. 5. Adicione na tabela de símbolos de variáveis e funções do compilador as funções da biblioteca padrão que manipulam inteiros. As assinaturas das funções são: function print_int(x: int): unit Tarefa 13: Literais inteiros Testes 0 3241 10 Literais reais Implementar no projeto de compilador da linguagem Panda o tratamento de números reais (representados como números em ponto flutante). Um literal real é formado por uma sequência de dígitos decimais seguida de um ponto seguido de outra sequência de dígitos decimais. Uma e somente uma das sequências de dígitos decimais pode ser vazia. 6

Tarefa 14: Literais reais Árvore abstrata Definir a classe Absyn.RealExp para representar a árvore abstrata de uma constante real. 1. Defina as variáveis de instância necessárias para representar a estrutura da expressão. 2. Defina o construtor para a classe. 3. Redefina o método totree para converter um objeto desta classe para Tree<String>. Tarefa 15: Literais reais Análise léxica 1. Modifique a gramática de Panda acrescentando um símbolo terminal REALLIT para os tokens dos literais reais. Use um valor semântico do tipo Double para estes tokens. classe Parse.Tokens para considerar o novo símbolo terminal REALLIT. 3. Acrescente regras léxicas para o símbolo terminal REALLIT. Tarefa 16: Literais reais Análise sintática Acrescente na gramática de Panda uma regra de produção para a expressão literal real. Tarefa 17: Literais reais Análise semântica 1. Defina a classe Types.REAL para representar o tipo dos valores reais. 2. Acrescte uma constante REAL na classe Types.Types cujo valor é uma instância da classe Types.REAL. 3. Redefina o método typecheck na classe Absyn.RealExp que calcula o tipo de uma expressão literal real. 4. Adicione na tabela de símbolos de tipos do compilador o símbolo real. 5. Adicione na tabela de símbolos de variáveis e funções do compilador as funções da biblioteca padrão que manipulam reais. As assinaturas das funções são: function print_real(x: real): unit function round(f: real): int function ceil(f: real): int function floor(f: real): int function real(i: int): real Tarefa 18: Literais reais Testes 30.12 98632..2349 11 Literais string Implementar no projeto de compilador da linguagem Panda o tratamento de strings. Considere que os literais strings são escritos como uma sequência de caracteres delimitada por aspas duplas ("). O caracter \ é especial e inicia uma sequência de escape. As seguintes sequências de escape são válidas: 7

\\ o caracter \ \" o caracter " \n o caracter de mudança de linha \t o caracter de tabulação horizontal \ddd o caracter de código decimal ddd (ddd é uma sequência de dígitos decimais) Tarefa 19: Literais strings Árvore abstrata Definir a classe Absyn.StringExp para representar a árvore abstrata de uma constante string. 1. Defina as variáveis de instância necessárias para representar a estrutura da expressão. 2. Defina o construtor para a classe. 3. Redefina o método totree para converter um objeto desta classe para Tree<String>. Tarefa 20: Literais strings Análise léxica 1. Modifique a gramática de Panda acrescentando um símbolo terminal STRINGLIT para os tokens dos literais strings. Use um valor semântico do tipo String para estes tokens. classe Parse.Tokens para considerar o novo símbolo terminal STRINGLIT. 3. Acrescente regras léxicas para o símbolo terminal STRINGLIT. Tarefa 21: Literais strings Análise sintática Acrescente na gramática de Panda uma regra de produção para a expressão literal string. Tarefa 22: Literais strings Análise semântica 1. Defina a classe Types.STRING para representar o tipo dos valores strings. 2. Acrescte uma constante STRING na classe Types.Types cujo valor é uma instância da classe Types.STRING. 3. Redefina o método typecheck na classe Absyn.StringExp que calcula o tipo de uma expressão literal string. 4. Adicione na tabela de símbolos de tipos do compilador o símbolo string. 5. Adicione na tabela de símbolos de variáveis e funções do compilador as funções da biblioteca padrão que manipulam strings. As assinaturas das funções são: function print(x: string): unit function length(s: string): int function substring(s: string, start: int, length: int): string Tarefa 23: Literais strings Testes "Bom dia, Brasil!" "" "abc\tdef\nghi\\jkl\"mno\065ok" // invalid escape sequence in string literal "abc\kdef" // unclosed string literal "abc 8