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

Slides:



Advertisements
Apresentações semelhantes
Funções em C Prof. Fabiano Utiyama.
Advertisements

Técnicas de Programação II Revisão TP1 Parte2
Software Básico Silvio Fernandes
Capítulo II – Algoritmos e Programas
Capítulo VIII – Subprogramação
5.5 – Análise Bottom-Up Tentativa de construir uma árvore sintática para a sentença analisada, começando das folhas, indo em direção à raiz (pós-ordem.
II – Análise léxica DEI lex: linguagem de especificação para analisadores léxicos Implementação de simuladores de autómatos finitos Bibliografia aconselhada:
I - Noções dum compilador Partes dum compilador Ferramentas de construção de compiladores Bibliografia aconselhada: –Aho, Sethi e Ullman – Cap. 1 LFA 1999/2000.
III – Análise sintáctica Geradores de parsers Bibliografia aconselhada: –Aho, Sethi e Ullman – secção 4.9 LFA 1999/ Jorge Morais.
Algoritmo e Programação
Análise Sintática Ascendente ­
Universidade Federal de São Carlos Introdução à Linguagem C Comandos.
Algoritmos e Programação Linguagens de Programação Teoria Aula (09/06)
YACC.
Lex e Yacc.
Universidade Federal do Espírito Santo
Análise Léxica Supondo o trecho de programa abaixo:
Construção de Compiladores
Construção de Compiladores
Construção de Compiladores
5.6 – Complementos de Yacc – Usando Yacc com gramáticas ambíguas
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2013 Capítulo II Confecção de Tabelas.
Revisão da Linguagem C.
Técnicas de Programação I
O Portal do Estudante de Computação
Lex Linguagem (e compilador) para especificar analisadores léxicos.
PROGRAMAÇÃO ESTRUTURADA II
Ferramentas para a Construção de Compiladores: Lex & Yacc
Compiladores, Aula Nº 9 João M. P. Cardoso
Análise Léxica Primeira fase de um compilador
Mayerber Carvalho Neto
Professor José Rui Aula 10
Algoritmo e Programação
Análise Léxica.
Capítulo II Gramáticas e Linguagens
Analise sintática aula-07-analise-sintática.pdf.
Estruturas de Dados Aula 2: Estruturas Estáticas 07/04/2014.
Análise Sintática LR Prof. Alexandre Monteiro
Analise Semântica aula-10-analise-semântica.pdf.
PROGRAMAÇÃO ou LINGUAGEM C?
Analisador Léxico Prof. Alexandre Monteiro
Capítulo V – Comandos de Entrada e Saída 5.1 – Equipamentos de entrada e saída 5.2 – Saída no vídeo-texto 5.3 – Entrada pelo teclado 5.4 – Entrada e saída.
Projeto de Tradutor Preditivo. Introdução Introdução Esquemas L-atribuidos são reconhecidos por analisadores Top-Down. Entre estes analisadores, se encontra.
Declarando e Chamando Funções
Algumas notas sobre a linguagem de programação C
Aula 12 1 Análise Sintáctica Compiladores, Aula Nº 12 João M. P. Cardoso.
Análise Sintática Prof. Alexandre Monteiro
Análise Léxica Prof. Alexandre Monteiro
Tradução Dirigida por Sintaxe
Aula Prática 3 Funções Monitoria Introdução à Programação.
Aula prática 3 Aprofundando em Funções Parâmetros de uma função Uso do return Execução Variáveis Global, local e estática Monitoria de Introdução à.
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2014 Capítulo I Comandos Simples e Repetições.
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2013 Capítulo I Comandos Simples e Repetições.
Analisador Léxico.
Mas para que serve um analisador sintático? Verificar se a estrutura gramatical do programa está correta Escrito de outra forma: O texto segue as regras.
CES-41 COMPILADORES Aulas Práticas
Faculdade Pernambucana - FAPE Setembro/2007
Aula Prática 3 Funções Monitoria Introdução à Programação.
Geradores de analisadores léxicos
DSC/CCT/UFCG Carga Horária: 60 h Profs.: José Eustáquio Rangel de Queiroz Roberto Medeiros de Faria Ulrich Schiel José Eustáquio Rangel.
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2014 Capítulo X Encadeamento de Estruturas por Ponteiros.
Programação Computacional Aula 8: Entrada e Saída pelo Console Prof a. Madeleine Medrano
PROGRAMAÇÃO II – PARTE 1 Profa. Maria Augusta Constante Puget.
Lex e Yacc Compiladores Giovani Rubert Librelotto
Fernando Célio.  Revisão da aula anterior  Dev-C++  Função printf( )
Compilador Software que traduz o texto (linguagem fonte) que representa um programa para código máquina(linguagem alvo) capaz de ser executado pelo.
Faculdade Pernambuca - FAPE Compiladores Abril/2007 Compiladores Abril/2007.
Módulo I Capítulo 7: Funções e Procedimentos William Ivanski Curso de Programação C#
Clique para editar o título Linguagem C Para programadores Python PMR
CES-41 COMPILADORES Aulas Práticas
Transcrição da apresentação:

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

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

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

% 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

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

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

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} ;

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

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.

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

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

% 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;}

% 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

% 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

% 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

% 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;}

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;}

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

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

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

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

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

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

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 | ε

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 | ε

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

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

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

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

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

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

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

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

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

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)$

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 * ( )$

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

{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

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

%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

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

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 * ( )$

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

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

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; } ;

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; } ;

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;

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

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;} %

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

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

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’

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

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 (‘(’);}

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

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

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_

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 =_

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

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 ; _

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_

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 =_

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_

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 ; _

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

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

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

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

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

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

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

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 )

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: ( ) ( ( ) ( ) ) ( ( ) ) $

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.

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

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