1 / 44

5.6 – Complementos de Yacc

5.6 – Complementos de Yacc. 5.6.1 – Usando Yacc com gramáticas ambíguas Gramáticas ambíguas causam conflitos durante a construção de um analisador sintático pelo Yacc Os tipos de conflitos são:

ceri
Download Presentation

5.6 – Complementos de Yacc

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. 5.6 – Complementos de Yacc 5.6.1 – Usando Yacc com gramáticas ambíguas • Gramáticas ambíguas causam conflitos durante a construção de um analisador sintático pelo Yacc • Os tipos de conflitos são: • Deslocamento-redução: o analisador tanto pode deslocar um átomo para a pilha, como pode reduzir o topo da pilha por uma produção • Redução-redução: o analisador pode usar mais de uma produção para reduzir o topo da pilha

  2. Há regras para a solução de ambiguidades • Yaccgera analisadores mais eficientes para gramáticas ambíguas do que para gramáticas não ambíguas

  3. Exemplo 5.34: Programa para análise da seguinte gramática ambígua para cálculo de expressões: E  E + E | E - E | E * E | E / E | ( E ) | - E | num Com a seguinte precedência de operadores: • ‘*’ e ‘/’ tem precedência sobre ‘+’ e ‘-’ • Menos-unário tem precedência sobre ‘*’ e ‘/’ O programa deve calcular expressões de valor real

  4. E  E + E | E - E | E * E | E / E | ( E ) | - E | num • A gramática é ambígua pois para a sentença 5 + 8 * 3 tem duas árvores sintáticas E E E + E E * E 5 E * E E + E 3 8 3 5 8

  5. Programa com regras para eliminação de ambiguidades e comandos de escrita para mostrar as reduções feitas: %{ #include <stdio.h> #include <ctype.h> #define YYSTYPE double %} %token NUM %left '+' '-' %left '*' '/' %right MENUN %% Declarações para solução de ambiguidades

  6. line : expr '$' {printf ( "Valor: %g\n", $1); return 0;} ; expr : expr '+' expr {$$ = $1 + $3; printf ("Regra1: %g = %g + %g\n", $$, $1, $3);} | expr '-' expr {$$ = $1 - $3; printf ("Regra2: %g = %g - %g\n", $$, $1, $3);} | expr '*' expr {$$ = $1 * $3; printf ("Regra3: %g = %g * %g\n", $$, $1, $3);}

  7. Dispositivo para solução de ambiguidades | expr '/' expr {$$ = $1 / $3; printf ("Regra4: %g = %g / %g\n", $$, $1, $3);} | '(' expr ')' {$$ = $2; printf ("Regra5: %g = ( %g )\n", $$, $2);} | '-' expr%prec MENUN {$$ = -$2; printf ("Regra6: %g = - %g \n", $$, $2);} | NUM {$$ = $1; printf ("Regra7: %g = %g\n", $$, $1);} ; %%

  8. yylex () { int c; do c = getchar (); while (c == ' '); if (c == '.' || isdigit (c)) { ungetc (c, stdin); scanf ("%lf", &yylval) ; return (NUM); } return c; }

  9. A seguir, são descritas regras e dispositivos de programação do Yacc para solucionar ambiguidades • Por default, o conflito redução-redução é resolvido em favor da produção que aparece primeiro na lista de produções • Por default, o conflito deslocamento-redução é resolvido em favor do deslocamento

  10. No exemplo anterior, não fosse pelas regras de precedência a serem comentadas logo a seguir, a forma sentencial: provocaria o deslocamento do ‘+’ para o topo da pilha • A soma seria realizada antes da multiplicação

  11. Nas declarações do programa Yacc, pode-se atribuir precedências e associatividades aos terminais da gramática; sejam as declarações: %left '+' '-' %left '*' '/' %right '~' (menos unário) • '+' e '-' têm mesma precedência • '*' e '/' têm mesma precedência • A precedência cresce de cima para baixo • No programa aparece: %right MENUN provocaria o deslocamento do ‘+’ para o topo da pilha A soma seria realizada antes da multiplicação Diferentes

  12. Cada produção em Yacc também tem associada a si uma precedência e uma associatividade: • Por default, é a precedência e associatividade de seu terminal mais a direita • Exemplo: a precedência e associatividade da produção A  a B c D e F G será a de ‘e’ • Na decisão (deslocar ‘a’) ou (reduzir por A) haverá deslocamento se ‘a’ tiver maior precedência que A, e vice-versa

  13. Na forma sentencial: haverá redução, pois a produção expr ‘*’ exprtem a precedência de ‘*’ que é maior que a de ‘+’

  14. Na declaração %left ‘-’, o operador ‘-’ é associativo à esquerda; a seguinte forma sentencial causa redução: • A expressão 5-3-1 = 2-1 = 1 • Se fosse %right ‘-’, causaria deslocamento • O cálculo de 5-3-1 seria 5-3-1 = 5-2 = 3

  15. Pode-se também forçar uma produção a ter uma determinada precedência • O programa visto apresenta: %left '+' '-' %left '*' '/' %right MENUN - - - - - - - - expr | '-' expr%prec MENUN • Esta produção é forçada a ter precedência maior que ‘+’, ‘-’, ‘*’, ‘/’

  16. 1) Entrada: 5-2-2$ Regra7: 5 = 5 Regra7: 2 = 2 Regra2: 3 = 5 - 2 Regra7: 2 = 2 Regra2: 1 = 3 - 2 Valor: 1 2) Trocando %left '+' '-' por %right '+' '-': Entrada: 5-2-2$ Regra7: 5 = 5 Regra7: 2 = 2 Regra7: 2 = 2 Regra2: 0 = 2 - 2 Regra2: 5 = 5 - 0 Valor: 5 • Exemplo: o programa visto produziu os seguintes resultados experimentais:

  17. 4) Entrada: -3+8$ Regra7: 3 = 3 Regra6: -3 = - 3 Regra7: 8 = 8 Regra1: 5 = -3 + 8 Valor: 5 3) Destrocando: Entrada: 5*-(3+2)$ Regra7: 5 = 5 Regra7: 3 = 3 Regra7: 2 = 2 Regra1: 5 = 3 + 2 Regra5: 5 = ( 5 ) Regra6: -5 = - 5 Regra3: -25 = 5 * -5 Valor: -25 • Exemplo: o programa visto produziu os seguintes resultados experimentais: 5) Trocando %right MENUN %left '+' '-' %left '*' '/' Entrada: -3+8$ Regra7: 3 = 3 Regra7: 8 = 8 Regra1: 11 = 3 + 8 Regra6: -11 = - 11 Valor: -11

  18. 5.6.2 – Notificação e tratamento de erros no Yacc • Em Yacc, o tratamento de erros pode ser feito usando produçõesde erros entre as produções da gramática • Primeiramente deve-se decidir quais não-terminais da gramática terão essas produções • Esses podem ser não-terminais que possuam átomos em suas produções normais, para que mensagens notificando a falta deles possam ser emitidas • Ou então outros estratégicos geradores de expressões, comandos, sub-programas, etc.

  19. Seja A um não-terminal escolhido; introduz-se, na gramática, produções da forma A error •  e  são cadeias de terminais e ou não-terminais, vazias ou não • error é uma palavra reservada do Yacc (um token especial) • Na montagem do analisador, as produções de erros são tratadas como produções normais da gramática • No entanto, quando o analisador produzido encontra um erro, a manipulação dos estados e da pilha é diferente do normal

  20. Encontrando um erro, desempilha-se símbolos e estados, até encontrar um estado no topo da pilha, cujo conjunto de itens contenha um item do tipo A . error  erro Entrada 0 Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  21. Encontrando um erro, desempilha-se símbolos e estados, até encontrar um estado no topo da pilha, cujo conjunto de itens contenha um item do tipo A . error  erro Entrada 0 Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  22. Desloca-se o átomo fictício error para o topo da pilha, como se tivesse visto um erro na entrada Estado com item do tipo A  error .  erro Entrada 0 error Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  23. Se  for vazia, reduz-se imediatamente para A e uma eventual ação semântica pode ocorrer (notificação e tratamento de erros programado) Estado com item do tipo A  error .  erro Entrada 0 error Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  24. Se  for vazia, reduz-se imediatamente para A e uma eventual ação semântica pode ocorrer (notificação e tratamento de erros programado) erro Entrada 0 A Programa analisador LR Saída Pilha Tabelas LR

  25. Se  não for vazia: erro Entrada 0 A Programa analisador LR Saída Pilha Tabelas LR

  26. redutível para  Se  não for vazia: o analisador observa os próximos símbolos de entrada, até encontrar uma sub-cadeiaredutível para  Estado com item do tipo A  error .  erro Entrada 0 error Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  27. redutível para   Essa sub-cadeia é deslocada para a pilha provocando a redução para A Estado com item do tipo A  error .  erro Entrada 0 error Programa analisador LR Estado com item do tipo A . error  Saída  Pilha Tabelas LR

  28. redutível para  Essa sub-cadeia é deslocada para a pilha provocando a redução para A O caso mais comum é o de  ser uma sequência de terminais erro Entrada 0 A Programa analisador LR Saída Pilha Tabelas LR

  29. redutível para  Também uma eventual ação semântica pode ocorrer (notificação e tratamento de erros programado) O caso mais comum é o de  ser uma sequência de terminais erro Entrada 0 A Programa analisador LR Saída Pilha Tabelas LR

  30. O analisador deixa o estado de erro e volta ao normal, através da execução de uma macro: yyerrok • O exemplo a seguir é experimental e relativamente simples: • Mostra os casos de  e  serem vazios e compostos de um e dois terminais • Mostra também o uso da macro yyerrok • A literatura (livros, Internet, etc.) apresenta outros dispositivos para recuperação de erros no Yacc

  31. Exemplo: programa para a seguinte gramática: Função : Cabeçalho Declarações Cabeçalho : ID ( ) Declarações : { ListDecl } ListDecl : ε | ListDeclDeclaração Declaração : TipoListElemDecl ; Tipo : INT | FLOAT | CHAR | BOOL ListElemDecl : ElemDecl | ListElemDecl , ElemDecl ElemDecl : ID

  32. Analisador léxico: delim [ \t\n\r] ws {delim}+ letra [A-Za-z] digito [0-9] id {letra}({letra}|{digito})* %% {ws} { ;} bool {return BOOL;} char {return CHAR;} float {return FLOAT;} int {return INT;} {id} {strcpy (yylval.cadeia, yytext); return ID;} "(" {return ABPAR;} ")" {return FPAR;} "{" {return ABCHAV;} "}" {return FCHAV;} ";" {return PVIRG;} "," {return VIRG;} . {yylval.carac = yytext[0]; return INVAL;} %%

  33. Analisador sintático: %{ #include <string.h> #include <stdio.h> #include <stdlib.h> void Esperado (char *); %} %union { char cadeia[50]; charcarac; }

  34. %token BOOL %token CHAR %token FLOAT %token INT %token <cadeia> ID %token ABPAR %token FPAR %token ABCHAV %token FCHAV %token PVIRG %token VIRG %token <carac> INVAL %%

  35. Funcao : CabecalhoDeclaracoes ; Cabecalho : ID ABPAR {printf ("%s \( ", $1);} FPAR {printf (")\n");} | ID error {printf ("%s ", $1); Esperado ("(");} FPAR {yyerrok; printf (")\n");} | ID error {printf ("%s\n", $1); Esperado ("( )"); yyerrok;} | error {Esperado ("Identificador");} ABPAR FPAR {yyerrok; printf ("() ");} | ID ABPAR error {printf ("%s (\n", $1); Esperado (")"); yyerrok;} ;

  36. Declaracoes : ABCHAV {printf ("\{\n");} ListDecl FCHAV {printf ("}\n");} ; ListDecl : | ListDeclDeclaracao ; Declaracao : Tipo ListElemDecl PVIRG {printf ("; \n");} | Tipo ListElemDecl error PVIRG {Esperado("';' "); yyerrok;} ;

  37. Tipo : INT {printf ("int ");} | FLOAT {printf ("float ");} | CHAR {printf ("char ");} | BOOL {printf ("bool ");} ; ListElemDecl : ElemDecl | ListElemDecl VIRG {printf (", ");} ElemDecl ; ElemDecl : ID {printf ("%s ", $1);} | error ID {Esperado("Identificador"); yyerrok;} ;

  38. %% #include "lex.yy.c" void Esperado (char *s) { printf ("\n***** Esperado: %s \n", s); } • A seguir alguns testese seus resultados

  39. Resultado: main ( ) { int i , j , k , fat ; bool m , n ; float x ; char a ; } 1) Programa para teste: (sem erros) main ( ) { inti, j, k, fat; bool m, n; float x; char a; }

  40. Resultado: syntax error ***** Esperado: Identificador () { int i , j , k , fat ; bool m , n ; float x ; char a ; } 2) Programa para teste: ( ) { inti, j, k, fat; bool m, n; float x; char a; }

  41. Resultado: syntax error abc ***** Esperado: ( ) { int i , j , k , fat ; bool m , n ; float x ; char a ; } 3) Programa para teste: abc ) { inti, j, k, fat; bool m, n; float x; char a; }

  42. Resultado: syntax error abc ( ***** Esperado: ) { int i , j , k , fat ; bool m , n ; float x ; char a ; } 4) Programa para teste: abc ( { inti, j, k, fat; bool m, n; float x; char a; }

  43. Resultado: syntax error abc ***** Esperado: ( ) { int i , j , k , fat ; bool m , n ; float x ; char a ; } 5) Programa para teste: abc { inti, j, k, fat; bool m, n; float x; char a; }

  44. Resultado: abc ( ) { int syntax error ***** Esperado: Identificador , j , k , fat ; bool m , n syntax error ***** Esperado: ';' char a ; } 6) Programa para teste: abc ( ) { intbooli, j, k, fat; bool m, n float x; char a; }

More Related