A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

1 CIn / UFPE Parsing Tarciana Dias / Gustavo Carvalho / Março 2012.

Apresentações semelhantes


Apresentação em tema: "1 CIn / UFPE Parsing Tarciana Dias / Gustavo Carvalho / Março 2012."— Transcrição da apresentação:

1 1 CIn / UFPE Parsing Tarciana Dias / Gustavo Carvalho tds@cin.ufpe.brtds@cin.ufpe.br / ghpc@cin.ufpe.brghpc@cin.ufpe.br Março 2012

2 2 Roteiro Processo de Compilação Conceitos Básicos Estratégias de Parsing Gramáticas LL / Recursive Descent Algorithm Referências

3 3 Processo de Compilação Análise Léxica (Scanning) Análise Sintática (Parsing) Análise Semântica Ger. Código Intermediário Otimização Cód. Interm. Geração de CódigoOtimização do Cód. Gerado Tokens AST AST decorada Cód. Interm. Cód. Interm. OtimizadoCód. ObjetoCód. Objeto Otimizado Front-end Back-end Compilador (1 ou N passos) Erro

4 4 Processo de Interpretação Análise Léxica (Scanning) Análise Sintática (Parsing) Análise Semântica Ger. Código Intermediário Otimização Cód. Interm. Geração de CódigoOtimização do Cód. Gerado Tokens Front-end Back-end Interpretador Erro Fetch => Analyze => Execute Saídas de forma imediata Não traduz programa fonte para código objeto (a priori) Ideal (melhor desempenho): instruções com formato simplificado (bytecode) Execução

5 5 Roteiro Processo de Compilação Conceitos Básicos Estratégias de Parsing Gramáticas LL / Recursive Descent Algorithm Referências

6 6 Conceitos Básicos Gramáticas livres de contexto (GLC) –Conjunto finito de símbolos não-terminais (V) Uma classe particular de frases de uma linguagem Ex.: Programa, Expressao, Valor –Conjunto finito de símbolos terminais (Σ), disjunto de V Símbolos atômicos Ex.: ‘ 23 ’, ‘ + ’, ‘ - ‘, ‘ and ’ –Conjunto finito de regras de produção (R) –Símbolo inicial (um dos símbolos de V) (S) Ex.: Programa

7 7 Conceitos Básicos Exemplo –Terminais +, -, not, length, and, or, ==, ++, 0, …, 9, a, …, z, A, …, Z –Não-terminais Programa, Expressao, Valor, ExpUnaria, ExpBinaria, ValorConcreto, ValorInteiro, ValorBooleano, ValorString –Produções Programa ::= Expressao Expressao ::= Valor | ExpUnaria | ExpBinaria Valor ::= ValorConcreto ValorConcreto ::= ValorInteiro | ValorBooleano | ValorString ExpUnaria ::= "-" Expressao | "not" Expressao | "length" Expressao ExpBinaria ::= Expressao "+" Expressao | Expressao "-" Expressao | Expressao "and" Expressao | Expressao "or" Expressao | Expressao "==" Expressao | Expressao "++" Expressao ValorInteiro ::= [1-9] [0-9]* ValorBooleano ::= "true" | "false" ValorString ::= ([A-Za-z] | [0-9])*

8 8 Conceitos Básicos Uma árvore sintática para uma gramática G –Árvore com labels em que: As folhas são símbolos terminais Os nós são símbolos não-terminais Uma frase de G –Seqüência de terminais de uma árvore sintática (esquerda p/ direita) Exemplo: 2 + 3 (onde o todo é 2 + 3 + 5) Uma sentença –Frase cuja árvore começa a partir do símbolo inicial Exemplo: 2 + 3 (onde o todo é 2 + 3) Linguagem gerada por G: todas as sentenças de G

9 9 Conceitos Básicos Gramáticas ambíguas –Podem gerar 2 árvores distintas para a mesma expressão –Exemplo: Suponha que usemos um único não-terminal string e que não façamos distinção entre dígitos e listas: Expressão: 9 – 5 + 2 string 2 5 9 - + 5 9 + - 2 string → string + string | string – string | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 (9 – 5 ) + 2 9 – (5 + 2)

10 10 Conceitos Básicos Expressões Regulares (REs) –Notação conveniente para expressar um conjunto de strings de símbolos terminais. ‘|’ separa alternativas; ‘*’ indica que o item anterior pode ser repetido 0 ou mais vezes; ‘(’ e ‘)’ são parênteses agrupadores. Exemplos: –Mr | Ms gera {Mr, Ms} –M(r | s) gera {Mr, Ms} –ps*t gera {pt, pst, psst, pssst,...} –ba(na)* gera {ba, bana, banana, bananana,...} –M(r | s)* gera {M, Mr, Ms, Mrr, Mrs, Msr, Mss, Mrrr,...} Assim RE são capazes de gerar linguagens simples, chamadas de linguagens regulares

11 11 Conceitos Básicos No entanto, linguagens de programação completas são self- embedding –Por exemplo, as expressões representadas por LE1 ou LE2 (vistas em sala de aula), ex.: a * (b+c) / d contém outra subexpressão embedded, (b + c). –O comando if x > y then m := x else m := y contém o subcomando embedded, ‘m := x’ Portanto, self-embedding nos permitem escrever expressões complexas, comandos, etc; Uma linguagem regular, ou seja, que não exibe self-embedding pode ser representada através de REs. Já uma linguagem que exiba self-embedding não pode ser gerada por REs. Para isso, nós escrevemos regras de produção recursivas usando ou BNF ou EBNF.

12 12 Conceitos Básicos EBNF é uma combinação de BNF com REs. Uma produção EBNF é da forma N := X, onde N é um símbolo não- terminal e X é uma RE estendida, ou seja, uma RE construída a partir de ambos os símbolos terminais e não-terminais. –Diferentemente de uma BNF, o lado direito de uma produção EBNF pode usar não somente ‘|’ mas também ‘*’ além de ‘(‘ e ‘)’. –Diferentemente de uma RE ordinária, o lado direito pode conter símbolos não- terminais como também símbolos terminais. Logo, podemos escrever regras de produção recursivas, e uma EBNF é capaz de gerar uma linguagem com self-embedding.

13 13 Conceitos Básicos Exemplo de gramática expressa em EBNF: Expression ::= primary-Expression (Operator primary-Expression)* primary-Expression ::= Identifier | (Expression) Identifier ::= a | b | c | d | e Operator ::= + | - | * | / Esta gramática gera expressões como: a + b a – b – c a + (b * c) a * (b + c) / d a – (b – (c – (d - e)))

14 14 Conceitos Básicos Transformações de Gramática –Fatoração à esquerda –Ex;: XY | XZ equivale à X (Y | Z) single-Command ::= V-name := Expression | if Expression then single-Command else single-Command single-Command ::= V-name := Expression | if Expression then single-Command ( ε | else single-Command)

15 15 Conceitos Básicos Transformações de Gramática –Eliminação de recursão à esquerda N ::= X | NY, onde N é um símbolo não-terminal e X e Y são REs estendidas. Esta produção é recursiva à esquerda. N ::= X(Y)* Substituindo por uma regra EBNF equivalente

16 16 Conceitos Básicos Transformações de Gramática Identifier ::= Letter | Identifier Letter | Identifier Digit Identifier ::= Letter | Identifier (Letter | Digit) Identifier ::= Letter (Letter | Digit)* Fatorando à esquerda Eliminando recursão à esquerda

17 17 Conceitos Básicos A necessidade da eliminação de recursão à esquerda é melhor entendida depois que se vai usar a abordagem top-down;

18 18 Roteiro Processo de Compilação Conceitos Básicos Estratégias de Parsing Gramáticas LL / Recursive Descent Algorithm Referências

19 19 Estratégias de Parsing Objetivo –Reconhecimento de uma string de entrada (seqüência de tokens) e decisão se esta é ou não uma sentença de G –Determinação de sua estrutura de frases (pode ser representada por uma árvore sintática) –Gramática não ambígua: cada sentença tem exatamente uma syntax tree Top-Down –Examina os símbolos terminais da esquerda para a direita –Forma a ST (syntax tree) de cima para baixo –Parsing ok: string de entrada totalmente conectada à ST L(eft-to-right) L(eft-most-derivation) => LL Bottom-Up –Examina os símbolos terminais da esquerda para a direita –Forma a ST (syntax tree) de baixo (nós terminais) para cima(nó raiz) –Parsing ok: string de entrada reduzida a uma S-tree S(imple) L(eft-to-right) R(ight-most-derivation) => SLR L(eft-to-right) R(ight-most-derivation) => LR L(ook) A(head) L(eft-to-right) R(ight-most-derivation) => LALR

20 20 Estratégia Bottom-Up Exemplo: Sentence ::= Subject Verb Object Subject ::= I | a Noun | the Noun Object ::= me | a Noun | the Noun Noun ::= cat | mat | rat Verb ::= like | is | see | sees the cat sees a rat. Noun Subject Verb Noun Object Sentence Aqui ele não poderia ter escolhido um Subject?

21 21 Estratégia Top-Down Exemplo: Sentence ::= Subject Verb Object Subject ::= I | a Noun | the Noun Object ::= me | a Noun | the Noun Noun ::= cat | mat | rat Verb ::= like | is | see | sees the cat sees a rat. Noun Subject Verb Noun Object Sentence

22 22 Estratégias de Parsing Qual estratégia de parsing devemos usar? –Isso vai depender do tipo de gramática ! –Sempre é necessário escolher qual regra de produção aplicar Isto é feito de acordo com o algoritmo de Parsing –Recursive Descent é um algoritmo de parsing top-down –Consiste de um grupo de métodos parseN, um para cada símbolo não-terminal N de G. Estes métodos cooperam para fazer o parse das sentenças completas parseSubject parseVerbparseObject parseSentence the cat sees a rat. parseNoun

23 23 Roteiro Processo de Compilação Conceitos Básicos Estratégias de Parsing Gramáticas LL / Recursive Descent Algorithm Referências

24 24 Gramáticas LL(1) Deve-se expressar a gramática em EBNF, com uma regra de produção simples para cada símbolo não-terminal, e realizar as transformações de gramática necessárias, por exemplo, sempre eliminar recursão à esquerda e fatorizar à esquerda sempre que possível Gramáticas LL(1): –Se a gramática contém X | Y, starters[[ X ]] e starters[[ Y ]] devem ser disjuntos –Se a gramática contém X*, starters[[ X ]] deve ser disjunto do conjunto de tokens que podem seguir X* Na prática quase toda gramática de uma linguagem de programação pode ser transformada em LL(1), sem mudar a linguagem que a gramática gera Recursive-descent parsing é somente adequado para gramáticas LL(1) –Em geral, o projetista da linguagem projeta a sua sintaxe para ser adequada à um parsing recursive-descent.

25 25 Gramáticas não-LL(1) Exemplo de uma Gramáticas não LL(1): Program ::= single-Command Command ::= single-Command (; single-Command)* V-name ::= Identifier single-Command ::= V-name := Expression | Identifier ( Expression ) | if Expression then single-Command else single-Command … Expression ::= primary-Expression (Operator primary-Expression)* primary-Expression ::= Integer-Literal | Identifier …

26 26 Gramáticas não-LL(1) Desenvolvimento do método parseSingleCommand: private void parseSingleCommand(){ switch(currentToken.kind){ case Token.IDENTIFIER: { parseVname(); accept(Token.BECOMES); parseExpression(); } break; case Token.IDENTIFIER: { parseIdentifier (); accept(Token.LPAREN); parseExpression(); accept(Token.RPAREN); } break; } Uma simples fatoração à esquerda resolve o problema! … V-name ::= Identifier single-Command ::= V-name := Expression | Identifier ( Expression ) | … … single-Command ::= Identifier (:= Expression | ( Expression ) )

27 27 Gramáticas não-LL(1) Exemplo de uma Gramáticas não LL(1): Aqui, starters[[ ;Declaration ]] = {;} e o conjunto de terminais que seguem (; Declaration)* neste contexto também é {;} –Como não são disjuntos, então a gramática não é LL(1) … Block::= begin Declaration (; Declaration)* ; Command end Declaration ::= integer Identifier (, Identifier)* … private void parseBlock(){ accept(Token.BEGIN){ parseDeclaration(); while (currentToken.kind == Token.SEMICOLON) acceptIt(); parseDeclaration(); } accept(Token.SEMICOLON); parseCommand(); accept(Token.END); } … Block::= begin Declaration ; (Declaration;)* Command end … Como resolver?

28 28 Recursive Descent Parser –Algoritmo de parsing para gramáticas LL –Visão geral Para cada produção N, crie um método parseN Crie uma classe parser com um atributo currentToken –E os métodos parseN –E os métodos auxiliares: accept e acceptIt –E um método público parse que chama parseS O código de cada método parseN depende da produção N A árvore é dada implicitamente pela chamada dos métodos –Pode ser criada explicitamente

29 29 Recursive Descent Parser Programa ::= Expressao Expressao ::= ExpCondicionalOr ExpCondicionalOr ::= ExpCondicionalAnd ( ("or" ExpCondicionalAnd)* | ε)? ExpCondicionalAnd ::= ExpIgualdade ( ("and" ExpIgualdade)* | ε)? ExpIgualdade ::= ExpAritmetica ( ("==" ExpAritmetica)? | ε)? ExpAritmetica ::= ExpConcatenacao ( (("+" | "-") ExpConcatenacao)* | ε)? ExpConcatenacao ::= ExpUnaria ( ("++" ExpUnaria)* | ε)? ExpUnaria ::= "-" Expressao | "not" Expressao | "length" Expressao | ValorConcreto ValorConcreto ::= ValorInteiro | ValorBooleano | ValorString accept(int type) { if ( currentToken.getType() == type ) { currentToken = scanner.getNextToken(); } else { // ERRO } acceptIt() { currentToken = scanner.getNextToken(); } Métodos auxiliares

30 30 Recursive Descent Parser parsePrograma() parseExpressao(); } parseExpressao() { parseExpCondicionalOr(); } parseExpCondicionalOr() { parseExpCondicionalAnd(); while ( currentToken.getType() == Token.OR ) { acceptIt(); parseExpCondicionalAnd(); } parseExpIgualdade() { parseExpAritmetica(); if ( currentToken.getType() == Token.EQUAL ) { acceptIt(); parseExpAritmetica(); } Programa ::= Expressao Expressao ::= ExpCondicionalOr ExpCondicionalOr ::= ExpCondicionalAnd ( ("or" ExpCondicionalAnd)* | ε)? ExpCondicionalAnd ::= ExpIgualdade ( ("and" ExpIgualdade)* | ε)? ExpIgualdade ::= ExpAritmetica ( ("==" ExpAritmetica)? | ε)? ExpAritmetica ::= ExpConcatenacao ( (("+" | "-") ExpConcatenacao)* | ε)? ExpConcatenacao ::= ExpUnaria ( ("++" ExpUnaria)* | ε)? ExpUnaria ::= "-" Expressao | "not" Expressao | "length" Expressao | ValorConcreto ValorConcreto ::= ValorInteiro | ValorBooleano | ValorString parse () { parsePrograma(); if ( currentToken.getType() != Token.EOT ) { // ERRO }

31 31 Recursive Descent Parser parseExpUnaria() { if ( currentToken.getType() == Token.MINUS ) { acceptIt(); parseExpressao(); } else if ( currentToken.getType() == Token.NOT ) { acceptIt(); parseExpressao(); } else if ( currentToken.getType() == Token.LENGTH ) { acceptIt(); parseExpressao(); } else { parseValorConcreto(); } Programa ::= Expressao Expressao ::= ExpCondicionalOr ExpCondicionalOr ::= ExpCondicionalAnd ( ("or" ExpCondicionalAnd)* | ε)? ExpCondicionalAnd ::= ExpIgualdade ( ("and" ExpIgualdade)* | ε)? ExpIgualdade ::= ExpAritmetica ( ("==" ExpAritmetica)? | ε)? ExpAritmetica ::= ExpConcatenacao ( (("+" | "-") ExpConcatenacao)* | ε)? ExpConcatenacao ::= ExpUnaria ( ("++" ExpUnaria)* | ε)? ExpUnaria ::= "-" Expressao | "not" Expressao | "length" Expressao | ValorConcreto ValorConcreto ::= ValorInteiro | ValorBooleano | ValorString parseValorConcreto() { if ( currentToken.getType() == Token.INT ) { acceptIt(); } else if ( currentToken.getType() == Token.BOOLEAN ) { acceptIt(); } else { accept(Token.STRING); }

32 32 Roteiro Processo de Compilação Conceitos Básicos Estratégias de Parsing Gramáticas LL / Recursive Descent Algorithm Referências

33 33 Referências WATT, D.; BROWN, D. Programming Language Processors in Java. –Capítulo 4 Foco maior na abordagem LL AHO, A.; LAM, M.; SETHI, R.; ULLMAN, J. Compilers: Principles, Techniques & Tools. –Capítulo 4 Foco maior na abordagem LR

34 34 CIn / UFPE Parsing Tarciana Dias / Gustavo Carvalho tds@cin.ufpe.brtds@cin.ufpe.br / ghpc@cin.ufpe.brghpc@cin.ufpe.br Março 2012


Carregar ppt "1 CIn / UFPE Parsing Tarciana Dias / Gustavo Carvalho / Março 2012."

Apresentações semelhantes


Anúncios Google