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

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

CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc.

Apresentações semelhantes


Apresentação em tema: "CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc."— Transcrição da apresentação:

1 CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc

2 Yacc é um gerador de analisadores sintáticos: Têm como entrada a gramática livre de contexto da linguagem-fonte do compilador e implementa uma função de nome yyparse, que responde se o programa analisado tem ou não erros sintáticos Têm como entrada a gramática livre de contexto da linguagem-fonte do compilador e implementa uma função de nome yyparse, que responde se o programa analisado tem ou não erros sintáticos Yacc (Yet Another Compiler-Compiler) do sistema UNIX também possui diversas versões para o sistema DOS (o Yacc do Mingw é uma delas) Yacc (Yet Another Compiler-Compiler) do sistema UNIX também possui diversas versões para o sistema DOS (o Yacc do Mingw é uma delas) O analisador gerado é um programa em Linguagem C O analisador gerado é um programa em Linguagem C

3 Programa 2.1: Saída de dados Criar na pasta MinGW/bin um arquivo extensão.y (saida.y, por exemplo) com o seguinte programa: Criar na pasta MinGW/bin um arquivo extensão.y (saida.y, por exemplo) com o seguinte programa:% prod:{printf ("hello friends!\n");} ;% yylex () { return 0; } Executar os seguintes comandos: Executar os seguintes comandos: yacc saida.y gcc y.tab.c main.c yyerror.c -o saida -lfl saida Colocar pelo menos uma produção Não pode haver função main Tem de haver função yylex

4 % prod:{printf ("hello friends!\n");} ;% yylex () { return 0; } Executar: saida > ppp Executar: saida > ppp Abrir o arquivo ppp (No DOS: more ppp) Abrir o arquivo ppp (No DOS: more ppp) Abrir o arquivo main.c (só executa yyparse e retorna) Abrir o arquivo main.c (só executa yyparse e retorna) yyparse é o analisador sintático produzido pelo Yacc yyparse é o analisador sintático produzido pelo Yacc Abrir o arquivo y.tab.c e localizar yylex, prod e o printf acima Abrir o arquivo y.tab.c e localizar yylex, prod e o printf acima

5 Estrutura de um programa em Yacc: Tal como em Lex, um programa em Yacc é dividido em três partes, a saber: Tal como em Lex, um programa em Yacc é dividido em três partes, a saber: Declarações Declarações % % % % Produções da gramática Produções da gramática % % % % Rotinas auxiliares Rotinas auxiliares

6 Produções da gramática: É a parte principal de um programa em Yacc É a parte principal de um programa em Yacc O programa deve conter pelo menos uma produção O programa deve conter pelo menos uma produção As produções podem vir acompanhadas de ações escritas na Linguagem C, inseridas em qualquer posição de seu lado direito As produções podem vir acompanhadas de ações escritas na Linguagem C, inseridas em qualquer posição de seu lado direito

7 Produções da gramática: : Sejam as produções: Exemplo: Sejam as produções: Expr  Expr OPAD Termo | Termo Termo  ID | CTE Em Yacc, com ações opcionais: Em Yacc, com ações opcionais: expr:expr OPAD {comandos em C} termo |{comandos em C} termo ; termo:ID {comandos em C} |CTE {comandos em C} ;

8 Produções da gramática: Ações podem aparecer no lado direito de uma produção vazia Ações podem aparecer no lado direito de uma produção vazia Exemplo: Exemplo: yyy: {comandos em C} | xxx {comandos em C} zzz ; A primeira produção de yyy é vazia

9 Declarações: Nelas estão inclusas: Em C, delimitadas por %{ e %}: Em C, delimitadas por %{ e %}: - Declarações de variáveis, tipos, protótipos, etc. - Definições de constantes e macros (define’s) - Inclusão de arquivos sem definição de funções Declarações do Yacc (fora de %{ e %}) usadas para definir terminais, não-terminais, precedência de operadores, tipos dos atributos, etc. Declarações do Yacc (fora de %{ e %}) usadas para definir terminais, não-terminais, precedência de operadores, tipos dos atributos, etc.

10 Declarações: Exemplo: para as produções anteriores Exemplo: para as produções anteriores expr:expr OPAD {comandos em C} termo |{comandos em C} termo ; termo:ID {comandos em C} |CTE {comandos em C} ; os átomos são assim declarados: %token OPAD %token ID %token CTE

11 Rotinas auxiliares: São definições de funções em C, referenciadas nas ações das produções da gramática São definições de funções em C, referenciadas nas ações das produções da gramática Podem trazer a inclusão de arquivos com extensão.c; por exemplo, o arquivo lex.yy.c, do Flex Podem trazer a inclusão de arquivos com extensão.c; por exemplo, o arquivo lex.yy.c, do Flex Não devem conter a função main, pois essa já vem inclusa no ambiente da ferramenta Não devem conter a função main, pois essa já vem inclusa no ambiente da ferramenta Devem incluir a função yylex; quando usado com Flex, essa função já vem contida no arquivo lex.yy.c Devem incluir a função yylex; quando usado com Flex, essa função já vem contida no arquivo lex.yy.c

12 % prod : {printf ("hello friends!\n");} ;% yylex () { return 0; return 0;} Fazer yylex retornar algo diferente de zero Fazer yylex retornar algo diferente de zero Colocar um return dentro da ação depois do printf Colocar um return dentro da ação depois do printf Retomando o programa saida.y return 50; prod : {printf ("hello friends!\n"); return;}

13 % prod : {printf ("hello friends!\n");} ;% yylex () { return 0; return 0;} O analisador gerado pelo Yacc é bottom-up O analisador gerado pelo Yacc é bottom-up Vai detectando lados direitos de produções e reduzindo-os para seus lados esquerdos Vai detectando lados direitos de produções e reduzindo-os para seus lados esquerdos Tudo acaba bem quando se consegue chegar ao símbolo inicial Tudo acaba bem quando se consegue chegar ao símbolo inicial Explicando os fatos

14 % prod : {printf ("hello friends!\n");} ;% yylex () { return 0; return 0;} A única produção desta gramática (prod) é vazia A única produção desta gramática (prod) é vazia Antes de yyparse pedir um átomo para yylex, ele casa a falta de átomo em suas mãos com seu lado direito Antes de yyparse pedir um átomo para yylex, ele casa a falta de átomo em suas mãos com seu lado direito yyparse faz a redução para o lado esquerdo e executa a ação no final da produção yyparse faz a redução para o lado esquerdo e executa a ação no final da produção Chegou ao símbolo inicial Chegou ao símbolo inicial Explicando os fatos

15 % prod : {printf ("hello friends!\n");} ;% yylex () { return 0; return 0;} Em seguida, chama yylex que lhe retorna zero Em seguida, chama yylex que lhe retorna zero Recebendo zero, ele aceita e retorna Recebendo zero, ele aceita e retorna main então se encerra main então se encerra Explicando os fatos

16 % prod : {printf ("hello friends!\n");} ;% yylex () { return 50; return 50;} Depois de chegar ao símbolo inicial, yyparse só aceita o átomo zero Depois de chegar ao símbolo inicial, yyparse só aceita o átomo zero Se yylex lhe retornar algo diferente de zero, ele rejeitará Se yylex lhe retornar algo diferente de zero, ele rejeitará Com o return dentro da ação, yyparse retorna para main antes de chamar yylex Com o return dentro da ação, yyparse retorna para main antes de chamar yylex Explicando os fatos prod : {printf ("hello friends!\n"); return;}

17 Programa 2.2: Entrada de dados Criar um arquivo extensão.y (entra.y, por exemplo) com o seguinte programa: Criar um arquivo extensão.y (entra.y, por exemplo) com o seguinte programa:% ppp:{int i, n; printf ("Digite o numero de repeticoes: "); scanf ("%d", &n); for (i = 1; i <= n; i++) printf ("\nhello friends!"); };% yylex () {return 0;}

18 Executar os seguintes comandos: Executar os seguintes comandos: yacc entra.y gcc y.tab.c yyerror.c main.c -o entra -lfl entra Criar um arquivo entra.dat, colocando nele o número 10 Criar um arquivo entra.dat, colocando nele o número 10 Executar os comandos: Executar os comandos: entra < entra.dat entra ppp Abrir o arquivo ppp Abrir o arquivo ppp

19 Esquema de produção de um programa executável usando Yacc, sem auxilio do Flex:

20 Programa 2.3: Reconhecimento de frase Rodar yacc e gcc para um arquivo recfrase.y com o seguinte programa: Rodar yacc e gcc para um arquivo recfrase.y com o seguinte programa:% prod :'C' 'O' 'M' 'P' ' ' '1' '5' {printf ("Reconheco!\n"); return;} ;% yylex () { return getchar (); } Executar recfrase com: COMP 14 COMP 15 COMP 16 COMP 153 O lado direito das produções tem apenas terminais (tokens) Um caractere entre apóstrofos é considerado um token

21 Programa 2.3: Reconhecimento de frase Rodar yacc e gcc para um arquivo recfrase.y com o seguinte programa: Rodar yacc e gcc para um arquivo recfrase.y com o seguinte programa:% prod :'C' 'O' 'M' 'P' ' ' '1' '5' {printf ("Reconheco!\n"); return;} ;% yylex () { return getchar (); } Executar recfrase com: COMP 14 COMP 15 COMP 16 COMP 153 Executar com arquivo de dados (recfrase.dat, por exemplo): uma frase de cada vez Executar: recfrase ppp

22 Programa 2.4: Gramática S → ε | a S b %token a %token b %token dolar %token erro % SS:S dolar {printf ("Fim da analise\n"); return;} ; S:S:S:S: | a S b ;% yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == 'a') return a; if (x == 'b') return b; if (x == '$') return dolar; return erro; } Rodar para várias cadeias, uma por vez: aabb$ $ aaabbb$ a$ b$ aaabb$ aabbb$ aba$ ba$ Rodar com arquivo de dados contendo: aabb$ Experimente tirar o return; sem e com arquivo de dados Tokens são convertidos em defines pelo Yacc

23 Programa 2.4: Gramática S → ε | a S b %token a %token b %token dolar %token erro % SS:S dolar {printf ("Fim da analise\n"); return;} ; S: | a S b ;% yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == 'a') return a; if (x == 'b') return b; if (x == '$') return dolar; return erro; } Experimente tirar o return; sem e com arquivo de dados yylex só retorna quando um caractere é digitado e nunca retorna zero Com fim de arquivo, yylex retorna erro Chegando ao símbolo inicial, yyparse sempre chama yylex, esperando zero

24 Exercício 2.1: Escrever em Yacc, um analisador sintático para a seguinte gramática geradora da linguagem L abaixo: L = { (a b) n c n (d d) * | n  1 } Gramática: S  a b A c D A  a b A c | ε D  d d D | ε

25 Exercício 2.2: Escrever em Yacc, um analisador sintático para a seguinte gramática geradora da linguagem L abaixo: L = { a i b j | j  i  0 } Gramática: S  A B A  a A b | ε B  b B | ε

26 Exercício 2.3: Escrever em Yacc, um analisador sintático para a seguinte gramática geradora de expressões contendo só pares de parêntesis balanceados e nenhum outro caractere Exemplos: ( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ( ) ) Gramática: S  ( A ) | S ( A ) A  ε | S

27 Programa 2.5: Yacc auxiliado por Lex Programa em Flex no arquivo expr01.l Programa em Flex no arquivo expr01.l delim[ \t\n\r] ws{delim}+ digit[0-9] num{digit}+ % {ws}{ ;} {num}{return CTE;} "+"{return OPAD;} "-"{return OPAD;} "*"{return OPMULT;} "/"{return OPMULT;} "("{return ABPAR;} ")"{return FPAR;} "$"{return DOLAR;}.{return INVAL;} % yylex retorna tokens declarados no programa em Yacc

28 Programa em Yacc no arquivo expr01.y Programa em Yacc no arquivo expr01.y%{ #include #include %} %tokenDOLAR %tokenCTE %tokenOPAD %tokenOPMULT %tokenABPAR %tokenFPAR %tokenINVAL % Tokens a serem retornados por yylex

29 line:expr DOLAR {printf("Fim da analise\n"); return;} ; expr:exprOPADterm |term ; term:termOPMULT fat |fat ; fat:CTE |ABPAR expr FPAR ;% #include "lex.yy.c" yylex está em lex.yy.c Tokens aparecem do lado direito das produções

30 Executar os seguintes comandos: Executar os seguintes comandos: flex expr01.l yacc expr01.y gcc y.tab.c main.c yyerror.c -o expr01 -lfl expr01 (digitar uma expressão correta terminada por ‘$’) expr01 (digitar uma expressão incorreta terminada por ‘$’) Usando arquivo de dados de entrada, yylex retorna zero ao ler fim de arquivo, quando criado pelo Flex Usando arquivo de dados de entrada, yylex retorna zero ao ler fim de arquivo, quando criado pelo Flex Então, dispensa-se o return da produção line Então, dispensa-se o return da produção line

31 Esquema de produção de um programa executável usando Yacc, com auxilio do Flex:

32 Programa 2.6: Uso de atributos (calculadora simples) Programa em Flex no arquivo calc01.l Programa em Flex no arquivo calc01.l delim[ \t\n\r] ws{delim}+ digit[0-9] num{digit}+ % {ws}{ ;} {num}{yylval = atoi(yytext); return CTE;} "+"{yylval = MAIS; return OPAD;} "-"{yylval = MENOS; return OPAD;} "*"{yylval = VEZES; return OPMULT;} "/"{yylval = DIV; return OPMULT;} "("{return ABPAR;} ")"{return FPAR;} "$"{return DOLAR;}.{yylval = yytext[0]; return INVAL;} % yylval guarda o atributo de um token yylval é declarado pelo Yacc

33 Programa em Yacc no arquivo calc01.y Programa em Yacc no arquivo calc01.y%{ #include #include #define MAIS1 #define MENOS2 #define VEZES3 #define DIV4 %} %tokenDOLAR %tokenCTE %tokenOPAD %tokenOPMULT %tokenABPAR %tokenFPAR %tokenINVAL % Atributos para os tokens OPAD e OPMULT Por default, yylval é inteiro

34 line:exprDOLAR{ printf("valor: %d\n", $1); }; expr:exprOPADterm { switch ($2) { case MAIS : $$ = $1 + $3; break; case MENOS : $$ = $1 - $3; break; }} |term ; Não-terminais também têm atributos Numa produção qualquer: $$ é o atributo do não-terminal do lado esquerdo $1, $2, $3... são atributos dos 1 o, 2 o, 3 o... símbolos do lado direito

35 term:termOPMULT fat { switch ($2) { case VEZES: $$ = $1 * $3; break; case DIV: $$ = $1 / $3; break; }} |fat ; fat:CTE |ABPAR expr FPAR {$$ = $2;} ;% #include "lex.yy.c" O atributo de um terminal é fornecido por yylex, em yylval Os atributos dos não-terminais devem ser calculados nas ações Por default, a ação tomada no final de uma produção é: $$ = $1; Rodar o executável para um arquivo com a expressão 10 * (5 + 3)$

36 No Yacc, a análise é bottom-up (por deslocamento e redução) No Yacc, a análise é bottom-up (por deslocamento e redução) Os átomos são obtidos e deslocados para uma pilha (deslocamento) Os átomos são obtidos e deslocados para uma pilha (deslocamento) Quando no topo da pilha se formar o lado-direito de uma produção, tem-se uma ocasião para reduzir Quando no topo da pilha se formar o lado-direito de uma produção, tem-se uma ocasião para reduzir O analisador verifica se a redução é válida O analisador verifica se a redução é válida  Isso será estudado no tópico sobre Análise Bottom-Up do capítulo sobre Análise Sintática Em caso positivo, substitui, na pilha, o lado-direito pelo lado-esquerdo da produção (redução) Em caso positivo, substitui, na pilha, o lado-direito pelo lado-esquerdo da produção (redução) Então, a ação no final da produção é executada Então, a ação no final da produção é executada

37 PilhaEntradaOperaçãoAção #10*(5+3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

38 PilhaEntradaOperaçãoAção #10*(5+3)$#d Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

39 PilhaEntradaOperaçãoAção #C 10 *(5+3)$# *(5+3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

40 PilhaEntradaOperaçãoAção #C 10 *(5+3)$# *(5+3)$# r: F → C $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

41 PilhaEntradaOperaçãoAção #F 10 *(5+3)$# *(5+3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

42 PilhaEntradaOperaçãoAção #F 10 *(5+3)$# *(5+3)$# r: T → F $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

43 PilhaEntradaOperaçãoAção #T 10 *(5+3)$# *(5+3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

44 PilhaEntradaOperaçãoAção #T 10 *(5+3)$# *(5+3)$# d d d Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR E → T ? Por que não reduz segundo E → T ? A resposta virá no estudo de Análise Bottom-Up

45 PilhaEntradaOperaçãoAção #T 10 *(C 5 +3)$# +3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

46 PilhaEntradaOperaçãoAção #T 10 *(C 5 +3)$# +3)$# r: F → C $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

47 PilhaEntradaOperaçãoAção #T 10 *(F 5 +3)$# +3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

48 PilhaEntradaOperaçãoAção #T 10 *(F 5 +3)$# +3)$# r: T → F $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

49 PilhaEntradaOperaçãoAção #T 10 *(T 5 +3)$# +3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

50 PilhaEntradaOperaçãoAção #T 10 *(T 5 +3)$# +3)$# r: E → T $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

51 PilhaEntradaOperaçãoAção #T 10 *(E 5 +3)$# +3)$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

52 PilhaEntradaOperaçãoAção #T 10 *(E 5 +3)$# +3)$# d d Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

53 PilhaEntradaOperaçãoAção #T 10 *(E 5 +C 3 )$# )$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

54 PilhaEntradaOperaçãoAção #T 10 *(E 5 +C 3 )$# )$# r: F → C $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

55 PilhaEntradaOperaçãoAção #T 10 *(E 5 +F 3 )$# )$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

56 PilhaEntradaOperaçãoAção #T 10 *(E 5 +F 3 )$# )$# r: T → F $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

57 PilhaEntradaOperaçãoAção #T 10 *(E 5 +T 3 )$# )$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

58 PilhaEntradaOperaçãoAção #T 10 *(E 5 +T 3 )$# )$# r: E → E+T $$ = $1+$3 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

59 PilhaEntradaOperaçãoAção #T 10 *(E 8 )$# )$# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

60 PilhaEntradaOperaçãoAção #T 10 *(E 8 )$# )$#d Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

61 PilhaEntradaOperaçãoAção #T 10 *(E 8 ) $# $# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

62 PilhaEntradaOperaçãoAção #T 10 *(E 8 ) $# $# r: F → (E) $$ = $2 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

63 PilhaEntradaOperaçãoAção #T 10 *F 8 $# $# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

64 PilhaEntradaOperaçãoAção #T 10 *F 8 $# $# r: T → T*F $$ = $1*$3 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

65 PilhaEntradaOperaçãoAção #T 80 $# $# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

66 PilhaEntradaOperaçãoAção #T 80 $# $# r: E → T $$ = $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

67 PilhaEntradaOperaçãoAção #E 80 $# $# Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

68 PilhaEntradaOperaçãoAção #E 80 $# $#d Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

69 PilhaEntradaOperaçãoAção #E 80 $ # Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

70 PilhaEntradaOperaçãoAção #E 80 $ # r: L → E$ Imprimir $1 Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR

71 PilhaEntradaOperaçãoAção #L # Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR Escrito no vídeo: valor 80

72 PilhaEntradaOperaçãoAção #L #aceitar Análise e cálculo da expressão 10 * (5 + 3)$ Análise e cálculo da expressão 10 * (5 + 3)$ line:expr DOLAR expr:expr OPAD term | term term:term OPMULT fat | fat fat:CTE | ABPAR exprFPAR Escrito no vídeo: valor 80

73 Árvore sintática de 10*(5+3)$ com atributos:

74 Programa 2.7: Alteração no tipo dos atributos Programa em Flex no arquivo calc02.l: Programa em Flex no arquivo calc02.l: delim[ \t\n] ws{delim}+ digit[0-9] cte{digit}+(\.{digit}*)? % {ws}{ ;} {cte}{yylval = atof(yytext); return CTE;} "+"{return MAIS;} "*"{return VEZES;} "("{return ABPAR;} ")"{return FPAR;} "$"{return DOLAR;} % Para simplificar: Expressões somente com somas e multiplicações

75 Programa em Yacc no arquivo calc02.y Programa em Yacc no arquivo calc02.y%{ #include #include #define YYSTYPE float %} %tokenDOLAR %tokenCTE %tokenMAIS %tokenVEZES %tokenABPAR %tokenFPAR % Alteração no tipo de yylval e dos atributos dos não- terminais

76 line:exprDOLAR { printf("valor: %g\n",$1); return 0;} ; expr:exprMAISterm {$$ = $1 + $3;} |term ; term:termVEZES fat{$$ = $1 * $3;} |fat ; fat:CTE |ABPAR expr FPAR {$$ = $2;} ;% #include "lex.yy.c" Rodar o executável para um arquivo com uma expressão tal como 10.5 * (5.2 + 3.3)$

77 Programa 2.8: Atributos de tipos alternativos Programa em Flex no arquivo calc03.l Programa em Flex no arquivo calc03.l delim[ \t\n] ws{delim}+ digit[0-9] ctint{digit}+ ctfloat{digit}+\.{digit}* % Programa com constantes inteiras e reais

78 {ws}{ ;} {ctint}{yylval.valint = atoi(yytext); return CTINT;} return CTINT;} {ctfloat}{yylval.valfloat = atof(yytext); return CTFLOAT;} return CTFLOAT;} "+"{yylval.atr = MAIS; return OPAD;} "-"{yylval.atr = MENOS; return OPAD;} "*"{yylval.atr = VEZES; return OPMULT;} "/"{yylval.atr = DIV; return OPMULT;} "("{return ABPAR;} ")"{return FPAR;} "$"{return DOLAR;} % yylval não é mais declarado no programa Flex Deve ser uma union com os campos: valint, valfloat e atr Agora yylval está sendo usado como apresentado no capítulo sobre Flex

79 Programa em Yacc no arquivo calc03.y Programa em Yacc no arquivo calc03.y%{ #include #include #define MAIS1 #define MENOS2 #define VEZES3 #define DIV4 %} %union { int valint, atr; float valfloat; } Declaração da estrutura e dos campos de yylval e de outras variáveis de mesmo tipo, usadas na função yyparse Os campos da union podem ser struct’s ou até outras union’s

80 %type expr term fat %tokenDOLAR %token CTINT %token CTFLOAT %token OPAD %token OPMULT %tokenABPAR %tokenFPAR % Especificação dos atributos dos tokens e dos não- terminais %type: para os não-terminais %token: para os terminais

81 line:exprDOLAR { printf("valor: %g\n",$1); }; expr:exprOPADterm { switch ($2) { case MAIS : $$ = $1 + $3; break; case MENOS : $$ = $1 - $3; break; }} |term ; Mudança no tipo do valor a ser escrito Aqui, $1 corresponde ao campo valfloat de alguma variável de yyparse Aqui: $1, $3 e $$ correspondem ao campo valfloat $2 corresponde ao campo atr

82 term:termOPMULT fat { switch ($2) { case VEZES: $$ = $1 * $3; break; case DIV: $$ = $1 / $3; break; }} |fat ; fat:CTINT{$$ = (float)$1;} |CTFLOAT |ABPAR expr FPAR {$$ = $2;} ;% #include "lex.yy.c" Fator de conversão Rodar o executável para um arquivo com uma expressão tal como 10.5 * (5 + 3.3)$

83 Programa 2.9: Ações no início e meio das produções %{ #include #include int v, w, x, y, z; %}% A:{w = 10; $$ = 5*w;} B {$$ = 1; v = $1; y = $2;} C { x = $3; z = $4; printf ("v = %d; w = %d; x = %d; y = %c; z = %c;", v, w, x, y, z); return 0; }; B:'b' ; C:'c' ;% yylex () { char x; x = getchar (); while (x != 'b' && x != 'c') x = getchar (); yylval = x; return x; } Arquivo acaomeio.y Caracteres entre apóstrofos são tokens O tipo e o atributo são iguais

84 A:{w = 10; $$ = 5*w;} B {$$ = 1; v = $1; y = $2;} C { x = $3; z = $4; printf ("- - -", v, w, x, y, z); return 0; }; B:'b' ; C:'c' ; Ação no início ou meio de uma produção: Yacc cria uma produção vazia para um não-terminal fictício A ação fica no final dessa produção vazia Tal não-terminal fica no lugar da ação, na produção original

85 AProdução:Torna-se: A:{w = 10; $$ = 5*w;} B {$$ = 1; v = $1; y = $2;} C {x = $3; z = $4; printf printf (..., v, w, x, y, z); ("... ", v, w, x, y, z); return 0;} return 0;}; $$1:{w = 10; $$ = 5*w;} ; $$2:{$$ = 1; v = $1; y = $2;} ; A:$$1 B $$2 C { x = $3; z = $4; printf ("…", v, w, x, y, z); return 0; } ;

86 Nas produções de $$1 e $$2, $$ é o atributo do lado esquerdo Nas produções de $$1 e $$2, $$ é o atributo do lado esquerdo Na produção de $$2, $1 é o atributo de $$1 e $2 é o de B, da produção de A Na produção de $$2, $1 é o atributo de $$1 e $2 é o de B, da produção de A Na produção de A, $3 é o atributo de $$2 e $4 é o de C Na produção de A, $3 é o atributo de $$2 e $4 é o de C Cuidado com a numeração dos atributos da produção original Cuidado com a numeração dos atributos da produção original $$1:{w = 10; $$ = 5*w;} ; $$2:{$$ = 1; v = $1; y = $2;} ; A:$$1 B $$2 C { x = $3; z = $4; printf ("…", v, w, x, y, z); return 0; } ;

87 Para entrada bc: $$1:{w = 10; $$ = 5*w;} ; $$2:{$$ = 1; v = $1; y = $2;} ; A:$$1 B $$2 C { x = $3; z = $4; printf ("…", v, w, x, y, z); return 0; } ; B:'b'; C:'c'; Resultado no vídeo: v = 50; w = 10; x = 1; y = b; z = c;

88 Programa 2.10: Pretty-Printer Dada uma entrada desorganizada do tipo: { i = 1; i = { i = 1; i = i + 1; i = 0; i + 1; i = 0; {j = 0;{ j {j = 0;{ j = j + 1; a = b = j + 1; a = b - (x-3) - (x-3) + c; } i = i - + c; } i = i - 1; } } 1; } } { i = 1 ; i = i + 1 ; i = 0 ; { j = 0 ; { j = j + 1 ; a = b - ( x - 3 ) + c ; } i = i - 1 ; } Obter uma saída organizada do tipo: É necessário mudar de linha e tabular oportunamente

89 Programa em Flex no arquivo pretty2014.l Programa em Flex no arquivo pretty2014.l delim[ \t\n] ws{delim}+ digito[0-9] letra[A-Za-z] intct{digito}+ id{letra}({letra}|{digito})* % {ws}{ ;} {id}{strcpy (yylval.cadeia, yytext); return ID;} {intct}{yylval.valint = atoi(yytext); return INTCT;} "+"{yylval.atr = MAIS; return ADOP;} "-"{yylval.atr = MENOS; return ADOP;} "("{return OPPAR;} ")"{return CLPAR;} "{"{return OPBRACE;} "}"{return CLBRACE;} ";"{return SCOLON;} "="{return ASSIGN;}.{yylval.carac = yytext[0]; return INVAL;} %

90 Programa em Yacc no arquivo pretty2014.y Programa em Yacc no arquivo pretty2014.y%{ #include #include #defineMAIS7 #defineMENOS8 int tab = 0; %} %union { char cadeia[50]; int atr, valint; char carac; } tab: n o de tabulações a serem dadas por uma função de nome tabular

91 %token ID %token INTCT %token ADOP %tokenOPPAR %tokenCLPAR %tokenOPBRACE %tokenCLBRACE %tokenSCOLON %tokenASSIGN %token INVAL %

92 CompStat :OPBRACE {tabular (); printf ("\{\n"); tab++;} StatList CLBRACE {tab--; tabular (); printf ("}\n");} ; StatList:Statement |StatList Statement ; Statement :AssignStat |CompStat ; AssignStat :ID {tabular (); printf ("%s ", $1);} ASSIGN {printf ("= ");} Expression SCOLON {printf(";\n");} ; tabular: dá tantas tabulações quanto for o valor de tab Depois de todo token imprime seu texto Para alguns tokens, imprime ‘\n’

93 Expression:Term |Expression ADOP { if ($2 == MAIS) printf ("+ "); if ($2 == MAIS) printf ("+ "); else printf ("- "); } Term } Term; Term :ID {printf ("%s ", $1);} |INTCT {printf ("%d ", $1);} | OPPAR {printf("\( ");} Expression CLPAR {printf (") ");} Expression CLPAR {printf (") ");} ;% #include "lex.yy.c" tabular () { int i; for (i = 1; i <= tab; i++) printf ("\t"); printf ("\t");} Rodar o executável para um arquivo contendo o programa desorganizado ilustrativo

94 Outra forma de apresentar a gramática (com abreviaturas): Comp :‘{’ $$1 StatL ‘}’ {tab--; tabular (); write("}\n");}; StatL :Stat | StatL Stat; Stat :AsStat | Comp; AsStat :ID $$2 “=” $$3 Expr ‘;’ {write(";\n");}; Expr:Term | Expr OPAD $$4 Term; Term:ID {write($1);} | INTCT {write($1);} | ‘(’ $$5 Expr ‘)’ {write (")");}; $$1: {tabular (); write ("{\n"); tab++;} $$2: {tabular (); write ($1);} $$3: {write ( " =");} $$4: {if ($2 == MAIS) write (‘+’); else printf ( ‘-’ );} $$5: {write (‘(’);}

95 A análise bottom-up por deslocamento e redução, feita pelo Yacc, simula o caminhamento em pós-ordem, na árvore sintática de uma sentença correta A análise bottom-up por deslocamento e redução, feita pelo Yacc, simula o caminhamento em pós-ordem, na árvore sintática de uma sentença correta Isso é usado a seguir para ilustrar o resultado das ações do pretty-printer para produzir o efeito desejado Isso é usado a seguir para ilustrar o resultado das ações do pretty-printer para produzir o efeito desejado Seja a seguinte sentença bem simples: Seja a seguinte sentença bem simples: { i = 1 ; j = 2 ; } A seguir, sua árvore sintática A seguir, sua árvore sintática

96 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: Tela do vídeo tab DeslocarDeslocar vazio Reduzir: Ação: { tabular (); write ("{\n"); tab++;} 0 _{_{_ 1 Os elementos dos retângulos formam a pilha

97 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab DeslocarDeslocar vazio Reduzir: Ação: {tabular (); write ($1);} {_{_ 1 { i_

98 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab DeslocarDeslocar vazio Reduzir: Ação: {write (“=");} 1 { i_ { i =_

99 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab Deslocar Reduzir: Ação: {write ($1);} 1 { i =_ { i = 1_ Reduzir: Ação: {$$ = $1);} irrelevante

100 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab Deslocar Reduzir: Ação: {write (“;\n”);} 1 { i = 1_ Reduzir: Ação: {$$ = $1);} irrelevante { i = 1 ; _

101 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab DeslocarDeslocar vazio Reduzir: Ação: {tabular(); write ($1);} 1 { i = 1 ; _ { i = 1 ; j_

102 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab DeslocarDeslocar vazio Reduzir: Ação: {write (“=”);} 1 { i = 1 ; j_ { i = 1 ; j =_

103 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab Deslocar Reduzir: Ação: {write ($1);} 1 Reduzir: Ação: {$$ = $1);} irrelevante { i = 1 ; j =_ { i = 1 ; j = 2_

104 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab Deslocar Reduzir: Ação: {write (“;\n”);} 1 Reduzir: Ação: {$$ = $1);} irrelevante { i = 1 ; j = 2_ { i = 1 ; j = 2 ; _

105 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) Seja a pós-ordem: tab Deslocar Reduzir: Ação: {tab--; tabular(); write (“}\n”);} 1 { i = 1 ; j = 2 ; _ 0 { i = 1 ; j = 2 ; } _ Aceitar

106 Comp Comp { $$1 StatL } { $$1 StatL }  StatL Stat  StatL Stat Stat AsStat Stat AsStat AsStat ID(j) $$2 = $$3 Expr ; AsStat ID(j) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ;   Term ID(i) $$2 = $$3 Expr ;   Term   Term INTCT(2)   Term INTCT(2) INTCT(1) { i = 1 ; j = 2 ; } _ As ações no pretty- printer produziram os resultados desejados Processamento de um não-terminal: é uma redução para ele Resultado

107 Programa 2.11: Conflitos no Yacc %token a %token b %token c %token dolar %token erro % SS:S dolar {printf ("Fim da analise\n"); return;} ; S:X C | A Y ; A: /* vazia */ | A a ; X: /* vazia */ | a X b ; Y: /* vazia */ | b Y c ; C: /* vazia */ | C c ; % Arquivo conflito.y com uma gramática geradora da linguagem L = {a i b j c k | i=j ou j=k} A gramática é ambígua: Sentença aaabbbccc tem mais de uma árvore sintática

108 yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == 'a') return a; if (x == 'b') return b; if (x == 'c') return c; if (x == '$') return dolar; return erro; } Executar: yacc conflito.y Executar: yacc conflito.y Resultado: Resultado: yacc: 1 shift/reduce conflict, 1 reduce/reduce conflict. Arquivo conflito.y (continuação) O analisador gerado pelo Yacc não consegue tratar certas gramáticas Solução: Método mais geral

109 yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == 'a') return a; if (x == 'b') return b; if (x == 'c') return c; if (x == '$') return dolar; return erro; } Executar: yacc –v conflito.y Executar: yacc –v conflito.y Abrir arquivo y.output Abrir arquivo y.output Arquivo conflito.y (continuação) O analisador gerado pelo Yacc não consegue tratar certas gramáticas Solução: Método mais geral

110 Arquivo y.output : Contém um relatório da montagem do analisador Contém um relatório da montagem do analisador Conflito shift-reduce: indecisão entre deslocar o átomo para a pilha ou fazer uma redução no topo da pilha Conflito shift-reduce: indecisão entre deslocar o átomo para a pilha ou fazer uma redução no topo da pilha Conflito reduce-reduce: indecisão na escolha de uma produção para reduzir no topo da pilha Conflito reduce-reduce: indecisão na escolha de uma produção para reduzir no topo da pilha

111 Arquivo y.output - as produções são numeradas: 0 $accept : SS $end 1 SS : S dolar 2 S : X C 3 | A Y 4 A : 5 | A a 6 X : 7 | a X b 8 Y : 9 | b Y c 10 C : 11 | C c 0: shift/reduce conflict (shift 1, reduce 4) on a No estado 0 (zero – início da análise), diante de um ‘a’ na entrada, ele não sabe se o empilha e vai para o estado 1, ou se faz uma redução usando a produção 4 0: reduce/reduce conflict (reduce 4, reduce 6) on dolar No estado 0 (zero – início da análise), diante de um ‘$’ na entrada, ele não sabe se faz uma redução usando a produção 4 ou 6 Produção arfificial do Yacc

112 Há gramáticas ambíguas que têm equivalentes não ambíguas Há gramáticas ambíguas que têm equivalentes não ambíguas Exemplo: gramática S  S S | ( S ) | ε Exemplo: gramática S  S S | ( S ) | ε geradora expressões com pares de parêntesis balanceados, tais como: ( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ( ) ) Gramática equivalente: S  ε | S ( S ) Gramática equivalente: S  ε | S ( S )

113 Programa 2.12: Conflito por ações no início ou meio de produções % SS : S '$' {printf ("Fim da analise\n"); return;} ; S : | S '(' S ')' ;% yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == '\(' || x == ')' || x == '$') return x; return '#'; } Programa correto para S  ε | S ( S ) ( ) ( ( ) ( ) ) ( ( ) ) $ Rodar para: ( ) ( ( ) ( ) ) ( ( ) ) $

114 Inserindo uma ação: % SS : S '$' {printf ("Fim da analise\n"); return;} ; S : | {printf ("\nyyy");} S '(' S ')' ;% yylex () { char x; x = getchar (); while (x == ' ' || x == '\n' || x == '\t' || x == '\r') x = getchar (); printf ("Caractere lido: %c\n", x); if (x == '\(' || x == ')' || x == '$') return x; return '#'; } yacc: 1 reduce/reduce conflict.

115 Arquivo y.output : 0 $accept : SS $end 1 SS : S '$' 2 S : 3 $$1 : 4 S : $$1 S '(' S ')' O conflito é em usar a produção 2 ou 3 para reduzir diante do ‘(’ O conflito é em usar a produção 2 ou 3 para reduzir diante do ‘(’ $$1 é um não-terminal fictício $$1 é um não-terminal fictício Cada caso tem sua solução particular Cada caso tem sua solução particular Aqui, pode-se colocar a ação depois do S Aqui, pode-se colocar a ação depois do S

116 Observações finais: Apesar do conflito, o Yacc gera o analisador Apesar do conflito, o Yacc gera o analisador O problema é que os resultados produzidos podem não ser corretos O problema é que os resultados produzidos podem não ser corretos No projeto da disciplina, as produções do comando condicional irão gerar um conflito shift/reduce No projeto da disciplina, as produções do comando condicional irão gerar um conflito shift/reduce O analisador gerado resolverá o conflito de forma a obedecer à regra usual para o caso if-else O analisador gerado resolverá o conflito de forma a obedecer à regra usual para o caso if-else


Carregar ppt "CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc."

Apresentações semelhantes


Anúncios Google