CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo III Análise Semântica no Yacc.
CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc.
Transcript of CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo II A Ferramenta Yacc.
CES-41 CES-41 COMPILADORESCOMPILADORES
Aulas Práticas - 2014Aulas Práticas - 2014
Capítulo II Capítulo II
A Ferramenta YaccA Ferramenta Yacc
Yacc é um gerador de analisadores sintáticos:Yacc é um gerador de analisadores sintáticos:
Têm como entrada a Têm como entrada a gramática livre de gramática livre de contextocontexto da linguagem-fonte do compilador e da linguagem-fonte do compilador e implementa uma função de nome implementa uma função de nome yyparseyyparse, que , que responde se o programa analisado tem ou não responde se o programa analisado tem ou não erros sintáticoserros sintáticos
YaccYacc ( (Yet Another Compiler-CompilerYet Another Compiler-Compiler) do ) do sistema sistema UNIXUNIX também possui diversas versões também possui diversas versões para o sistema para o sistema DOSDOS (o Yacc do (o Yacc do MingwMingw é uma é uma delas)delas)
O analisador gerado é um programa em O analisador gerado é um programa em Linguagem CLinguagem C
Programa 2.1: Saída de dadosPrograma 2.1: Saída de dados
Criar na pasta Criar na pasta MinGW/binMinGW/bin um arquivo um arquivo extensão extensão .y (saida.y.y (saida.y, por exemplo, por exemplo) ) com o com o seguinte programa:seguinte programa:
%%%%prod:prod: {printf ("hello friends!\n");}{printf ("hello friends!\n");}
;;%%%%yylex () {yylex () {return 0;return 0;
}}
ExecutarExecutar os seguintes comandos: os seguintes comandos:
yacc saida.yyacc saida.ygcc y.tab.c main.c yyerror.c -o saida -lflgcc y.tab.c main.c yyerror.c -o saida -lflsaidasaida
Colocar pelo menos uma
produção
Não pode haver função
main
Tem de haver função yylex
%%%%prod:prod: {printf ("hello friends!\n");}{printf ("hello friends!\n");}
;;%%%%yylex () {yylex () {return 0;return 0;
}}
Executar: Executar: saida > pppsaida > ppp
Abrir o arquivo Abrir o arquivo pppppp (No DOS: (No DOS: more pppmore ppp))
Abrir o arquivo Abrir o arquivo main.cmain.c (só executa (só executa yyparseyyparse e e retorna) retorna)
yyparseyyparse é o analisador sintático produzido pelo é o analisador sintático produzido pelo YaccYacc
Abrir o arquivo Abrir o arquivo y.tab.cy.tab.c e localizar e localizar yylexyylex, , prodprod e o e o printfprintf acima acima
Estrutura de um programa em Yacc:Estrutura de um programa em Yacc:
Tal como em Tal como em LexLex,, um programa em um programa em YaccYacc é é dividido em três partes, a saber:dividido em três partes, a saber:
DeclaraçõesDeclarações
% %% %
Produções da gramática Produções da gramática
% %% %
Rotinas auxiliaresRotinas auxiliares
Produções da gramática:Produções da gramática:
É a É a parte principalparte principal de um programa em de um programa em YaccYacc
O programa deve conter O programa deve conter pelo menos uma pelo menos uma produçãoprodução
As As produçõesproduções podem vir acompanhadas de podem vir acompanhadas de açõesações escritas na escritas na Linguagem CLinguagem C, inseridas em , inseridas em qualquer posiçãoqualquer posição de seu de seu lado direitolado direito
Produções da gramática:Produções da gramática:
Exemplo:: Sejam as produções: Sejam as produções:
Expr Expr Expr Expr OPAD OPAD TermoTermo | | TermoTermo
Termo Termo ID | CTEID | CTE
Em Em YaccYacc, com ações opcionais:, com ações opcionais:
exprexpr :: expr OPAD {comandos em C} termoexpr OPAD {comandos em C} termo
|| {comandos em C} termo {comandos em C} termo
;;
termotermo :: ID {comandos em C}ID {comandos em C}
|| CTE {comandos em C}CTE {comandos em C}
;;
Produções da gramática:Produções da gramática:
AçõesAções podem aparecer no lado direito de uma podem aparecer no lado direito de uma produção vaziaprodução vazia
Exemplo:Exemplo:
yyyyyy : : {comandos em C}{comandos em C}
| | xxx {comandos em C} zzz xxx {comandos em C} zzz
;;
A primeira produção de yyy é vazia
Declarações:Declarações:
Nelas estão inclusas:Nelas estão inclusas:
Em C, delimitadas por Em C, delimitadas por %{%{ e e %}%}::
- DeclaraçõesDeclarações de variáveis, tipos, protótipos, de variáveis, tipos, protótipos, etc.etc.
- Definições de constantes e macros (Definições de constantes e macros (definedefine’s) ’s) - Inclusão de Inclusão de arquivosarquivos sem definição de sem definição de
funções funções
Declarações do YaccDeclarações do Yacc (fora de (fora de %{%{ e e %}%}) usadas ) usadas para definir terminais, não-terminais, precedência para definir terminais, não-terminais, precedência de operadores, tipos dos atributos, etc.de operadores, tipos dos atributos, etc.
Declarações:Declarações:
Exemplo: Exemplo: para as produções anteriorespara as produções anteriores
exprexpr :: expr OPAD {comandos em C} termoexpr OPAD {comandos em C} termo|| {comandos em C} termo {comandos em C} termo ;;
termotermo :: ID {comandos em C}ID {comandos em C}|| CTE {comandos em C}CTE {comandos em C};;
os átomos são assim declarados:os átomos são assim declarados:
%token OPAD%token OPAD%token ID%token ID%token CTE%token CTE
Rotinas auxiliares:Rotinas auxiliares:
São São definições de funções em Cdefinições de funções em C, referenciadas , referenciadas nas nas açõesações das produções da gramática das produções da gramática
Podem trazer a Podem trazer a inclusãoinclusão de arquivos com de arquivos com extensão extensão .c.c; por exemplo, o arquivo ; por exemplo, o arquivo lex.yy.clex.yy.c, do , do FlexFlex
NãoNão devem conter a função devem conter a função mainmain, pois essa já , pois essa já vem inclusa no vem inclusa no ambienteambiente da ferramenta da ferramenta
Devem incluir a função Devem incluir a função yylexyylex; quando usado com ; quando usado com FlexFlex, essa função já vem contida no arquivo , essa função já vem contida no arquivo lex.yy.clex.yy.c
%%%%prod : {printf ("hello friends!\n");}prod : {printf ("hello friends!\n");}
;;%%%%yylex () {yylex () { return 0;return 0;
}}
Fazer Fazer yylexyylex retornar algo diferente de retornar algo diferente de zerozero
Colocar um Colocar um returnreturn dentro da ação depois do dentro da ação depois do printfprintf
Retomando o programa saida.y
return 50;
prod : {printf ("hello friends!\n"); return;}
%%%%prod : {printf ("hello friends!\n");}prod : {printf ("hello friends!\n");}
;;%%%%yylex () {yylex () { return 0;return 0;
}}
O analisador gerado pelo O analisador gerado pelo YaccYacc é é bottom-upbottom-up
Vai detectando Vai detectando lados direitoslados direitos de produções e de produções e reduzindo-os para seus reduzindo-os para seus lados esquerdoslados esquerdos
Tudo Tudo acaba bemacaba bem quando se consegue chegar quando se consegue chegar ao ao símbolo inicialsímbolo inicial
Explicando os fatos
%%%%prod : {printf ("hello friends!\n");}prod : {printf ("hello friends!\n");}
;;%%%%yylex () {yylex () { return 0;return 0;
}}
A A únicaúnica produção desta gramática ( produção desta gramática (prodprod) é vazia) é vazia
Antes de Antes de yyparseyyparse pedir um átomo para pedir um átomo para yylexyylex, ele , ele casa a casa a falta de átomofalta de átomo em suas mãos com seu em suas mãos com seu lado direitolado direito
yyparseyyparse faz a faz a reduçãoredução para o lado esquerdo e para o lado esquerdo e executa a ação no final da produçãoexecuta a ação no final da produção
Chegou ao Chegou ao símbolo inicialsímbolo inicial
Explicando os fatos
%%%%prod : {printf ("hello friends!\n");}prod : {printf ("hello friends!\n");}
;;%%%%yylex () {yylex () { return 0;return 0;
}}
Em seguida, chama Em seguida, chama yylexyylex que lhe retorna que lhe retorna zerozero
Recebendo zero, ele Recebendo zero, ele aceita e retornaaceita e retorna
mainmain então se encerra então se encerra
Explicando os fatos
%%%%prod : {printf ("hello friends!\n");}prod : {printf ("hello friends!\n");}
;;%%%%yylex () {yylex () { return return 5050;;
}}
Depois de chegar ao Depois de chegar ao símbolo inicialsímbolo inicial, , yyparse yyparse só aceita o átomo só aceita o átomo zerozero
Se Se yylexyylex lhe retornar algo lhe retornar algo diferente de zerodiferente de zero, , ele ele rejeitarárejeitará
Com o Com o returnreturn dentro da ação, dentro da ação, yyparseyyparse retorna retorna para para mainmain antes de chamar antes de chamar yylexyylex
Explicando os fatos
prod : {printf ("hello friends!\n"); return;}
Programa 2.2: Entrada de dadosPrograma 2.2: Entrada de dados
Criar um arquivo extensão Criar um arquivo extensão .y (entra.y.y (entra.y, por , por exemploexemplo) ) com o seguinte programa:com o seguinte programa:
%%%%ppp:ppp: {int i, n;{int i, n;
printf ("Digite o numero de repeticoes: printf ("Digite o numero de repeticoes: ");");
scanf ("%d", &n);scanf ("%d", &n);for (i = 1; i <= n; i++)for (i = 1; i <= n; i++)
printf ("\nhello friends!"); printf ("\nhello friends!"); }};;
%%%%yylex () {return 0;}yylex () {return 0;}
Executar os seguintes comandos:Executar os seguintes comandos:
yacc entra.yyacc entra.ygcc y.tab.c yyerror.c main.c -o entra -lflgcc y.tab.c yyerror.c main.c -o entra -lflentraentra
Criar um arquivo Criar um arquivo entra.datentra.dat, colocando nele o , colocando nele o número 10número 10
Executar os comandos:Executar os comandos:
entra < entra.datentra < entra.datentra < entra.dat > pppentra < entra.dat > ppp
Abrir o arquivo Abrir o arquivo pppppp
Esquema de produção de um Esquema de produção de um programa programa executávelexecutável usando usando YaccYacc, sem auxilio do , sem auxilio do FlexFlex::
Programa 2.3: Reconhecimento de frasePrograma 2.3: Reconhecimento de frase
Rodar Rodar yaccyacc e e gccgcc para um arquivo para um arquivo recfrase.yrecfrase.y com o seguinte programa:com o seguinte programa:
%%%%prod :prod : 'C' 'O' 'M' 'P' ' ' '1' '5''C' 'O' 'M' 'P' ' ' '1' '5'
{printf ("Reconheco!\n"); return;}{printf ("Reconheco!\n"); return;} ; ;
%%%%yylex () {yylex () {return getchar ();return getchar ();
}}
Executar recfrase com:
COMP 14COMP 15COMP 16COMP 153
O lado direito das produções tem apenas terminais (tokens)
Um caractere entre apóstrofos é considerado um token
Programa 2.3: Reconhecimento de frasePrograma 2.3: Reconhecimento de frase
Rodar Rodar yaccyacc e e gccgcc para um arquivo para um arquivo recfrase.yrecfrase.y com o seguinte programa:com o seguinte programa:
%%%%prod :prod : 'C' 'O' 'M' 'P' ' ' '1' '5''C' 'O' 'M' 'P' ' ' '1' '5'
{printf ("Reconheco!\n"); return;}{printf ("Reconheco!\n"); return;} ; ;
%%%%yylex () {yylex () {return getchar ();return getchar ();
}}
Executar recfrase com:
COMP 14COMP 15COMP 16COMP 153
Executar com arquivo de dados (recfrase.dat, por exemplo): uma frase de cada vez
Executar:
recfrase < recfrase.dat > ppp
Programa 2.4: Gramática S → Programa 2.4: Gramática S → εε | a S b | a S b
%token%token a a%token%token b b%token%token dolar dolar%token%token erro erro%%%%SSSS :: S dolar S dolar {printf ("Fim da analise\n");{printf ("Fim da analise\n");
return;return;}};;
SS ::| a S b| a S b;;
%%%%
yylexyylex () { () {charchar x; x;x = getchar ();x = getchar ();whilewhile (x == ' ' || x == '\n' || x == '\t' || x (x == ' ' || x == '\n' || x == '\t' || x
== '\r')== '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);ifif (x == 'a') (x == 'a') returnreturn a; a; ifif (x == 'b') (x == 'b') returnreturn
b;b;ifif (x == '$') (x == '$') returnreturn dolar; dolar; returnreturn erro; 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 → Programa 2.4: Gramática S → εε | a S b | a S b
%token%token a a%token%token b b%token%token dolar dolar%token%token erro erro%%%%SSSS :: S dolar S dolar {printf ("Fim da analise\n");{printf ("Fim da analise\n");
return;return;}};;
SS ::| a S b| a S b;;
%%%%
yylexyylex () { () {charchar x; x;x = getchar ();x = getchar ();whilewhile (x == ' ' || x == '\n' || x == '\t' || x (x == ' ' || x == '\n' || x == '\t' || x
== '\r')== '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);ifif (x == 'a') (x == 'a') returnreturn a; a; ifif (x == 'b') (x == 'b') returnreturn
b;b;ifif (x == '$') (x == '$') returnreturn dolar; dolar; returnreturn erro; erro;
}}
Experimente tirar o return; sem e com arquivo de dados
yylex só retorna quando um caractere é digitado e nunca retorna zeroCom fim de arquivo, yylex retorna erro
Chegando ao símbolo inicial, yyparse sempre chama yylex, esperando zero
Exercício 2.1: Exercício 2.1: Escrever em Yacc, um analisador Escrever em Yacc, um analisador sintático para a seguinte gramática geradora sintático para a seguinte gramática geradora da linguagem L abaixo:da linguagem L abaixo:
L = { (a b)L = { (a b)nn c cnn (d d) (d d)** | n | n 1 1 }}
Gramática:Gramática:
S S a b A c D a b A c DA A a b A c | a b A c | εε D D d d D | d d D | εε
Exercício 2.2: Exercício 2.2: Escrever em Yacc, um analisador Escrever em Yacc, um analisador sintático para a seguinte gramática geradora sintático para a seguinte gramática geradora da linguagem L abaixo:da linguagem L abaixo:
L = { aL = { aii b bjj | j | j i i 0 } 0 }
Gramática:Gramática:
S S A B A BA A a A b | a A b | εε B B b B | b B | εε
Exercício 2.3: Exercício 2.3: Escrever em Yacc, um analisador Escrever em Yacc, um analisador sintático para a seguinte gramática geradora sintático para a seguinte gramática geradora de expressões contendo só pares de de expressões contendo só pares de parêntesis balanceadosparêntesis balanceados e nenhum outro e nenhum outro caracterecaractere
Exemplos:Exemplos: ( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ( ) )( ( ) )
Gramática:Gramática:
S S ( A ) | S ( A ) ( A ) | S ( A )
A A εε | S | S
Programa 2.5: Yacc auxiliado por LexPrograma 2.5: Yacc auxiliado por Lex
Programa em Programa em FlexFlex no arquivo no arquivo expr01.lexpr01.l
delimdelim [ \t\n\r][ \t\n\r]wsws {delim}+{delim}+digitdigit [0-9][0-9]numnum {digit}+{digit}+%%%%{ws}{ws} { ;}{ ;}{num}{num} {return CTE;}{return CTE;}"+""+" {return OPAD;}{return OPAD;}"-""-" {return OPAD;}{return OPAD;}"*""*" {return OPMULT;}{return OPMULT;}"/""/" {return OPMULT;}{return OPMULT;}"(""(" {return ABPAR;}{return ABPAR;}")"")" {return FPAR;}{return FPAR;}"$""$" {return DOLAR;}{return DOLAR;}.. {return INVAL;}{return INVAL;}%%%%
yylex retorna tokens declarados no programa em Yacc
Programa em Programa em YaccYacc no arquivo no arquivo expr01.yexpr01.y
%{%{
#include#include <stdio.h><stdio.h>
#include#include <stdlib.h><stdlib.h>
%}%}
%token%token DOLARDOLAR
%token%token CTECTE
%token%token OPADOPAD
%token%token OPMULTOPMULT
%token%token ABPARABPAR
%token%token FPARFPAR
%token%token INVALINVAL
%%%%
Tokens a serem retornados por yylex
lineline :: expr DOLAR expr DOLAR
{printf("Fim da analise\n"); return;}{printf("Fim da analise\n"); return;}
;;
exprexpr :: exprexpr OPADOPAD termterm
|| termterm
;;
termterm :: termterm OPMULT fatOPMULT fat
|| fatfat
;;
fatfat :: CTECTE
|| ABPARABPAR expr expr FPAR FPAR
;;
%%%%
#include "lex.yy.c"#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.lflex expr01.lyacc expr01.yyacc expr01.ygcc y.tab.c main.c yyerror.c -o expr01 -lflgcc y.tab.c main.c yyerror.c -o expr01 -lfl
expr01expr01
(digitar uma expressão correta terminada por (digitar uma expressão correta terminada por ‘$’‘$’))expr01expr01
(digitar uma expressão incorreta terminada por (digitar uma expressão incorreta terminada por ‘$’‘$’))
Usando arquivo de dados de entrada, Usando arquivo de dados de entrada, yylexyylex retorna retorna zerozero ao ler ao ler fim de arquivofim de arquivo, quando , quando criado pelo criado pelo FlexFlex
Então, dispensa-se o Então, dispensa-se o returnreturn da produção da produção lineline
Esquema de produção de um Esquema de produção de um programa programa executávelexecutável usando usando YaccYacc, com auxilio do , com auxilio do FlexFlex::
Programa 2.6: Uso de atributos Programa 2.6: Uso de atributos (calculadora (calculadora simples)simples)
Programa em Programa em FlexFlex no arquivo no arquivo calc01.lcalc01.l
delimdelim [ \t\n\r][ \t\n\r]wsws {delim}+{delim}+digitdigit [0-9][0-9]numnum {digit}+{digit}+%%%%{ws}{ws} { ;}{ ;}{num}{num} {{yylval = atoi(yytext);yylval = atoi(yytext); return CTE;} return CTE;}"+""+" {{yylval = MAIS;yylval = MAIS; return OPAD;} return OPAD;}"-""-" {{yylval = MENOS;yylval = MENOS; return OPAD;} return OPAD;}"*""*" {{yylval = VEZES;yylval = VEZES; return OPMULT;} return OPMULT;}"/""/" {{yylval = DIV;yylval = DIV; return OPMULT;} return OPMULT;}"(""(" {return ABPAR;}{return ABPAR;}")"")" {return FPAR;}{return FPAR;}"$""$" {return DOLAR;}{return DOLAR;}.. {{yylval = yytext[0];yylval = yytext[0]; return INVAL;} return INVAL;}%%%%
yylval guarda o atributo de um token
yylval é declarado pelo Yacc
Programa em Programa em YaccYacc no arquivo no arquivo calc01.ycalc01.y
%{%{#include#include <stdio.h><stdio.h>#include#include <stdlib.h><stdlib.h>#define #define MAISMAIS 11#define #define MENOSMENOS 22#define #define VEZESVEZES 33#define #define DIVDIV 44%}%}%token%token DOLARDOLAR%token%token CTECTE%token%token OPADOPAD%token%token OPMULTOPMULT%token%token ABPARABPAR%token%token FPARFPAR%token%token INVALINVAL%%%%
Atributos para os tokens OPAD e OPMULT
Por default, yylval é inteiro
lineline :: exprexpr DOLARDOLAR {{printf("valor: %d\n", $1);printf("valor: %d\n", $1);
}};;
exprexpr :: exprexpr OPADOPAD termterm{{
switch ($2) switch ($2) {{
case MAIS : $$ = $1 + $3; break;case MAIS : $$ = $1 + $3; break;case MENOS : $$ = $1 - $3; case MENOS : $$ = $1 - $3;
break;break;}}
}}|| termterm;;
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 1o, 2o, 3o ... símbolos do lado direito
termterm :: termterm OPMULT fatOPMULT fat
{{
switch ($2) switch ($2)
{{
case VEZES: $$ = $1 * $3; break;case VEZES: $$ = $1 * $3; break;
case DIV: $$ = $1 / $3; break;case DIV: $$ = $1 / $3; break;
}}
}}
|| fatfat
;;
fatfat :: CTECTE
|| ABPAR exprABPAR expr FPAR FPAR {$$ = $2;}{$$ = $2;}
;;
%%%%
#include "lex.yy.c"#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 No YaccYacc, a análise é , a análise é bottom-upbottom-up (por (por deslocamentodeslocamento e e reduçãoredução))
Os átomos são obtidos e deslocados para uma Os átomos são obtidos e deslocados para uma pilhapilha ( (deslocamentodeslocamento))
Quando no Quando no topotopo da pilha se formar o da pilha se formar o lado-direitolado-direito de uma produção, tem-se uma ocasião para de uma produção, tem-se uma ocasião para reduzirreduzir
O analisador O analisador verificaverifica se a redução é se a redução é válida válida
Isso será estudado no tópico sobre Isso será estudado no tópico sobre Análise Análise Bottom-UpBottom-Up do capítulo sobre do capítulo sobre Análise Análise SintáticaSintática
Em caso positivo, substitui, na pilha, o Em caso positivo, substitui, na pilha, o lado-lado-direitodireito pelo pelo lado-esquerdolado-esquerdo da produção da produção ((reduçãoredução))
Então, a Então, a ação no finalação no final da produção é executada da produção é executada
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
## 10*(5+3)$#10*(5+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
## 10*(5+3)$#10*(5+3)$# dd
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#C#C1010 *(5+3)$#*(5+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#C#C1010 *(5+3)$#*(5+3)$# r: F → Cr: F → C $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#F#F1010 *(5+3)$#*(5+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#F#F1010 *(5+3)$#*(5+3)$# r: T → Fr: T → F $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010 *(5+3)$#*(5+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010 *(5+3)$#*(5+3)$# d d dd d d
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
Por que não reduz segundo E E → T→ T ? ?
A resposta virá no estudo de A resposta virá no estudo de Análise Análise Bottom-UpBottom-Up
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(C*(C55 +3)$#+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(C*(C55 +3)$#+3)$# r: F → Cr: F → C $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(F*(F55 +3)$#+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(F*(F55 +3)$#+3)$# r: T → Fr: T → F $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(T*(T55 +3)$#+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(T*(T55 +3)$#+3)$# r: E → Tr: E → T $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55 +3)$#+3)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55 +3)$#+3)$# d dd d
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+C+C33 )$#)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+C+C33 )$#)$# r: F → Cr: F → C $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+F+F33 )$#)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+F+F33 )$#)$# r: T → Fr: T → F $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+T+T33 )$#)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E55+T+T33 )$#)$# r: E → E+Tr: E → E+T $$ = $1+$3$$ = $1+$3
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E88 )$#)$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E88 )$#)$# dd
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E88)) $#$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*(E*(E88)) $#$# r: F → (E)r: F → (E) $$ = $2$$ = $2
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*F*F88 $#$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T1010*F*F88 $#$# r: T → T*Fr: T → T*F $$ = $1*$3$$ = $1*$3
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T8080 $#$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#T#T8080 $#$# r: E → Tr: E → T $$ = $1$$ = $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#E#E8080 $#$#
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#E#E8080 $#$# dd
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#E#E8080$$ ##
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#E#E8080$$ ## r: L → E$r: L → E$ Imprimir $1Imprimir $1
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#L#L ##
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
Escrito no vídeo: valor 80
PilhaPilha EntradaEntrada OperaçãoOperação AçãoAção
#L#L ## aceitaraceitar
Análise e cálculo da expressão Análise e cálculo da expressão 10 * (5 + 10 * (5 + 3)$3)$
lineline :: exprexpr DOLAR DOLAR
exprexpr :: exprexpr OPAD term | term OPAD term | term
termterm :: termterm OPMULT fat | fat OPMULT fat | fat
fatfat :: CTE | ABPAR exprCTE | ABPAR expr FPARFPAR
Escrito no vídeo: valor 80
Árvore sintática de 10*(5+3)$ com atributos:
Programa 2.7: Alteração no tipo dos Programa 2.7: Alteração no tipo dos atributosatributos
Programa em Programa em FlexFlex no arquivo no arquivo calc02.lcalc02.l::
delimdelim [ \t\n][ \t\n]wsws {delim}+{delim}+digitdigit [0-9][0-9]ctecte {digit}+(\.{digit}*)?{digit}+(\.{digit}*)?%%%%{ws}{ws} { ;}{ ;}{cte}{cte} {yylval = atof(yytext); return CTE;}{yylval = atof(yytext); return CTE;}"+""+" {return MAIS;}{return MAIS;}"*""*" {return VEZES;}{return VEZES;}"(""(" {return ABPAR;}{return ABPAR;}")"")" {return FPAR;}{return FPAR;}"$""$" {return DOLAR;}{return DOLAR;}%%%%
Para simplificar:
Expressões somente com somas e multiplicações
Programa em Programa em YaccYacc no arquivo no arquivo calc02.ycalc02.y
%{%{
#include#include <stdio.h><stdio.h>
#include#include <stdlib.h><stdlib.h>
#define #define YYSTYPE floatYYSTYPE float
%}%}
%token%token DOLARDOLAR
%token%token CTECTE
%token%token MAISMAIS
%token%token VEZESVEZES
%token%token ABPARABPAR
%token%token FPARFPAR
%%%%
Alteração no tipo de yylval e dos atributos dos não-terminais
lineline :: exprexpr DOLAR {DOLAR {
printf("valor: %g\n",$1);printf("valor: %g\n",$1);
return 0;}return 0;}
;;
exprexpr :: exprexpr MAISMAIS term term {$$ = $1 + $3;}{$$ = $1 + $3;}
|| termterm
;;
termterm :: termterm VEZES fatVEZES fat {$$ = $1 * $3;}{$$ = $1 * $3;}
|| fatfat
;;
fatfat :: CTECTE
|| ABPARABPAR expr expr FPAR FPAR {$$ = {$$ = $2;}$2;}
;;
%%%%
#include "lex.yy.c"#include "lex.yy.c"
Rodar o executável para um arquivo com uma expressão tal como
10.5 * (5.2 + 3.3)$
Programa 2.8: Atributos de tipos Programa 2.8: Atributos de tipos alternativosalternativos
Programa em Programa em FlexFlex no arquivo no arquivo calc03.lcalc03.l
delimdelim [ \t\n][ \t\n]wsws {delim}+{delim}+digitdigit [0-9][0-9]ctintctint {digit}+{digit}+ctfloatctfloat {digit}+\.{digit}*{digit}+\.{digit}*%%%%
Programa com constantes inteiras e reais
{ws}{ws} { ;}{ ;}{ctint}{ctint} {{yylval.valintyylval.valint = atoi(yytext); = atoi(yytext);
return CTINT;}return CTINT;}{ctfloat}{ctfloat} {{yylval.valfloatyylval.valfloat = atof(yytext); = atof(yytext);
return CTFLOAT;}return CTFLOAT;}"+""+" {{yylval.atryylval.atr = MAIS; return OPAD;} = MAIS; return OPAD;}"-""-" {{yylval.atryylval.atr = MENOS; return OPAD;} = MENOS; return OPAD;}"*""*" {{yylval.atryylval.atr = VEZES; return OPMULT;} = VEZES; return OPMULT;}"/""/" {{yylval.atryylval.atr = DIV; return OPMULT;} = DIV; return OPMULT;}"(""(" {return ABPAR;}{return ABPAR;}")"")" {return FPAR;}{return FPAR;}"$""$" {return DOLAR;}{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 Programa em YaccYacc no arquivo no arquivo calc03.ycalc03.y
%{%{
#include#include <stdio.h><stdio.h>
#include#include <stdlib.h><stdlib.h>
#define MAIS#define MAIS 11
#define MENOS#define MENOS 22
#define VEZES#define VEZES 33
#define DIV#define DIV 44
%}%}
%union {%union {
int valint, atr;int valint, atr;
float valfloat;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 %type <valfloat> <valfloat> expr term fatexpr term fat
%token%token DOLARDOLAR
%token%token <valint><valint> CTINTCTINT
%token%token <valfloat><valfloat> CTFLOATCTFLOAT
%token%token <atr><atr> OPADOPAD
%token%token <atr><atr> OPMULTOPMULT
%token%token ABPARABPAR
%token%token FPARFPAR
%%%%
Especificação dos atributos dos tokens e dos não-terminais
%type: para os não-terminais
%token: para os terminais
lineline :: exprexpr DOLAR {DOLAR {
printf("valor: %g\n",$1);printf("valor: %g\n",$1);
}}
;;
exprexpr :: exprexpr OPADOPAD termterm
{{
switch ($2) {switch ($2) {
case MAIS : $$ = $1 + $3; break;case MAIS : $$ = $1 + $3; break;
case MENOS : $$ = $1 - $3; case MENOS : $$ = $1 - $3; break;break;
}}
}}
|| termterm
;;
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
termterm :: termterm OPMULT fatOPMULT fat
{{
switch ($2) {switch ($2) {
case VEZES: $$ = $1 * $3; break;case VEZES: $$ = $1 * $3; break;
case DIV: $$ = $1 / $3; break;case DIV: $$ = $1 / $3; break;
}}
}}
|| fatfat
;;
fatfat :: CTINTCTINT {$$ = (float)$1;}{$$ = (float)$1;}
|| CTFLOATCTFLOAT
|| ABPARABPAR expr expr FPAR FPAR {$$ = $2;} {$$ = $2;}
;;
%%%%
#include "lex.yy.c"#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)$
Programa 2.9: Ações no início e meio das Programa 2.9: Ações no início e meio das produçõesproduções
%{%{#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>int v, w, x, y, z;int v, w, x, y, z;%}%}%%%%AA :: {w = 10; $$ = 5*w;}{w = 10; $$ = 5*w;} B B
{$$ = 1; v = $1; y = $2;}{$$ = 1; v = $1; y = $2;} C C{{
x = $3; z = $4;x = $3; z = $4;printf ("v = %d; w = %d; x = %d; y = %c; z = %c;",printf ("v = %d; w = %d; x = %d; y = %c; z = %c;",
v, w, x, y, z);v, w, x, y, z);return 0; return 0;
}};;
BB :: 'b''b';;
CC :: '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
AA :: {w = 10; $$ = 5*w;} B {w = 10; $$ = 5*w;} B
{$$ = 1; v = $1; y = $2;} C{$$ = 1; v = $1; y = $2;} C
{{
x = $3; z = $4;x = $3; z = $4;
printf ("- - -", printf ("- - -", v, w, x, y, z);v, w, x, y, z);
return 0; return 0;
}}
;;
BB :: 'b''b'
;;
CC :: '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
A A
Produção:Produção:
Torna-se:Torna-se:
AA :: {w = 10; $$ = 5*w;} B {w = 10; $$ = 5*w;} B {$$ = 1; v = $1; y = $2;} C{$$ = 1; v = $1; y = $2;} C{x = $3; z = $4;{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 Nas produções de $$1$$1 e e $$2$$2, , $$$$ é o atributo é o atributo do lado esquerdodo lado esquerdo
Na produção de Na produção de $$2$$2, , $1$1 é o atributo de é o atributo de $$1$$1 e e $2$2 é o de é o de BB, da produção de , da produção de AA
Na produção de Na produção de AA, , $3$3 é o atributo de é o atributo de $$2$$2 e e $4$4 é o de é o de CC
Cuidado com a numeração dos atributos da Cuidado com a numeração dos atributos da produção originalproduçã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 entradaPara entrada bc 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-PrinterPrograma 2.10: Pretty-Printer
Dada uma entrada Dada uma entrada
desorganizada do tipo: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 Obter uma saída organizada do tipo:organizada do tipo:
É necessário mudar de linha e tabular oportunamente
Programa em Flex no arquivo pretty2014.lPrograma em Flex no arquivo pretty2014.l
delimdelim [ \t\n][ \t\n]wsws {delim}+{delim}+digitodigito [0-9][0-9]letraletra [A-Za-z][A-Za-z]intctintct {digito}+{digito}+idid {letra}({letra}|{digito})*{letra}({letra}|{digito})*%%%%{ws}{ws} { ;}{ ;}{id}{id} {strcpy (yylval.cadeia, yytext); return ID;}{strcpy (yylval.cadeia, yytext); return ID;}{intct}{intct} {yylval.valint = atoi(yytext); return INTCT;}{yylval.valint = atoi(yytext); return INTCT;}"+""+" {yylval.atr = MAIS; return ADOP;}{yylval.atr = MAIS; return ADOP;}"-""-" {yylval.atr = MENOS; return ADOP;}{yylval.atr = MENOS; return ADOP;}"(""(" {return OPPAR;}{return OPPAR;}")"")" {return CLPAR;}{return CLPAR;}"{""{" {return OPBRACE;}{return OPBRACE;}"}""}" {return CLBRACE;}{return CLBRACE;}";"";" {return SCOLON;}{return SCOLON;}"=""=" {return ASSIGN;}{return ASSIGN;}.. {yylval.carac = yytext[0]; return INVAL;}{yylval.carac = yytext[0]; return INVAL;}%%%%
Programa em Yacc no arquivo pretty2014.yPrograma em Yacc no arquivo pretty2014.y
%{%{#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>#define#define MAISMAIS 77#define#define MENOSMENOS 88int tab = 0;int tab = 0;%}%}%union {%union {char cadeia[50];char cadeia[50];int atr, valint;int atr, valint;char carac;char carac;
}}
tab: no de tabulações a serem dadas por uma função de nome tabular
%token%token <cadeia><cadeia> IDID
%token%token <valint><valint> INTCTINTCT
%token%token <atr><atr> ADOPADOP
%token%token OPPAROPPAR
%token%token CLPARCLPAR
%token%token OPBRACEOPBRACE
%token%token CLBRACECLBRACE
%token%token SCOLONSCOLON
%token%token ASSIGNASSIGN
%token%token <carac><carac> INVALINVAL
%%%%
CompStat :CompStat : OPBRACEOPBRACE
{tabular (); printf ("\{\n"); tab++;}{tabular (); printf ("\{\n"); tab++;}
StatList CLBRACEStatList CLBRACE
{tab--; tabular (); printf ("}\n");}{tab--; tabular (); printf ("}\n");}
;;
StatListStatList :: StatementStatement
|| StatList StatementStatList Statement
;;
Statement :Statement : AssignStatAssignStat
|| CompStatCompStat
;;
AssignStat AssignStat :: ID {tabular (); printf ("%s ", $1);}ID {tabular (); printf ("%s ", $1);}
ASSIGN {printf ("= ");}ASSIGN {printf ("= ");}
Expression SCOLON {printf(";\n");}Expression SCOLON {printf(";\n");}
;;
tabular: dá tantas tabulações quanto for o valor de tabDepois de todo token imprime seu texto
Para alguns tokens, imprime ‘\n’
ExpressionExpression :: TermTerm
|| Expression ADOP {Expression ADOP {
if ($2 == MAIS) printf ("+ ");if ($2 == MAIS) printf ("+ ");
else printf ("- ");else printf ("- ");
} Term} Term
;;
TermTerm :: ID {printf ("%s ", $1);}ID {printf ("%s ", $1);}
|| INTCT {printf ("%d ", $1);}INTCT {printf ("%d ", $1);}
| | OPPAR {printf("\( ");}OPPAR {printf("\( ");}
Expression CLPAR {printf (") ");}Expression CLPAR {printf (") ");}
;;
%%%%
#include "lex.yy.c"#include "lex.yy.c"
tabular () {tabular () {
int i;int i;
for (i = 1; i <= tab; 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 Outra forma de apresentar a gramática (com abreviaturas):abreviaturas):
Comp :Comp : ‘{’ $$1 StatL ‘}’ ‘{’ $$1 StatL ‘}’ {tab--; tabular (); write("}\n");}{tab--; tabular (); write("}\n");} ;;
StatL :StatL : Stat | StatL StatStat | StatL Stat ;;Stat Stat :: AsStat | CompAsStat | Comp
;;AsStat :AsStat : ID $$2 “=” $$3 Expr ‘;’ ID $$2 “=” $$3 Expr ‘;’
{write(";\n");}{write(";\n");};;
ExprExpr :: Term | Expr OPAD $$4 TermTerm | Expr OPAD $$4 Term ;;TermTerm :: ID {write($1);} | INTCT {write($1);}ID {write($1);} | INTCT {write($1);}
| ‘(’ $$5 Expr ‘)’ {write (")");}| ‘(’ $$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 A análise bottom-upbottom-up por por deslocamento e deslocamento e reduçãoredução, feita pelo , feita pelo YaccYacc, simula o , simula o caminhamento em caminhamento em pós-ordempós-ordem, na árvore , na árvore sintática de uma sentença corretasintática de uma sentença correta
Isso é usado a seguir para ilustrar o resultado Isso é usado a seguir para ilustrar o resultado das ações do das ações do pretty-printerpretty-printer para produzir o para produzir o efeito desejadoefeito desejado
Seja a seguinte sentença bem simples:Seja a seguinte sentença bem simples:
{ i = 1 ; j = 2 ; }{ i = 1 ; j = 2 ; }
A seguir, sua árvore sintáticaA seguir, sua árvore sintática
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)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
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarDeslocar vazio
Reduzir: Ação:{tabular (); write ($1);}
{_
1
{i_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarDeslocar vazio
Reduzir: Ação:{write (“=");}
1
{i_
{i =_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarReduzir: Ação:{write ($1);}
1
{i =_
{i = 1_
Reduzir: Ação:{$$ = $1);} irrelevante
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarReduzir: Ação:{write (“;\n”);}
1
{i = 1_
Reduzir: Ação:{$$ = $1);} irrelevante
{i = 1 ;
_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarDeslocar vazio
Reduzir: Ação:{tabular(); write ($1);}
1
{i = 1 ;
_
{i = 1 ;j_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarDeslocar vazio
Reduzir: Ação:{write (“=”);}
1
{i = 1 ;j_
{i = 1 ;j =_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarReduzir: Ação:{write ($1);}
1
Reduzir: Ação:{$$ = $1);} irrelevante
{i = 1 ;j =_
{i = 1 ;j = 2_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarReduzir: Ação:{write (“;\n”);}
1
Reduzir: Ação:{$$ = $1);} irrelevante
{i = 1 ;j = 2_
{i = 1 ;j = 2 ;
_
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)INTCT(1)
Seja a pós-ordem:
tab
DeslocarReduzir: Ação:{tab--; tabular(); write (“}\n”);}
1
{i = 1 ;j = 2 ;
_
0
{i = 1 ;j = 2 ;
}_ Aceitar
CompComp
{ $$1 StatL { $$1 StatL }}
StatL Stat StatL Stat
Stat AsStatStat AsStat
AsStat ID(j) $$2 = $$3 AsStat ID(j) $$2 = $$3 Expr ;Expr ;
ID(i) $$2 = $$3 Expr ; ID(i) $$2 = $$3 Expr ; TermTerm
Term Term INTCT(2)INTCT(2)
INTCT(1)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 YaccPrograma 2.11: Conflitos no Yacc
%token a%token a%token b%token b%token c%token c%token dolar%token dolar%token erro%token erro%%%%SSSS:: S dolar {printf ("Fim da analise\n"); S dolar {printf ("Fim da analise\n");
return;} ;return;} ;SS :: X C | A Y ;X C | A Y ;AA : /* vazia */ | A a ;: /* vazia */ | A a ;XX : /* vazia */ | a X b ;: /* vazia */ | a X b ;YY : /* vazia */ | b Y c ;: /* vazia */ | b Y c ;CC : /* vazia */ | C c ;: /* vazia */ | C c ;%%%%
Arquivo conflito.y com uma gramática geradora da linguagem
L = {aibjck | i=j ou j=k}
A gramática é ambígua:
Sentença aaabbbccc tem mais de uma árvore sintática
yylex () {yylex () {char x;char x;
x = getchar ();x = getchar ();while (x == ' ' || x == '\n' || while (x == ' ' || x == '\n' ||
x == '\t' || x == '\r')x == '\t' || x == '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);if (x == 'a') return a; if (x == 'a') return a; if (x == 'b') return b;if (x == 'b') return b;if (x == 'c') return c; if (x == 'c') return c; if (x == '$') return dolar; if (x == '$') return dolar; return erro;return erro;
}}
Executar: Executar: yacc conflito.yyacc conflito.y
Resultado: Resultado: yacc: 1 shift/reduce conflict, 1 yacc: 1 shift/reduce conflict, 1 reduce/reduce conflict.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 () {yylex () {char x;char x;
x = getchar ();x = getchar ();while (x == ' ' || x == '\n' || while (x == ' ' || x == '\n' ||
x == '\t' || x == '\r')x == '\t' || x == '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);if (x == 'a') return a; if (x == 'a') return a; if (x == 'b') return b;if (x == 'b') return b;if (x == 'c') return c; if (x == 'c') return c; if (x == '$') return dolar; if (x == '$') return dolar; return erro;return erro;
}}
Executar: Executar: yacc –v conflito.yyacc –v conflito.y
Abrir arquivoAbrir arquivo y.output 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
ArquivoArquivo y.output y.output::
Contém um relatório da Contém um relatório da montagemmontagem do do analisadoranalisador
Conflito Conflito shift-reduceshift-reduce: indecisão entre : indecisão entre deslocardeslocar o átomo para a pilha ou fazer uma o átomo para a pilha ou fazer uma reduçãoredução no topo da pilha no topo da pilha
Conflito Conflito reduce-reducereduce-reduce: indecisão na : indecisão na escolhaescolha de uma produção para de uma produção para reduzirreduzir no topo da no topo da pilhapilha
ArquivoArquivo y.output y.output -- as produções são as produções são numeradas:numeradas:
0 $accept : SS $end 0 $accept : SS $end
1 SS : S dolar1 SS : S dolar
2 S : X C2 S : X C
3 | A Y3 | A Y
4 A :4 A :
5 | A a5 | A a
6 X :6 X :
7 | a X b7 | a X b
8 Y :8 Y :
9 | b Y c9 | b Y c
10 C :10 C :
11 | C c11 | 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 Há gramáticas ambíguas que têm equivalentesequivalentes não ambíguas não ambíguas
Exemplo:Exemplo: gramática gramática S S S S | ( S ) | S S | ( S ) | εε
geradora expressões com pares de parêntesis geradora expressões com pares de parêntesis balanceados, tais como:balanceados, tais como:
( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ( ) )( ), ( ( ) ), ( ) ( ), ( ) ( ( ) ( ( ) ) ) ( ( ) )
Gramática equivalente: Gramática equivalente: S S εε | S ( S ) | S ( S )
Programa 2.12: Conflito por ações no início Programa 2.12: Conflito por ações no início ou meio de produçõesou meio de produções
%%%%SS SS : S '$' {printf ("Fim da analise\n"); : S '$' {printf ("Fim da analise\n");
return;} ; return;} ;S S ::
| S '(' S ')'| S '(' S ')';;
%%%%yylex () {yylex () {
char x; x = getchar ();char x; x = getchar ();while (x == ' ' || x == '\n' || x == '\t' || while (x == ' ' || x == '\n' || x == '\t' ||
x == '\r')x == '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);if (x == '\(' || x == ')' || x == '$') if (x == '\(' || x == ')' || x == '$')
return x;return x;return '#';return '#';
}}
Programa Programa correto para correto para
S S εε | S ( S ) | S ( S )
Rodar para: ( ) ( ( ) ( ) ) ( ( ) ) ( ) ( ( ) ( ) ) ( ( ) ) $$
Inserindo uma ação:Inserindo uma ação:
%%%%SS SS : S '$' {printf ("Fim da analise\n"); : S '$' {printf ("Fim da analise\n");
return;} ; return;} ;S S ::
| | {printf ("\nyyy");}{printf ("\nyyy");} S '(' S ')' S '(' S ')';;
%%%%yylex () {yylex () {
char x; x = getchar ();char x; x = getchar ();while (x == ' ' || x == '\n' || x == '\t' || while (x == ' ' || x == '\n' || x == '\t' ||
x == '\r')x == '\r')x = getchar ();x = getchar ();
printf ("Caractere lido: %c\n", x);printf ("Caractere lido: %c\n", x);if (x == '\(' || x == ')' || x == '$') if (x == '\(' || x == ')' || x == '$')
return x;return x;return '#';return '#';
}}
yacc: 1 reduce/reduce conflict.
ArquivoArquivo y.output y.output::
0 $accept : SS $end 0 $accept : SS $end 1 SS : S '$'1 SS : S '$'2 S :2 S :3 $$1 :3 $$1 :4 S : $$1 S '(' S ')'4 S : $$1 S '(' S ')'
O O conflitoconflito é em usar a produção é em usar a produção 22 ou ou 33 para para reduzirreduzir diante do diante do ‘(’‘(’
$$1 $$1 é um não-terminal fictícioé um não-terminal fictício
Cada caso tem sua Cada caso tem sua solução particularsolução particular
Aqui, pode-seAqui, pode-se colocar a ação depois do colocar a ação depois do SS
Observações finais:Observações finais:
Apesar do conflito, o Apesar do conflito, o Yacc gera o analisadorYacc gera o analisador
O problema é que os O problema é que os resultadosresultados produzidos produzidos podem podem não ser corretosnão ser corretos
No projeto da disciplina, as produções do No projeto da disciplina, as produções do comando condicionalcomando condicional irão gerar um conflito irão gerar um conflito shift/reduceshift/reduce
O analisador gerado O analisador gerado resolverá o conflito resolverá o conflito de de forma a obedecer à forma a obedecer à regra usual regra usual para o caso para o caso if-elseif-else