Construção de Compiladores

Slides:



Advertisements
Apresentações semelhantes
Software Básico Silvio Fernandes
Advertisements

Tópicos em Compiladores
Compiladores Claudio Benossi
II – Análise léxica DEI lex: linguagem de especificação para analisadores léxicos Implementação de simuladores de autómatos finitos Bibliografia aconselhada:
III – Análise sintáctica Geradores de parsers Bibliografia aconselhada: –Aho, Sethi e Ullman – secção 4.9 LFA 1999/ Jorge Morais.
Compiladores I Cristiano Damiani Vasconcellos
LINGUAGEM DE PROGRAMAÇÃO ORIENTADA A OBJETOS INTRODUÇÃO AOS APLICATIVOS JAVA Prof. Thiago Pereira Rique
Deyvisson, Rafael M.P., Renato, Robson C.F., Rodolfo
Análise Léxica (Parte 2)
Software Básico Silvio Fernandes
Introdução a Programação Renata Freire
JavaCC e JJTree Geração de compiladores implementados em Java
YACC.
Lex e Yacc.
Linguagem de Prog. e Programas
Análise Léxica Supondo o trecho de programa abaixo:
Universidade Federal da Paraíba Departamento de Informática Construção de Compiladores Verificação de Tipos.
Construção de Compiladores
Construção de Compiladores
Construção de Compiladores
Construção de Compiladores
5.6 – Complementos de Yacc – Usando Yacc com gramáticas ambíguas
Prof. Msc. Raul Paradeda Aula 3 Fundamentos
Introdução a Programação JAVA
JAVA: Conceitos Iniciais
Departamento de Estatística e Informática
JAVA Linguagem Ambiente de Desenvolvimento
Ferramentas para a Construção de Compiladores: Lex & Yacc
Compiladores, Aula Nº 5 João M. P. Cardoso
Compiladores, Aula Nº 9 João M. P. Cardoso
Gramáticas Livres de Contexto
Linguagem de Programação JAVA
Introdução a aplicativos Java
Prof. Daniel Aula 03.  Criar Projeto  Criar Pacote  Criando classes  Meu primeiro programa  Compilar  Comentários  Variáveis.
Análises léxica e sintática
Análise Léxica Primeira fase de um compilador
Classes, Objetos, Atributos e Métodos JAVA
Mayerber Carvalho Neto
Algoritmo e Programação
Vladimir Oliveira Di Iorio
Análise Léxica.
Capítulo II Gramáticas e Linguagens
Analise sintática aula-07-analise-sintática.pdf.
By Ducheno Kelly Centro de Formação São Domingos.
Análises léxica e sintática
Analisador Léxico Prof. Alexandre Monteiro
Linguagem de Programação C#
Compiladores Análise Léxica
Aula 12 1 Análise Sintáctica Compiladores, Aula Nº 12 João M. P. Cardoso.
Análise Léxica Prof. Alexandre Monteiro
CES-41 COMPILADORES Aulas Práticas Capítulo II A Ferramenta Yacc.
William Ivanski Curso de Programação C#. Sumário  Exercícios para Fixação  Utilizando uma IDE  Elementos da Linguagem C#  Valores  Variáveis  Tipos.
Analisador Léxico.
JAVA Sintaxe.
CES-41 COMPILADORES Aulas Práticas
Faculdade Pernambucana - FAPE Setembro/2007
COMPILADORES 04 Prof. Marcos.
Fundamentos de linguagens de programação
Geradores de analisadores léxicos
JavaCC.
Sintaxe de uma Linguagem
PLP – JavaCC Java Compiler Compiler
Analisador sintático: Tipos de análises sintáticas
Compilador Software que traduz o texto (linguagem fonte) que representa um programa para código máquina(linguagem alvo) capaz de ser executado pelo.
Faculdade Pernambuca - FAPE Compiladores Abril/2007 Compiladores Abril/2007.
Informática Teórica Engenharia da Computação. Teoria da Computação Contexto do que vamos começar a estudar As linguagens também podem ser definidas formalmente.
COMPILADORES 03 Prof. Marcos.
SOCKET - É um canal de comunicação entre processos que estabelece uma conexão entre eles na forma de cliente-servidor. Por meio de sockets, os computadores.
Java Básico Lab Ruddá Beltrão | Cristian Costa.
Laboratório de Computação Aula 06 e 07 – Implementação de classes Prof. Fábio Dias
Transcrição da apresentação:

Construção de Compiladores JFLEX e CUP

Introdução Analisadores léxicos e sintáticos são construídos a partir de especificações formais Gramáticas Regulares / Autômatos finitos Gramáticas Livre de contexto A formalidade das descrições permite que tais analisadores sejam automaticamente construídos Programas que geram programas

Introdução Analisadores Léxicos em C Analisadores Sintáticos em C Lex Flex Analisadores Sintáticos em C Bison YACC Léxico e Sintático em C ANTLR Analisadores Léxicos em Java JLex JFlex Analisadores Sintáticos em Java JCup BYACC/B Léxico e Sintático em Java JavaCC SableCC ANTLR

JFLex e JCup Esquema da operação .jflex .cup .java .java JFLex JCup Descrição em gramática regular Descrição em gramática livre de contexto javac Analisador Léxico Analisador Sintático Arquivo fonte Arvore sintática Arquivo de tokens .class

Gerador de Analisadores Léxicos JFLEX Gerador de Analisadores Léxicos http://jflex.de/index.html

JFlex Arquivo de especificação (.jflex) Dividido em três seções: Código do usuário Diretivas Regras de Expressões Regulares Cada seção é separada da seção seguinte por uma linha contendo apenas ‘%%’

JFlex Código do usuário O código escrito nessa seção é copiado diretamente no topo do arquivo do scanner Útil para declarar “imports” e nome de pacotes

JFlex Diretivas Principais diretivas: Permite a definição de diretivas, macros e nome de estados Principais diretivas: %init{...%init} Tudo que você escrever entre as chaves vai ser copiado diretamente para o método construtor da classe do scanner %eof{...%eof} Permite declarar código que vai ser executado quando o scanner encontrar o fim do arquivo de entrada %char Ativa o contador de caracteres através da variável inteira yychar

JFlex Principais diretivas (continuação) %line %cup Ativa o contador de linhas através da variável inteira yyline %cup Ativa a compatibilidade com o JCup. Isso significa que a classe gerada do scanner vai implementar a interface java_cup.runtime.Scanner %class <nome> Muda o nome da classe do scanner (default = Yylex). %debug Gera o public static void main(...)

JFlex Código incluído entre %...% é copiado literalmente na classe gerada Declaração de variáveis Declaração de funções Identificadores para variáveis e funções não devem ser iniciados com yy

JFlex Diretivas (Macros) São abreviações para expressões regulares Cada macro deve estar contida numa única linha Formato: <nome> = <definição> O nome da macro deve começar com uma letra ou ‘_’. A definição da macro é uma expressão regular.

JFlex Diretivas (Macros) Macros podem conter outras macros. Exemplos: DIGITO = [0-9] ALFA = [A-Za-z] ESPACO_EM_BRANCO = [\n\r\x20\t] NUM_NATURAL = {DIGITO}+

JFlex Diretivas (Estados) Permite implementar uma máquina de estados no scanner. Todo scanner tem pelo menos um estado (declarado internamente) chamado YYINITIAL. Exemplo: %state COMMENT

JFlex Regras de expressões regulares Formato das regras: [<estados>] <expressão> { <ação> } [<estados>] – opcional. Formato: <estado0, estado1, ..., estadoN> Se uma regra for precedida por uma lista de estados, o scanner só tentará aplicar a regra se ele estiver em um dos estados listados Se uma lista de estados não for especificada para uma regra, o scanner sempre tentará aplicar a regra independentemente do seu estado atual

JFlex Regras de expressões regulares <expressão> – obrigatório. Baseadas em expressões regulares Símbolos especiais: | - representa uma opção. Exemplo: e|f significa que a expressão pode casar com e ou f. . (ponto) - casa com qualquer caráter, exceto o ‘\n’. * - casa com zero ou mais repetições da expressão regular precedente Exemplo: [a-z]* casa com {ε, a, aa, ab, ...} + - casa com uma ou mais repetições da expressão regular precedente. Exemplo: [0-9]+ casa com qualquer número natural.

JFlex Regras de expressões regulares <expressão> – obrigatório. Símbolos especiais (cont.): ? – casa com zero ou uma ocorrência da expressão regular precedente. Exemplo: [+ -]?[0-9]+ casa com números naturais precedidos ou não por um sinal de ‘-’ ou ‘+’  {0, 1, -1, +1, -123, +456, ...} (...) – os parênteses são usados para agrupar expressões regulares. Exemplo: (ab)*  {ε, ab, abab, ababac, ...} enquanto que ab*  {a, ab, abb, abbb, ...}

JFlex Regras de expressões regulares <expressão> – obrigatório. Símbolos especiais (cont.): [...] – usado para denotar uma classe de caracteres Exemplo: [a-z] casa com qualquer letra de ‘a’ até ‘z’ Se o símbolo seguinte ao ‘[‘ for o circunflexo (^), o conteúdo do [...] é negado. Exemplo: [^0-9] casa com tudo exceto dígitos.

JFlex Regras de expressões regulares <expressão> – obrigatório. Expressões podem conter macros desde que essas sejam escritas entre chaves Exemplos: {DIGITO}+ representa uma expressão que casa com os números naturais {ALFA}({ALFA}|{DIGITO}|_)* é a expressão que casa com nomes de variáveis na maioria das linguagens de programação

JFlex Regras de expressões regulares <ação> - obrigatório. Uma ação é o trecho de código que deve ser executado quando uma regra for aplicada pelo scanner É possível trocar o estado do scanner dentro de uma ação através de chamada ao método interno yybegin(nome_do_estado) Você pode fazer uso das variáveis yytext (String), yychar (int) e yyline (int) dentro do código de suas ações.

JFlex Regras de expressões regulares (observações) Se mais de uma regra casar com a string de entrada, o scanner escolhe a regra que casa com a maior substring da string. Exemplo: String: abcd Regra 1: “ab” { acao1(); } Regra 2: [a-z]+ { acao2(); } O scanner vai escolher a regra 2. Todas as seqüências de caracteres passadas como entrada para o scanner devem casar com alguma das regras. Caso isso não ocorra, o scanner vai gerar um erro

Gerador de Analisadores Sintáticos JCup Gerador de Analisadores Sintáticos http://www2.cs.tum.edu/projects/cup/

JCup Dividido em quatro seções: Seção 1: declaração de “packages” e “imports” que serão inseridos no topo do arquivo gerado pelo JCup e diretivas do JCup Seção 2: declaração de terminais e não-terminais Seção 3: precedência e associatividade de terminais Seção 4: gramática

JCup Seção 1 -Especificação de “packages” e “imports”. Exemplo: package compilador.parser; import compilador.scanner; Diretivas parser code {: ... :}; Permite que você declare variáveis e métodos na classe do parser. Similar à diretiva %{...%} do JFlex init with {: ... :}; O código entre chaves vai ser executado antes que o parser peça o primeiro token ao scanner scan with {: ... :}; Serve para que você escreva o código que o parser vai executar sempre que ele quiser pedir um token ao scanner. Se essa diretiva não for utilizada, o parser chama scanner.next_token() para receber tokens.

JCup Seção 2 - Lista de símbolos terminal [classe] nome0, nome1, ...; non terminal [classe] nome0, nome1, ...; Em tempo de execução, os símbolos são representados por objetos da classe java_cup.runtime.Symbol. Essa classe possui uma variável chamada “value” que contém o valor do símbolo. Exemplo: terminal Integer NUMERO; Quando o parser recebe do scanner um NUMERO, ele cria um objeto da classe Symbol. A variável “value” será um objeto da classe Integer. Assim, o valor do número pode ser obtido através de simbolo.value.intValue(); Se não for fornecida uma classe na declaração do (non) terminal, a variável “value” ficará com valor null. Os nomes dos (non) terminais não podem ser palavras reservadas do JCup: "code", "action", "parser", "terminal", "non", "nonterminal", "init", "scan", "with", "start", "precedence", "left", "right", "nonassoc", "import", e "package"

JCup Seção 3 - Precedência e Associatividade precedence left terminal[, terminal...]; precedence right terminal[, terminal...]; precedence nonassoc terminal[, terminal...]; A precedência cresce de cima para baixo, por exemplo: precedence left ADD, SUBTRACT; precedence left TIMES, DIVIDE; Significa que a multiplicação e a divisão têm maior precedência.

JCup Seção 4 - Gramática Especifica as produções da gramática da linguagem. start with non-terminal; (diretiva opcional) Indica qual é o não-terminal inicial da gramática. Se essa diretiva for omitida, o parser assume o primeiro não-terminal declarado nas produções da gramática. As produções têm o formato: não-terminal ::= <símbolos e ações> Os símbolos à direita de “::=“ podem ser terminais ou não-terminais. As ações correspondem ao código que é executado quando a regra de produção é aplicada

JCup Seção 4 – Gramática Exemplo: expr ::= NUMBER:n {: RESULT=n; :} | expr:r PLUS expr:s RESULT=new Integer(r.intValue() + s.intValue()); Observe que pode-se especificar várias produções para um mesmo não terminal através do uso da barra “|”. Pode-se nomear símbolos para poder referenciá-los no código da ação. O resultado da produção deve ser armazenado na variável implícita “RESULT”. O tipo de “RESULT” é o mesmo que foi declarado na seção 2.