1 / 41

Análise Léxica e Sintática

Análise Léxica e Sintática. Teoria e Implementação de Linguagens Computacionais - IF688 – 2007.1. 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.

dusan
Download Presentation

Análise Léxica e Sintática

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. 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 Roteiro

  3. 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

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

  5. Fases da compilação Código fonte Análise Léxica tokens e lexemas implementação abstração Árvoresintáticaabstrata Análise Sintática Análise Semântica AST decorada CódigoMáquina Geração de Código

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

  7. "n" id intLit intLit "1" "0" 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 assign RPAR LCUR return comm RCUR else ...

  8. 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

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

  10. Análise Sintática “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;

  11. 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

  12. 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

  13. 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) Exemplo

  14. Derivações 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)

  15. Parse tree S S S ; E id := 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 E id := E E + num num

  16. 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

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

  18. 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 Gramática refatorada

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

  20. 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

  21. Parser Recursive descent • Desenvolvendo um recursive descentparser • 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

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

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

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

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

  26. 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)

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

  28. 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´ →

  29. 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. pushX da pilha e popC B A.

  30. Outros Parsers LR • LR(0) • Olham apenas para a pilha • SLR • 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

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

  32. 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

  33. 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 ::= ...

  34. 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 }

  35. 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

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

  37. 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

  38. 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

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

  40. ?

  41. 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

More Related