Análise Léxica e Sintática

Slides:



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

Tópicos em Compiladores
5.5 – Análise Bottom-Up Tentativa de construir uma árvore sintática para a sentença analisada, começando das folhas, indo em direção à raiz (pós-ordem.
Compiladores Claudio Benossi
III – Análise sintáctica
III – Análise sintáctica
Compiladores I Cristiano Damiani Vasconcellos
Compiladores FIC– Ciência da Computação Professor: Ciro Meneses Santos
Deyvisson, Rafael M.P., Renato, Robson C.F., Rodolfo
Análise Sintática Ascendente ­
Software Básico Silvio Fernandes
Compiladores Prof. Yandre Maldonado Compiladores - Prof. Yandre - 1.
Profa. Heloise Manica Paris Teixeira
JavaCC e JJTree Geração de compiladores implementados em Java
Curso Sistemas de Informação Disciplina: Arquitetura de Software
YACC.
Análise Sintática Ascendente
Relações em uma Gramática
Linguagem de Prog. e Programas
Análise Léxica Supondo o trecho de programa abaixo:
Construção de Compiladores
Construção de Compiladores
Construção de Compiladores
Denis Pinheiro Teoria de Linguagens Prof. Newton José Vieira
Análise léxica e sintática
Aula prática - análise contextual
Ferramentas para a Construção de Compiladores: Lex & Yacc
Compiladores, Aula Nº 11 João M. P. Cardoso
Compiladores, Aula Nº 19 João M. P. Cardoso
Compiladores, Aula Nº 9 João M. P. Cardoso
Gramáticas Livres de Contexto
Aula 17 1 Análise Sintáctica Compiladores, Aula Nº 17 João M. P. Cardoso.
Teoria e Implementação de Linguagens Computacionais
Teoria e Implementação de Linguagens Computacionais – IF688
Sintaxe e Semântica Prof.: Gláucya Carreiro Boechat
Análises léxica e sintática
SableCC José Francisco Pereira Equipe de Monitores
Aulão de Linguagens Formais e Compiladores
Capítulo II Gramáticas e Linguagens
Analise sintática aula-07-analise-sintática.pdf.
Análise Sintática LR Prof. Alexandre Monteiro
Análises léxica e sintática
Aula sobre JavaCC Parsing Tarciana Dias Abril 2013.
Projeto de Tradutor Preditivo. Introdução Introdução Esquemas L-atribuidos são reconhecidos por analisadores Top-Down. Entre estes analisadores, se encontra.
Aula 12 1 Análise Sintáctica Compiladores, Aula Nº 12 João M. P. Cardoso.
Compiladores.
Análise Sintática Prof. Alexandre Monteiro
Tradução Dirigida por Sintaxe
Revisão Compiladores – AP2
AST no ANTLR Teoria e Implementação de Linguagens Computacionais - IF688 Allan J. Souza
Análise Sintática de Descida Recursiva
Linguagens Livres de Contexto
Revisão Compiladores – AP1
Faculdade Pernambucana - FAPE Setembro/2007
Aula de SableCC Teoria e Implementação de Linguagens Computacionais (Compiladores) - IF688 – Artur Ribeiro de Aquino – ara Allan Jefferson – ajss.
COMPILADORES 04 Prof. Marcos.
Um Tradutor Dirigido por Sintaxe Simples
Semântica de Linguagens de Programação
JavaCC.
Sintaxe de uma Linguagem
PLP – JavaCC Java Compiler Compiler
Teoria e Implementação de Linguagens Computacionais Revisão 1º EE André Ricardo Schäffer Lopes – Rodrigo Diego Melo Amorim–
Analisador sintático: Tipos de análises sintáticas
1 CIn / UFPE Algoritmos de Parsing Gustavo Carvalho Março 2011.
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.
Análise Contextual Mauro Araújo Teoria e Implementação de Linguagens Computacionais - IF688 Centro de Informática – CIn Universidade Federal de Pernambuco.
Transcrição da apresentação:

Análise Léxica e Sintática Teoria e Implementação de Linguagens Computacionais - IF688 – 2007.1

Roteiro Fases da compilação Analise Lexica Tokens, lexemas, expressões regulares e autômatos finitos Analise Sintática Gramáticas e parsers Parser trees Derivações Gramáticas ambíguas Ambigüidade aritméticas Parser recursive descendent Recursão à esquerda Gramáticas LL(k) Gramáticas LR(k) Outras gramáticas Dangling else Parsing LR de gramáticas ambíguas AST Referências

Atenção! Este material não substitui a leitura da bibliografia Sugerimos pesquisar a leitura referenciada no final deste trabalho e no site da disciplina

Processo de Compilação begin if x = 5 then ... output 1100111 0011100011 + params Programa Código Fonte Compilador

Árvore sintática abstrata Fases da compilação Código fonte Análise Léxica tokens e lexemas implementação abstração Árvore sintática abstrata Análise Sintática Análise Semântica AST decorada Código Máquina Geração de Código

Background Acadêmico - CIn IP Lógica Teórica

Análise Léxica O analisador léxico é responsável por traduzir o arquivo fonte em lexemas e tokens if (n == 0) { return 1; } else { ... } if LPAR "n" id assign "0" intLit RPAR LCUR return "1" intLit comm RCUR else ...

Reconhecendo tokens Expressões regulares (implementadas como Autômatos Finitos) são comumente utilizadas Exemplos: if IF [a-z][a-z0-9]* ID [0-9]+ NUM

Reconhecendo tokens 1 2 a-z 0-9 ID 2 1 3 i f IF

Análise Sintática int y = 0,k = 0; int x = y+++k; “syn-tax: the way in wich words are put together to form phrases, clauses or setences.” Webster´s Dictionary A seguinte construção é válida? int y = 0,k = 0; int x = y+++k;

Análise Sintática O Analisador Sintático é responsável por verificar quando uma sentença faz parte da gramática da linguagem. Entrada: lexemas e tokens gerados pelo analisador léxico

Gramáticas – descrevendo linguagens Gramáticas livres de contexto são utilizadas para descrever linguagens de programação Produções Símbolos terminais Símbolos não-terminais Símbolo inicial

Exemplo S → S ; S S → id := E S → print (L) E → id E → num E → E + E E → (S , E) L → E L → L , E Terminais: id print , + ; := ( ) Não terminas: S E L Símbolo inicial: S → é utilizado na notação de produções A cadeia seguinte pertence à gramática? a := 7; b := c + (d := 5 + 6, d)

Derivações S S ; S S ; id := E id := E ; id := E id := num ; id := E Para determinar se uma cadeia pertence à gramática pode ser utilizado o processo de Derivação: S S ; S S ; id := E id := E ; id := E id := num ; id := E id := num ; id := E + E id := num ; id := E + (S, E) id := num ; id := id + (S, E) id := num ; id := id + (id := E, E) id := num ; id := id + (id := E + E, E) id := num ; id := id + (id := E + E, id) id := num ; id := id + (id := num + E, id) id := num ; id := id + (id := num + num, id)

Parse tree S S S ; id := E E id := num + E E ( S , E ) id A Parse Tree é construída conectando cada derivação a sua origem. Na prática não é implementada pelos compiladores. id id := E E + E num num

Gramáticas ambíguas Uma gramática é ambígua se a partir dela uma sentença pode dar origem a duas arvores de parsing diferentes Indeterminismo é problemático para a compilação Eliminação de ambigüidade é quase sempre possível Refatoração da gramática

Gramáticas ambíguas x := 1 + 2 + 3; S S E E id := id := E + E E + E num E + E num E + E num num num num

Gramática refatorada S → S ; S S → id := E S → print (L) E → id E → num E → E + E E → (S , E) L → E L → L , E S → S ; S S → id := E S → print (L) E → id E → num E → E + T E → T E → (S , E) L → E L → L , E

Parsers Utilizados para avaliar uma entrada quanto à sintaxe Podem ser Top-down Recursive-descent / LL(k) Bottom-up SRL, LR(k)

Parser Recursive descent Algoritmo baseado em previsões Também conhecido como Predictive Parsing Funções mutuamente recursivas Simples implementação Uma função para cada não-terminal Uma cláusula para cada produção Verifica o primeiro símbolo terminal para decidir qual função usar

Parser Recursive descent Desenvolvendo um recursive descent parser Cada não terminal 'X' dará origem a um método/função parseX(); Produções do tipo 'A | B' darão origem a cláusulas cases

Parser Recursive descent parseA() { accept(‘a’); parseB(); accept(‘c’); parseC(); } parseB() { case (d): parseC(); parseB(); case (c): accept(‘c’); } A ::= aBcC B ::= CB | cC C ::= da parseC() { accept(‘d’); accept(‘a’); }

Recursive descent Na prática constrói uma tabela de produções indexadas por não-terminais e terminais a c d A A::= aBcC B B::= CB B::= CA C C::= da A ::= aBcC B ::= CB | CA C ::= da

Recursive descent Vantagens Desvantagens Fácil de implementar Fácil de entender Desvantagens Performance deficiente Gramática reconhecida possui restrições Sem recursão à esquerda Deve estar fatorada

Recursive descent A ::= aBcC B ::= CB | CA C ::= da A ::= aBcC B ::= CX X ::= B | A C ::= da Gramática LL(1) a c d A A::= aBcC B B::= CX C C::= da X X::=A X::=B

Gramáticas e Parsers LL(1) Gramáticas SEM entradas duplicadas na tabela são conhecidas como LL(1) LL(1) - Left-to-right, leftmost-derivation, 1-symbol lookahead Left-to-right – direção na qual os símbolos serão examinados Leftmost-derivation – ordem pela qual os símbolos não-terminais serão expandidos 1-symbol lookahead– não mais que um símbolo será avaliado por vez Existem LL(2), LL(3),... Toda LL(1) é LL(2), toda LL(2) é LL(3),... LL(k)

LL(1) na prática - Applet http://ag-kastens.uni-paderborn.de/lehre/material/uebi/parsdemo/LL1Parser.html

Recursão à esquerda Gramáticas LL(1) são vulneráveis às entradas duplicadas. Por exemplo, o fragmento a seguir: E → E + T E → T O fato de E aparecer no início do lado direito da produção é a causa do problema. Isso é conhecido como Recursão à Esquerda. Para corrigir isso, vamos refatorar a gramática, com Recursão à Direita: E → T E´ E´ → +T E´ E´ →

Gramáticas e Parsers LR(1) As fraquezas de LL(k) são superadas pela técnica LR(k) LR(1) - Left-to-right, rightmost-derivation, 1-symbol lookahead Uso de uma pilha para armazenar símbolos de forma temporária Possui duas operações, shift e reduce shift: Move o primeiro símbolo para o topo da pilha reduce: escolhe uma regra da gramática do tipo X→A B C. push X da pilha e pop C B A.

Outros Parsers LR LR(0) SLR LR(1) LALR(1) Olham apenas para a pilha Melhoramento sobre o LR(0) LR(1) Lookahead de 1 símbolo Consegue descrever a maioria das linguagens de programação LALR(1) Melhoramento sobre o LR(1) Diminuí o tamanho da tabela de parsing

shift-reduce na prática - Applet http://ag-kastens.uni-paderborn.de/lehre/material/uebi/parsdemo/SRParser.html

Parsing LR de Gramáticas Ambíguas Gramáticas ambíguas ocasionam conflitos em parsers LR Shift-reduce conflict O parser não consegue decidir se empilha o próximo símbolo da entrada, ou se reduz para uma regra já disponível Reduce-reduce conflict O parser pode realizar uma redução para duas regras distintas

Parsing LR de Gramáticas Ambíguas Caso clássico: dangling-else S ::= 'if' E 'then' S 'else' S S ::= 'if' E 'then' S S ::= ...

Parsing LR de Gramáticas Ambíguas if a then { if b then s1 } else s2 ? if a then if b then s1 else s2 if a then { if b then s1 else s2 }

Parsing LR de Gramáticas Ambíguas Solução: Transformar a gramática Introdução dos conceitos de matched e unmatched S ::= 'if' E 'then' S 'else' S S ::= 'if' E 'then' S S ::= ... S ::= M | U M ::= 'if' E 'then' M 'else' M | ... U ::= 'if' E 'then' S | 'if' E 'then' M 'else' U

Gramáticas não-ambíguas Gramáticas ambíguas LR(0) LL(0) SLR LALR(1) LL(k) LL(1) Gramáticas não-ambíguas Gramáticas ambíguas LR(1) LR(k)

Sintaxe abstrata Apenas reconhecer se uma sentença pertence ou não a linguagem especificada por uma gramática não é o suficiente É necessário produzir uma estrutura que sirva de base para a próxima fase do processo de compilação Parse trees nunca são montadas na prática

AST – Abstract Syntax Tree Capturam a essência da estrutura de uma gramática abstraindo não-terminais Representação possível Java: Classes que possam se relacionar a fim de montar uma árvore Pode ser produzida através da inserção de ações semânticas no parser

AST – Abstract Syntax Tree IfThenElse ::= 'if' expr 'then' comm1 'else' comm2 return new IfThenElse(expr, comm1, comm2);

?

Referências Análises léxica e sintática, Mauro La-Salette C. L. de Araújo Modern Compiler implementation in Java, Andrew W. Appel