Análises léxica e sintática Teoria e Implementação de Linguagens Computacionais - IF688 Mauro La-Salette C. L. de Araújo Centro de Informática – CIn Universidade Federal de Pernambuco – UFPE mscla@cin.ufpe.br
Roteiro Visão geral Análise léxica Análise sintática Definição Especificação Implementação Correspondência Análise sintática Algoritmos de parsing e gramáticas Gramáticas ambíguas Sintaxe abstrata
Visão Geral Código fonte Análise léxica AST Análise semântica Geração de código AST decorada Análise sintática Tokens executável
Análise Léxica
Definição Fase da compilação responsável por extrair os tokens do código fonte de um programa. if (n == 0) { return 1; } else { ... } if LPAR "n" id assign "0" intLit RPAR LCUR return "1" intLit comm RCUR else ...
Especificação Os tokens de uma linguagem comumente são especificados através de Expressões Regulares [a-z][a-z0-9]* identifier [0-9]+ intLiteral
Implementação Autômatos finitos 1 2 a-z 0-9 ID 2 1 3 i f IF
Análise Sintática
Definição Fase da compilação responsável por determinar se uma dada cadeia de entrada pertence ou não à linguagem definida por uma gramática Tem como entrada os tokens processados pela análise léxica Produz uma estrutura comumente denominada AST – abstract syntax tree
Especificação BNF - Backus-Naur form S, A, B, C, D : não-terminais A ::= C | D B ::= bba C ::= ab D ::= dab Produções BNF - Backus-Naur form S, A, B, C, D : não-terminais a,b,d: terminais
Implementação Algoritmos de parsing e gramáticas Classificação Top-down Recursive-descent / LL(1) Bottom-up LR, SLR, LALR, LR(k)
Recursive descent Algoritmo baseado em previsões Funções mutuamente recursivas Uma função para cada não-terminal
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
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 parseA() { accept(‘a’); parseB(); accept(‘c’); parseC(); } parseB() { case (d): parseC(); parseB(); case (d): parseA(); } A ::= aBcC B ::= CB | CA C ::= da parseC() { accept(‘d’); accept(‘a’); }
Recursive descent Vantagens Desvantagens Fácil de implementar Performance Gramática reconhecida possui restrições Sem recursão à esquerda Deve estar fatorada ...
Recursive descent A ::= aBC A ::= aBC B ::= CX B ::= CB | CA C ::= da A ::= aBC B ::= CX X ::= B | A C ::= da Gramática LL(1)
Gramáticas LL(1) Left-to-right parse Leftmost-derivation 1-symbol-lookahead
Gramáticas Ambíguas Uma gramática é ambígua se a partir dela uma sentença pode dar origem a duas arvores de parsing Problemáticas para a compilação Eliminação de ambigüidade é quase sempre possível Transformações na gramática
Gramáticas Ambíguas Caso clássico: gramática para expressões aritméticas E ::= intLiteral | E '*' E | E '/' E | E '+' E | E '-' E |'(' E ')'
Gramáticas Ambíguas 1 + 2 * 3 E E * + E E E E 3 1 + * E E E E 1 2 2 3
Gramáticas Ambíguas Solução: Transformar a gramática * e / com maior precedência que + ou - Operadores associativos a esquerda E ::= intLiteral | E '*' E | E '/' E | E '+' E | E '-' E |'(' E ')' E ::= E '+' T | E '–' T | T T ::= T '*' F | T '/' F | F F ::= intLiteral |'(' E ')'
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);
Análises léxica e sintática Teoria e Implementação de Linguagens Computacionais - IF688 Mauro La-Salette C. L. de Araújo Centro de Informática – CIn Universidade Federal de Pernambuco – UFPE mscla@cin.ufpe.br