Como construir um compilador utilizando ferramentas Java

Documentos relacionados
Compiladores. Exemplo. Caraterísticas de Gramáticas. A αβ 1 αβ 2. A αx X β 1 β 2. Lembrando... Gramáticas Livres de Contexto

Análise Sintática II: Analisadores Descendentes Preditivos

Como construir um compilador utilizando ferramentas Java

Como construir um compilador utilizando ferramentas Java

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Compiladores Analisador Sintático. Prof. Antonio Felicio Netto Ciência da Computação

V Análise Sintática. V.1.1 Gramáticas Livres de Contexto Definições de GLC

Como construir um compilador utilizando ferramentas Java

Compiladores - Análise LL(1)

Análise Sintática (Cap. 04) Análise Sintática Descendente

Análise Sintática LL(1)

Compiladores - Análise Ascendente

Compiladores - Análise Ascendente

Compiladores. Análise Sintática

Como construir um compilador utilizando ferramentas Java

Um Compilador Simples. Definição de uma Linguagem. Estrutura de Vanguarda. Gramática Livre de Contexto. Exemplo 1

Construção de Compiladores Aula 17 - Análise Sintática Descendente

Análise sintática. Análise sintática. Top-down ou descendente. Com retrocesso: por tentativa e erro. Preditiva: para gramáticas LL(1) 09/04/2012

Análise sintática. Prof. Thiago A. S. Pardo Tratamento de erros sintáticos

Compiladores Aula 6. Celso Olivete Júnior.

Plano da aula. Compiladores. Os erros típicos são sintáticos. Análise Sintática. Usando Gramáticas. Os erros típicos são sintáticos

Como construir um compilador utilizando ferramentas Java

Análise Sintática. Fabiano Baldo

Análise sintática. Análise sintática ascendente. Bottom-up, ascendente ou redutiva. Analisadores de precedência de operadores Analisadores LR

INE5317 Linguagens Formais e Compiladores AULA 9: Propriedades e Reconhecimento das Linguagens Livres do Contexto

Conceitos de Linguagens de Programação

Compiladores - Análise Preditiva

BNF (Backus-Naur Form) Gramática Livres de Contexto / Estruturas Recursivas

Compiladores - Gramáticas

Construção de Compiladores Aula 16 - Análise Sintática

INE5318 Construção de Compiladores. AULA 4: Análise Sintática

INE5416 Paradigmas de Programação. Ricardo Azambuja Silveira INE CTC UFSC E Mail: URL:

Compilação: Erros. Detecção de Erros: * Analisadores Top-Down - Preditivo Tabular (LL) - Feito a mão. * Analisadores Botton-Up: - Shift-Reduce (SLR)

Análise sintática. Análise sintática ascendente. Parte-se dos símbolos terminais em direção ao símbolo inicial da gramática. Derivação mais à direita

Reduce: reduz o que está imediatamente à esquerda do foco usando uma produção

Gramática. Prof. Yandre Maldonado e Gomes da Costa. Prof. Yandre Maldonado - 1

Gramática. Gramática. Gramática

Vantagens de uma Gramática. Sintaxe de uma Linguagem. Analisador Sintático - Parser. Papel do Analisador Sintático. Tiposde Parsers para Gramáticas

Análise Sintática Bottom-up

Gramática Livre de Contexto

Análise sintática. Prof. Thiago A. S. Pardo. Análise sintática ascendente

Compiladores - Análise SLR

Compiladores - Análise Léxica

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Familiarização com a ferramenta JavaCC

Análise Sintática - Final

Como construir um compilador utilizando ferramentas Java

IV Gramáticas Livres de Contexto

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

Compiladores. Capítulo 3: Análise Sintática Introdução

Compiladores Aula 4. Celso Olivete Júnior.

Parsing Preditivo. Antes de ser abordado o Parsing Preditivo, será apresentado o Analisador Sintático Descendente Recursivo.

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Sintaxe e Semântica. George Darmiton da Cunha Cavalcanti.

Compiladores - Análise Léxica

Compiladores - JACC. Fabio Mascarenhas

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

Gramática Livre de Contexto

Notação EBNF BNF estendida Notação usada com o YACC (gerador de parsers Bottom-up)

Análise Sintática Descendente

Linguagens Livres de Contexto

Construção de Compiladores

Concurso Público para provimento de cargo efetivo de Docentes. Edital 20/2015 CIÊNCIA DA COMPUTAÇÃO II Campus Rio Pomba

Linguagens Formais e Autômatos. Simplificação de Gramáticas Livre do Contexto (GLC)

Conceitos de Linguagens de Programação

Compiladores Aula 1. Celso Olivete Júnior.

Transcrição:

Como construir um compilador utilizando ferramentas Java p. 1/2 Como construir um compilador utilizando ferramentas Java Aula 6 Análise Sintática Prof. Márcio Delamaro delamaro@icmc.usp.br

Como construir um compilador utilizando ferramentas Java p. 2/2 Ascendente descendente Dada uma GLC, a análise sintática baseada nessa GLC pode ser ascendente ou descendente. Um analisador ascendente agrupa os símbolos da entrada para formar os símbolos não terminais mais distantes do símbolo inicial da GLC ou que estão em níveis inferiores na estrutura da linguagem. Na análise descendente, parte-se do símbolo inicial da GLC e busca-se identificar na entrada as construções que correspondem às produções da GLC.

Como construir um compilador utilizando ferramentas Java p. 3/2 Descendente recursiva Um analisador descendente recursivo utiliza essa última estratégia. Recursivo, pois a cada símbolo não terminal da GLC corresponde um método (muitas vezes recursivo). Cada método deve ler a entrada e reconhecer a estrutrutura do não-terminal.

Como construir um compilador utilizando ferramentas Java p. 4/2 Exemplo classdecl class ident [ extends ident ] classbody

Como construir um compilador utilizando ferramentas Java p. 4/2 Exemplo classdecl class ident [ extends ident ] classbody verificar se o próximo token da entrada é class.

Como construir um compilador utilizando ferramentas Java p. 4/2 Exemplo classdecl class ident [ extends ident ] classbody verificar se o próximo token da entrada é class. verificar se o próximo token é ident.

Como construir um compilador utilizando ferramentas Java p. 4/2 Exemplo classdecl class ident [ extends ident ] classbody verificar se o próximo token da entrada é class. verificar se o próximo token é ident. verificar se o próximo token é extends. Se não for, deve continuar a análise, pois essa parte da produção é opcional. Se for, deve verificar se o token seguinte é um ident. Se for, deve continuar com a análise.

Como construir um compilador utilizando ferramentas Java p. 4/2 Exemplo classdecl class ident [ extends ident ] classbody verificar se o próximo token da entrada é class. verificar se o próximo token é ident. verificar se o próximo token é extends. Se não for, deve continuar a análise, pois essa parte da produção é opcional. Se for, deve verificar se o token seguinte é um ident. Se for, deve continuar com a análise. verificar se o resto da entrada corresponde ao não-terminal classboby. Isso não é feito diretamente pelo método, mas, sim, invocando o método correspondente àquele não-terminal.

Como construir um compilador utilizando ferramentas Java p. 5/2 Exemplo void classdecl() { if ( curtoken.type == CLASS) // token corrente é "class" analex(); // chama AL. curtoken recebe novo token else SintaticError(); // ocorreu erro sintático if ( curtoken.type == IDENT) // token corrente é identificador analex(); else SintaticError(); if ( curtoken.type == EXTENDS) // token corrente é "extends" { analex(); if ( curtoken.type == IDENT) // token é identificador analex(); else SintaticError(); } classbody(); }

Como construir um compilador utilizando ferramentas Java p. 6/2 Gramáticas LL(1) Cuidado na escolha da grámática.

Como construir um compilador utilizando ferramentas Java p. 6/2 Gramáticas LL(1) Cuidado na escolha da grámática. O primeiro L significa left to right e indica que a leitura da entrada é feita da esquerda para a direita.

Como construir um compilador utilizando ferramentas Java p. 6/2 Gramáticas LL(1) Cuidado na escolha da grámática. O primeiro L significa left to right e indica que a leitura da entrada é feita da esquerda para a direita. O segundo L significa left linear e indica que sempre o símbolo não terminal que estiver mais à esquerda será reconhecido primeiro.

Como construir um compilador utilizando ferramentas Java p. 6/2 Gramáticas LL(1) Cuidado na escolha da grámática. O primeiro L significa left to right e indica que a leitura da entrada é feita da esquerda para a direita. O segundo L significa left linear e indica que sempre o símbolo não terminal que estiver mais à esquerda será reconhecido primeiro. E o número 1 indica que o número de símbolos de lookahead necessários é 1.

Como construir um compilador utilizando ferramentas Java p. 7/2 Gramática LL(1)? classdecl class ident [ extends ident ] classbody

Como construir um compilador utilizando ferramentas Java p. 7/2 Gramática LL(1)? classdecl class ident [ extends ident ] classbody classdecl class ident classbody class ident extends ident classbody

Como construir um compilador utilizando ferramentas Java p. 8/2 Tabela preditiva Indica qual caminho seguir S A asab baa bab c Terminais Não-terminal a b c S A S asab S baa A bab A c As posições vazias ou mais do que uma produção.

Como construir um compilador utilizando ferramentas Java p. 9/2 Recursão à esquerda Um caso típico de problemas ao construir a tabela preditiva é relativo à a existência de recursão à esquerda. B Bα A partir de B podemos gerar uma forma sentencial em que o próprio B aparece como primeiro símbolo. Ao tentar reconhecer B, o AS descendente recursivo invoca o método correspondente ao não-terminal. Olhando para o token da entrada, esse método pode escolher um caminho que leve ao aparecimento de outro B, sem que nenhum token tenha sido consumido o que caracteriza a recursão à esquerda.

Como construir um compilador utilizando ferramentas Java p. 10/2 Construção da tabela preditiva À primeira vista, pode parecer fácil calcular a tabela preditiva de uma GLC. Basta olhar quais são os tokens que iniciam as produções do não-terminal B e colocar na linha de B, na coluna desses tokens, as produções que eles iniciam. Porém, existem diversas situações que podem complicar essa tarefa.

Como construir um compilador utilizando ferramentas Java p. 11/2 Dificuldade I Se temos B Aα Cβ, então é preciso saber quais são os tokens que iniciam as produções de A e C para decidir qual produção utilizar. E essa situação pode se propagar, uma vez que A e C podem também iniciar com não-terminais. prog class ident [ classbody ] classbody funcbody. vardecl ;

Como construir um compilador utilizando ferramentas Java p. 12/2 Dificuldade II Se temos B A 1 A 2...A n aα, precisamos saber se A 1,... A n podem gerar a cadeia vazia. Se isso acontecer, então o token a também deve ser utilizado para decidir qual produção de B utilizar. prog class ident [ classbody ] classbody funcbody vardecl ; funcbody [ algumacoisa ] vardecl [ outracoisa ]

Como construir um compilador utilizando ferramentas Java p. 13/2 Dificuldade III Se temos A abb;b α e α λ, então b deve ser considerado como um token que deve ser utilizado para decidir pela produção B α ao tentar reconhecer B. prog class ident classbody ; classbody funcbody vardecl. funcbody [ algumacoisa ] vardecl [ outracoisa ]

Como construir um compilador utilizando ferramentas Java p. 14/2 Algoritmo para construir a TP Adicionar $, que aparece no fim da cadeia Computar FIRST: Seja α uma forma sentencial da gramática. Então FIRST(α) é definido como o conjunto de todos os símbolos terminais a tal que α aβ, ou seja, o conjunto de terminais que iniciam alguma cadeia derivada a partir de α. Computar FOLLOW: Seja B um não-terminal da gramática e S o seu símbolo inicial. O conjunto FOLLOW(B) é formado pelos terminais a tal que S αbaβ, ou seja, existe uma forma sentencial derivável a partir do símbolo inicial em que a aparece imediatamente à direita de B.

Como construir um compilador utilizando ferramentas Java p. 15/2 FIRST para o terminal a, FIRST(a) = {a}; para o não-terminal B, tal que B A 1 A 2...A n, onde A i são símbolos terminais ou não terminais, fazemos: inicialmente FIRST(B) = {} repetimos FIRST(B) = FIRST(B) FIRST(A i ), para i = 1, 2,... até que encontremos algum i tal que A i não deriva λ; para um string α = A 1 A 2...A n, onde A i são símbolos terminais ou não terminais, fazemos: repetimos FIRST(α) = FIRST(α) FIRST(A i ), para i = 1, 2,... até que encontremos algum i tal que A i não deriva λ.

Como construir um compilador utilizando ferramentas Java p. 16/2 Exemplo expression term expression expression term [expression ] +term [expression ] λ term factor term term factor [term ] /factor [term ] λ f actor ident constant (expression)

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*} FIRST(/) = {/ }

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*} FIRST(/) = {/ } FIRST(ident) = {ident}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*} FIRST(/) = {/ } FIRST(ident) = {ident} FIRST(constant) = {constant}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*} FIRST(/) = {/ } FIRST(ident) = {ident} FIRST(constant) = {constant} FIRST(( ) = {(}

Como construir um compilador utilizando ferramentas Java p. 17/2 FIRST: exemplo FIRST($) = {$} FIRST(+) = {+} FIRST(-) = {-} FIRST(*) = {*} FIRST(/) = {/ } FIRST(ident) = {ident} FIRST(constant) = {constant} FIRST(( ) = {(} FIRST(factor) = {ident, constant, (}

Como construir um compilador utilizando ferramentas Java p. 18/2 FIRST: exemplo FIRST(term ) = {*, / }

Como construir um compilador utilizando ferramentas Java p. 18/2 FIRST: exemplo FIRST(term ) = {*, / } FIRST(term) = {ident, constant, (}

Como construir um compilador utilizando ferramentas Java p. 18/2 FIRST: exemplo FIRST(term ) = {*, / } FIRST(term) = {ident, constant, (} FIRST(expression ) = {+, -}

Como construir um compilador utilizando ferramentas Java p. 18/2 FIRST: exemplo FIRST(term ) = {*, / } FIRST(term) = {ident, constant, (} FIRST(expression ) = {+, -} FIRST(expression) = {ident, constant, (}

Como construir um compilador utilizando ferramentas Java p. 19/2 FOLLOW adicionar o indicador de fim de cadeia $ ao conjunto FOLLOW(S), onde S é o símbolo inicial da GLC; dada a produção B αaβ, fazemos: FOLLOW(A) = FOLLOW(A) FIRST(β) se β λ, então fazemos FOLLOW(A) = FOLLOW(A) FOLLOW(B).

Como construir um compilador utilizando ferramentas Java p. 20/2 FOLLOW: exemplo FOLLOW(expression) = {$, )} FOLLOW(expression ) = {$, )} FOLLOW(term) = {+, -, $, )} FOLLOW(term ) = {+, -, $, )} FOLLOW(factor) = {*, /, +, -, $, )}

Como construir um compilador utilizando ferramentas Java p. 21/2 Finalizando a tabela dada a produção B α, para todo terminal a FIRST(α), devemos colocar essa produção na posição (B, a) da tabela; dada a produção B α, onde α λ, para todo terminal a FOLLOW(B), devemos colocar essa produção na posição (B, a) da tabela.

Como construir um compilador utilizando ferramentas Java p. 22/2 Resultado Terminais Não terminais ident constant +, - *, / ( ) $ expression 1 1 1 expression 2 3 3 term 4 4 4 term 6 5 6 6 factor 7 8 9

Como construir um compilador utilizando ferramentas Java p. 23/2 Resultado (1)expression term expression (2)expression +term expression (3)expression λ (4)term factor term (5)term factor term (6)term λ (7)factor ident (8)f actor constant (9)f actor (expression)

Como construir um compilador utilizando ferramentas Java p. 24/2 Como usar a TP A tabela preditiva pode ser usada, além da verificação da gramática, para construir o AS. Para implementar o método de um não-terminal, podemos olhar a tabela e determinar para cada terminal válido quais são as seqüências de ações a tomar, como, por exemplo, consumir um terminal ou invocar os métodos de outros não-terminais.

Como construir um compilador utilizando ferramentas Java p. 24/2 Como usar a TP A tabela preditiva pode ser usada, além da verificação da gramática, para construir o AS. Para implementar o método de um não-terminal, podemos olhar a tabela e determinar para cada terminal válido quais são as seqüências de ações a tomar, como, por exemplo, consumir um terminal ou invocar os métodos de outros não-terminais. Porém, se a linguagem é complexa, o cálculo da tabela preditiva e a construção do AS de forma manual são tarefas árduas. Ainda mais se estivermos trabalhando com uma gramática na BNF, pois, como vimos, o cálculo dos conjuntos FIRST e FOLLOW consideram apenas produções normais, sem os operadores da BNF.

Como construir um compilador utilizando ferramentas Java p. 25/2 Como usar a TP Nesse ponto entram os programas como o JavaCC, que, baseado na definição da linguagem em BNF, gera todos os métodos correspondentes aos não-terminais e verifica possíveis problemas, avisando ao implementador os pontos da gramática que os originaram.

Como construir um compilador utilizando ferramentas Java p. 26/2 Exercícios Dê exemplo de uma gramática que gera uma tabela preditiva com mais de uma entrada em alguma posição. Dê exemplo de uma gramática com recursão à esquerda. Elimine a recursão à esquerda. Dê exemplos, retirados da gramática de X ++ que mostrem as três dificuldades na construção da tabela preditiva. Compute o FIRST e FOLLOW de alguns símbolos de X ++.