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

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

5.6 – Complementos de Yacc – Usando Yacc com gramáticas ambíguas

Apresentações semelhantes


Apresentação em tema: "5.6 – Complementos de Yacc – Usando Yacc com gramáticas ambíguas"— Transcrição da apresentação:

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
Yacc gera 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 * 3 tem duas árvores sintáticas E + 5 * 8 3 E * + 3 5 8

5 #include <stdio.h> #include <ctype.h>
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 printf ("Regra4: %g = %g / %g\n", $$, $1, $3);} | '(' expr ')'
| 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);} ; %% Dispositivo para solução de ambiguidades

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 Pilha Entrada expr ‘*’ expr ‘+’ 3

11 provocaria o deslocamento do ‘+’ para o topo da pilha
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 ‘*’ expr tem a precedência de ‘*’ que é maior que a de ‘+’ Pilha Entrada expr ‘*’ expr ‘+’ 3

14 Na declaração %left ‘-’, o operador ‘-’ é associativo à esquerda; a seguinte forma sentencial causa redução: A expressão = = 1 Se fosse %right ‘-’, causaria deslocamento O cálculo de seria = = 3 Pilha Entrada expr ‘-’ expr ‘-’ 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 Exemplo: o programa visto produziu os seguintes resultados experimentais:
1) Entrada: 5-2-2$ Regra7: 5 = 5 Regra7: 2 = 2 Regra2: 3 = 5 - 2 Regra2: 1 = 3 - 2 Valor: 1 2) Trocando %left '+' '-' por %right '+' '-': Entrada: 5-2-2$ Regra7: 5 = 5 Regra7: 2 = 2 Regra2: 0 = 2 - 2 Regra2: 5 = 5 - 0 Valor: 5

17 Exemplo: o programa visto produziu os seguintes resultados experimentais:
4) Entrada: -3+8$ Regra7: 3 = 3 Regra6: -3 = - 3 Regra7: 8 = 8 Regra1: 5 = 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 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ções de 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 Programa analisador LR
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 Programa analisador LR Estado com item do tipo A  . error  Saída Pilha Tabelas LR

21 Programa analisador LR
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 Programa analisador LR Estado com item do tipo A  . error  Saída Pilha Tabelas LR

22 Programa analisador LR
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 error Programa analisador LR Estado com item do tipo A  . error  Saída Pilha Tabelas LR

23 Programa analisador LR
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 error Programa analisador LR Estado com item do tipo A  . error  Saída Pilha Tabelas LR

24 Programa analisador LR
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 Programa analisador LR A Saída Pilha Tabelas LR

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

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

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

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

29 Programa analisador LR
Também uma eventual ação semântica pode ocorrer (notificação e tratamento de erros programado) redutível para  O caso mais comum é o de  ser uma sequência de terminais erro Entrada Programa analisador LR A 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 Função : Cabeçalho Declarações
Exemplo: programa para a seguinte gramática: Função : Cabeçalho Declarações Cabeçalho : ID ( ) Declarações : { ListDecl } ListDecl : ε | ListDecl Declaração Declaração : Tipo ListElemDecl ; 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]; char carac; }

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 : Cabecalho Declaracoes
; 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 : | ListDecl Declaracao 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 testes e seus resultados

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

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

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

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

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

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


Carregar ppt "5.6 – Complementos de Yacc – Usando Yacc com gramáticas ambíguas"

Apresentações semelhantes


Anúncios Google