0) { num := 1; cont := 0; enquanto (cont < n) { num := num + 1; div := 2; achou := falso; enquanto (achou = falso && div * div <= num) { resto := num % div; se (resto = 0) achou := verdade; senao div := div + 1; } se (achou = falso) { escrever (num, "\n"); cont := cont + 1; }}} senao escrever ("O valor de entrada deveria ser maior que zero"); senao escrever ("O valor de entrada deveria ser maior que zero");}"> 0) { num := 1; cont := 0; enquanto (cont < n) { num := num + 1; div := 2; achou := falso; enquanto (achou = falso && div * div <= num) { resto := num % div; se (resto = 0) achou := verdade; senao div := div + 1; } se (achou = falso) { escrever (num, "\n"); cont := cont + 1; }}} senao escrever ("O valor de entrada deveria ser maior que zero"); senao escrever ("O valor de entrada deveria ser maior que zero");}">
Carregar apresentação
A apresentação está carregando. Por favor, espere
PublicouIuri Rosa Alterado mais de 10 anos atrás
1
CES-41 COMPILADORES Aulas Práticas - 2013 Capítulo IV Código Intermediário no Yacc
2
O sub-set da Linguagem COMP-ITA-2013, usado no final do capítulo anterior, contém: O sub-set da Linguagem COMP-ITA-2013, usado no final do capítulo anterior, contém: Comandos de atribuição, compostos, entrada e saída, condicionais, enquanto, variáveis escalares e indexadas Comandos de atribuição, compostos, entrada e saída, condicionais, enquanto, variáveis escalares e indexadas Seja essa linguagem chamada de Sub-Set2 2013 Seja essa linguagem chamada de Sub-Set2 2013 Seja o programa a seguir, escrito em Sub-Set2 2013, para encontrar números primos Seja o programa a seguir, escrito em Sub-Set2 2013, para encontrar números primos
3
programa primos; var logic achou; int n, div, resto, cont, num; { ler (n); escrever (n, " primeiros numeros naturais primos:\n\n"); escrever (n, " primeiros numeros naturais primos:\n\n"); se (n > 0) { num := 1; cont := 0; enquanto (cont < n) { num := num + 1; div := 2; achou := falso; enquanto (achou = falso && div * div <= num) { resto := num % div; se (resto = 0) achou := verdade; senao div := div + 1; } se (achou = falso) { escrever (num, "\n"); cont := cont + 1; }}} senao escrever ("O valor de entrada deveria ser maior que zero"); senao escrever ("O valor de entrada deveria ser maior que zero");}
4
Um possível código intermediário não otimizado: Um possível código intermediário não otimizado: programa primos; var logic achou; int n, div, resto, cont, num; 1) OPENMOD, (MODULO, primos), (IDLE), (IDLE) ler (n); 2) PARAM, (VAR, n), (IDLE), (IDLE) 3) READ, (INT, 1), (IDLE), (IDLE)
5
se (n > 0) { - - - - - } 4) GT, (VAR, n), (INT, 0), (VAR, ##1) 5) JF, (VAR, ##1), (IDLE), (ROTULO, 42) - - - - - 42) NOP, (IDLE), (IDLE), (IDLE) num := 0; cont := 0; 6) ATRIB, (INT, 0), (IDLE), (VAR, num) 7) ATRIB, (INT, 0), (IDLE), (VAR, cont) NOP: no operation Todos os desvios serão feitos para quádruplas com NOPs Facilitam a programação Devem ser eliminadas na fase de otimização
6
enquanto (cont < n) { - - - - - } 8) NOP, (IDLE), (IDLE), (IDLE) 9) LT, (VAR, cont), (VAR, n), (VAR, ##2) 10) JF, (VAR, ##2), (IDLE), (ROTULO, 41) - - - - - 40) JUMP, (IDLE), (IDLE), (ROTULO, 8) 41) NOP, (IDLE), (IDLE), (IDLE) num := num + 1; div := 2; achou := falso; 11) MAIS, (VAR, num), (INT, 1), (VAR, ##3) 12) ATRIB, (VAR, ##3), (IDLE), (VAR, num) 13) ATRIB, (INT, 2), (IDLE), (VAR, div) 14) ATRIB, (LOGIC, 0), (IDLE), (VAR, achou) NOP: no operation Todos os desvios serão feitos para quádruplas com NOPs Facilitam a programação Devem ser eliminadas na fase de otimização
7
enquanto (achou = falso && div * div <= num) { - - - - - } 15) NOP, (IDLE), (IDLE), (IDLE) 16) EQ, (VAR, achou), (LOGIC, 0), (VAR, ##4) 17) MULT, (VAR, div), (VAR, div), (VAR, ##5) 18) LE, (VAR, ##5), (VAR, num), (VAR, ##6) 19) AND, (VAR, ##4), (VAR, ##6), (VAR, ##7) 20) JF, (VAR, ##7), (IDLE), (ROTULO, 32) - - - - - 31) JUMP, (IDLE), (IDLE), (ROTULO, 15) 32) NOP, (IDLE), (IDLE), (IDLE)
8
resto := num % div; se (resto = 0) achou := verdade; senao div := div + 1; 21) RESTO, (VAR, num), (VAR, div), (VAR, ##8) 22) ATRIB, (VAR, ##8), (IDLE), (VAR, resto) 23) EQ, (VAR, resto), (INT, 0), (VAR, ##9) 24) JF, (VAR, ##9), (IDLE), (ROTULO, 27) 25) ATRIB, (LOGIC, 1), (IDLE), (VAR, achou) 26) JUMP, (IDLE), (IDLE), (ROTULO, 30) 27) NOP, (IDLE), (IDLE), (IDLE) 28) MAIS, (VAR, div), (INT, 1), (VAR, ##10) 29) ATRIB, (VAR, ##10), (IDLE), (VAR, div) 30) NOP, (IDLE), (IDLE), (IDLE)
9
se (achou = falso) {escrever (num); cont := cont + 1;} 33) EQ, (VAR, achou), (LOGIC, 0), (VAR, ##11) 34) JF, (VAR, ##11), (IDLE), (ROTULO, 39) 35) PARAM, (VAR, num), (IDLE), (IDLE) 36) WRITE, 1, (IDLE), (IDLE) 37) MAIS, (VAR, cont), (INT, 1), (VAR, ##12) 38) ATRIB, (VAR, ##12), (IDLE), (VAR, cont) 39) NOP, (IDLE), (IDLE), (IDLE) Cada linha do código intermediário chama-se quádrupla
10
Estrutura de dados para o código intermediário de linguagens contendo subprogramas:
11
Cada lista de quádruplas fica acoplada a um mod-head As quádruplas do módulo prog destinam-se a: alocar as variáveis do programa principal (globais) executar o programa principal e encerrar tudo no final
12
A lista de mod-heads tem um nó-líder e cada lista de quádruplas também tem
13
Estrutura de dados para código intermediário de linguagens sem subprogramas: A primeira quádrupla é uma quádrupla-líder, sem conteúdo Esta estrutura será usada nas próximas aulas No projeto será usada a do slide anterior
14
Programa 4.1: O arquivo inter012013.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2013 O arquivo inter012013.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2013 O arquivo inter012013.l é seu analisador léxico O arquivo inter012013.l é seu analisador léxico O arquivo inter012013.y contém ainda declarações e funções para auxiliar a construção do código intermediário O arquivo inter012013.y contém ainda declarações e funções para auxiliar a construção do código intermediário Rodar esses arquivos com inter012013.dat Rodar esses arquivos com inter012013.dat A seguir, uma descrição dessas declarações e funções A seguir, uma descrição dessas declarações e funções
15
Estrutura de uma quádrupla: Estrutura de uma quádrupla: typedef struct celquad celquad; typedef celquad *quadrupla; struct celquad { int num, oper; operando opnd1, opnd2, result; quadrupla prox; }; O campo num numera as quádruplas O campo num numera as quádruplas Não é necessário na compilação Não é necessário na compilação Foi colocado por razões didáticas Foi colocado por razões didáticas Um operando tem dois campos: o tipo e o atributo Um operando tem dois campos: o tipo e o atributo operopnd1 opnd2result prox num celquad
16
Estrutura de um operando: Estrutura de um operando: typedef struct operando operando; struct operando { int tipo; atribopnd atr; }; Os tipos dos operandos são: Os tipos dos operandos são: Operando vazio (idle) Operando vazio (idle) Nome de variável Nome de variável Constantes inteira, real, lógica e caractere Constantes inteira, real, lógica e caractere Cadeia de caracteres Cadeia de caracteres Rótulo de quádruplas (ponteiro para quádruplas) Rótulo de quádruplas (ponteiro para quádruplas) Nome de módulo Nome de módulo tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) operando
17
Estrutura do atributo de um operando: Estrutura do atributo de um operando: typedef union atribopnd atribopnd; union atribopnd { simbolo simb; int valint; float valfloat; char valchar; char vallogic; char *valcad; quadrupla rotulo; modhead modulo; }; Tabela dos atributos conforme o tipo de operando: Tabela dos atributos conforme o tipo de operando: TipoAtributoTipoAtributo Idle-Constante caracterevalchar Nome de variávelsimbCadeia de caracteresvalcad Constante inteiravalintRótulo de quádruplarotulo Constante realvalfloatNome de módulomodulo Constante lógicavallogic tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) operando
18
Estrutura de um cabeçalho de módulo: Estrutura de um cabeçalho de módulo: typedef struct celmodhead celmodhead; typedef celmodhead *modhead; struct celmodhead { simbolo modname; modhead prox; int modtip; quadrupla listquad; }; modname modtip celmodhead prox listquad
19
Variáveis globais: Variáveis globais: quadrupla quadcorrente, quadaux; modhead codintermed, modcorrente; int oper, numquadcorrente; operando opnd1, opnd2, result, opndaux; int numtemp; const operando opndidle = {IDLEOPND, 0}; quadcorrente: ponteiro para a celquad recém-alocada quadcorrente: ponteiro para a celquad recém-alocada codintermed: ponteiro que dá acesso a todo o código intermediário codintermed: ponteiro que dá acesso a todo o código intermediário modcorrente: ponteiro para a última celmodhead alocada modcorrente: ponteiro para a última celmodhead alocada numtemp: usada para controlar a concessão de nomes a variáveis temporárias numtemp: usada para controlar a concessão de nomes a variáveis temporárias opndidle: constante do tipo operando para preencher operandos vazios nas quádruplas opndidle: constante do tipo operando para preencher operandos vazios nas quádruplas
20
Novas definições para os tipos dos identificadores: Novas definições para os tipos dos identificadores: Relembrando as definições para os tipos de variáveis: Relembrando as definições para os tipos de variáveis: #define IDPROG1 #define IDVAR2 #define IDFUNC3 #define IDPROC4 #define NOTVAR0 #define INTEGER1 #define LOGIC2 #define FLOAT3 #define CHAR4
21
Definições de constantes para operadores de quádruplas: Definições de constantes para operadores de quádruplas: #defineOPOR1 #defineOPAND2 #define OPLT 3 #define OPLE 4 #defineOPGT 5 #defineOPGE6 #defineOPEQ7 #defineOPNE8 #defineOPMAIS9 #defineOPMENOS10 #defineOPMULTIP11 #defineOPDIV12 #defineOPRESTO13 #defineOPMENUN14 #defineOPNOT15 #defineOPATRIB16 #defineOPENMOD17 #defineNOP18 #defineOPJUMP19 #defineOPJF20
22
Definições de constantes para os tipos dos operandos: Definições de constantes para os tipos dos operandos: #defineIDLEOPND0 #defineVAROPND1 #defineINTOPND2 #defineREALOPND3 #defineCHAROPND4 #defineLOGICOPND5 #defineCADOPND6 #defineROTOPND7 #defineMODOPND8
23
Protótipos das funções para o código intermediário: Protótipos das funções para o código intermediário: void InicCodIntermed (void); void InicCodIntermMod (simbolo); quadrupla GeraQuadrupla (int, operando, operando, operando); simbolo NovaTemp (int); void ImprimeQuadruplas (void); void RenumQuadruplas (quadrupla, quadrupla);
24
Função InicCodIntermed: Função InicCodIntermed: void InicCodIntermed () { codintermed = malloc (sizeof (celmodhead)); modcorrente = codintermed; modcorrente->listquad = NULL; modcorrente->listquad = NULL; modcorrente->prox = NULL; } codintermed modname modtip prox listquad modcorrente
25
Função InicCodIntermMod (simbolo simb): Função InicCodIntermMod (simbolo simb): void InicCodIntermMod (simbolo simb) { modcorrente->prox = malloc (sizeof (celmodhead)); modcorrente = modcorrente->prox; modcorrente->prox = NULL; modcorrente->modname = simb; modcorrente->modtip = simb->tid; modcorrente->listquad = malloc (sizeof (celquad)); quadcorrente = modcorrente->listquad; quadcorrente->prox = NULL; numquadcorrente = 0; quadcorrente->num = numquadcorrente; } codintermed simb num oper #### opnd1 #### opnd2 #### result #### prox quadcorrente 0 modname modtip prox listquad modname modtip prox listquad modcorrente cadeiatid
26
Função GeraQuadrupla (oper, opnd1, opnd2, result): Função GeraQuadrupla (oper, opnd1, opnd2, result): quadrupla GeraQuadrupla (int oper, operando opnd1, operando opnd2, operando result) { quadcorrente->prox = malloc (sizeof (celquad)); quadcorrente = quadcorrente->prox; quadcorrente->oper = oper; quadcorrente->opnd1 = opnd1; quadcorrente->opnd2 = opnd2; quadcorrente->result = result; quadcorrente->prox = NULL; numquadcorrente ++; quadcorrente->num = numquadcorrente; quadcorrente->num = numquadcorrente; return quadcorrente; return quadcorrente;} num 452 oper X opnd1 YYYY opnd2 ZZZZ result WWWW prox quadcorrente 453 R oper SSSS opnd1 TTTT opnd2 VVVV result TTTT SSSS VVVV R num oper opnd1 opnd2 result prox valor retornado
27
Função Novatemp (tip): Função Novatemp (tip): simbolo NovaTemp (int tip) { simbolo simb; int temp, i, j; char nometemp[10] = "##", s[10] = {0}; numtemp ++; temp = numtemp; for (i = 0; temp > 0; temp /= 10, i++) s[i] = temp % 10 + '0'; i --; for (j = 0; j <= i; j++) nometemp[2+i-j] = s[j]; simb = InsereSimb (nometemp, IDVAR, tip); simb->inic = simb->ref = TRUE; simb->array = FALSE; return simb; } Gera um nome para uma nova variável temporária O nome começa com ## e termina com um número O número é a soma do último utilizado +1 O nome é inserido na TabSimb e marcado como inicializado e referenciado Retorna um ponteiro para a célula inserida na TabSimb O tipo da nova variável vem como argumento
28
Os operandos para as quádruplas que calculam o valor de expressões devem estar nos atributos dos não-terminais para a montagem de expressões Os operandos para as quádruplas que calculam o valor de expressões devem estar nos atributos dos não-terminais para a montagem de expressões Exemplo: seja a produção Exemplo: seja a produção Termo : Termo OPMULT Fator Deve ser gerada a quádrupla com: operador correspondente ao atributo de OPMULT primeiro operando: no atributo de Termo do lado direito segundo operando: no atributo de Fator operando resultado: no atributo de Termo do lado esquerdo
29
Não-terminais para a montagem de expressões: Não-terminais para a montagem de expressões: Expressao, ExprAux1, ExprAux2, ExprAux3, ExprAux4, Termo, Fator Esses não-terminais já guardam seus tipos em seus atributos, para os testes de compatibilidade entre operadores e operandos: Esses não-terminais já guardam seus tipos em seus atributos, para os testes de compatibilidade entre operadores e operandos: %type Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator Agora, o atributo desses não-terminais deverá ter dois campos: Agora, o atributo desses não-terminais deverá ter dois campos: o tipo e o operando
30
Seja também a produção: Seja também a produção: Fator : Variavel É conveniente também que o não-terminal Variavel carregue um operando em seu atributo, para que o operando de Fator receba esse operando É conveniente também que o não-terminal Variavel carregue um operando em seu atributo, para que o operando de Fator receba esse operando Esse não-terminal já guarda em seu atributo um ponteiro para a TabSimb, para os testes de compatibilidade entre operadores e operandos: Esse não-terminal já guarda em seu atributo um ponteiro para a TabSimb, para os testes de compatibilidade entre operadores e operandos: %type Variavel %type Variavel Agora, o atributo desse não-terminal deverá ter dois campos: Agora, o atributo desse não-terminal deverá ter dois campos: o referido ponteiro e o operando
31
Novas declarações para atributos de expressões e variáveis: Novas declarações para atributos de expressões e variáveis: typedef struct infoexpressao infoexpressao; struct infoexpressao { int tipo; operando opnd; }; typedef struct infovariavel infovariavel; struct infovariavel { simbolo simb; operando opnd; }; Novos campos para a declaração %union: Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; char carac; infoexpressao infoexpr; infovariavel infovar; simbolo simb; int dim; int nsubscr; }
32
Novos campos para a declaração %union: Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; char carac; infoexpressao infoexpr; infovariavel infovar; simbolo simb; int dim; int nsubscr; simbolo simb; int dim; int nsubscr;} Novas especificações para os atributos dos não-terminais envolvidos: Novas especificações para os atributos dos não-terminais envolvidos: %type Variavel %type Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator Antes era
33
Nas produções onde aparecem não-terminais envolvidos no cálculo de expressões foi trocado $$ por $$.tipo e $1, $2, etc. por $1.tipo, $2.tipo, etc. Nas produções onde aparecem não-terminais envolvidos no cálculo de expressões foi trocado $$ por $$.tipo e $1, $2, etc. por $1.tipo, $2.tipo, etc. Nas ocorrências de atributos do não terminal Variavel, foi trocado $$ por $$.simb e $1, $2, etc. por $1.simb, $2.simb, etc. Nas ocorrências de atributos do não terminal Variavel, foi trocado $$ por $$.simb e $1, $2, etc. por $1.simb, $2.simb, etc.
34
Exercício 4.1: Inicializar o código intermediário e a lista de quádruplas do único módulo, imprimindo-as (a lista é vazia) Na produção do não-terminal Prog: Na produção do não-terminal Prog: Prog:{ InicTabSimb (); InicCodIntermed (); numtemp = 0; } PROGRAMA ID PVIRG { printf ("programa %s ;\n", $3); simb = InsereSimb ($3, IDPROG, NOTVAR); simb = InsereSimb ($3, IDPROG, NOTVAR); InicCodIntermMod (simb); InicCodIntermMod (simb); } Decls CmdComp { VerificaInicRef (); ImprimeTabSimb (); VerificaInicRef (); ImprimeTabSimb (); ImprimeQuadruplas (); ImprimeQuadruplas (); }; Acrescentar ao arquivo inter012013.y o código em destaque Rodar com o arquivo inter012013.dat
35
Exercício 4.2: Inserir a quádrupla OPENMOD Ainda na produção do não-terminal Prog: Ainda na produção do não-terminal Prog: Prog:{- - - - -} PROGRAMA ID PVIRG { - - - - - InicCodIntermMod (simb); InicCodIntermMod (simb); opnd1.tipo = MODOPND; opnd1.tipo = MODOPND; opnd1.atr.modulo = modcorrente; opnd1.atr.modulo = modcorrente; GeraQuadrupla (OPENMOD, opnd1, opndidle, opndidle); GeraQuadrupla (OPENMOD, opnd1, opndidle, opndidle); } Decls CmdComp { - - - - - - - - - - }; Acrescentar ao arquivo inter012013. y o código em destaque Rodar com o arquivo inter012013. dat
36
Exercício 4.3: Inserir quádruplas para expressões sem variáveis indexadas Exemplo: as quádruplas para a expressão: Exemplo: as quádruplas para a expressão: (i+3 >= j-2) && b2 sendo: int i, j; logic b2; podem ser: MAIS, (VAR, i), (INT, 3), (VAR, ##1) MENOS, (VAR, j), (INT, 2), (VAR, ##2) GE, (VAR, ##1), (VAR, ##2), (VAR, ##3) AND, (VAR, ##3), (VAR, b2), (VAR, ##4)
37
É necessária uma programação em todos os não-terminais envolvendo expressões É necessária uma programação em todos os não-terminais envolvendo expressões Em toda produção que contribui para a formação de expressões, deve-se calcular o atributo operando do não- terminal do lado esquerdo Em toda produção que contribui para a formação de expressões, deve-se calcular o atributo operando do não- terminal do lado esquerdo Numa produção onde aparece operador de expressões, além desse cálculo, deve-se gerar quádrupla com a operação correspondente e com os atributos operandos dos não- terminais de expressões Numa produção onde aparece operador de expressões, além desse cálculo, deve-se gerar quádrupla com a operação correspondente e com os atributos operandos dos não- terminais de expressões
38
Na 1ª produção do não-terminal Variavel (sem subscritos), calcula-se seu operando: Na 1ª produção do não-terminal Variavel (sem subscritos), calcula-se seu operando: Variavel: ID {- - - - - $$.simb = simb; $$.simb = simb; if ($$.simb != NULL) { if ($$.simb != NULL) { if (- - - - -) Esperado ("Subscrito\(s)"); $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = $$.simb; $$.opnd.atr.simb = $$.simb; }};
39
Nas produções sem operadores do não-terminal Fator, calcula-se seu operando: Nas produções sem operadores do não-terminal Fator, calcula-se seu operando: Fator: Variavel { if ($1.simb != NULL) { - - - - - $$.tipo = $1.simb->tvar; $$.opnd = $1.opnd; } } | CTINT { - - - - - $$.tipo = INTEGER; $$.opnd.tipo = INTOPND; $$.opnd.tipo = INTOPND; $$.opnd.atr.valint = $1; } | CTREAL { - - - - - $$.tipo = FLOAT; | CTREAL { - - - - - $$.tipo = FLOAT; $$.opnd.tipo = REALOPND; $$.opnd.tipo = REALOPND; $$.opnd.atr.valfloat = $1; }
40
Fator: CTCARAC { - - - - - $$.tipo = CHAR; Fator: CTCARAC { - - - - - $$.tipo = CHAR; $$.opnd.tipo = CHAROPND; $$.opnd.tipo = CHAROPND; $$.opnd.atr.valchar = $1; } | VERDADE { - - - - - $$.tipo = LOGICAL; | VERDADE { - - - - - $$.tipo = LOGICAL; $$.opnd.tipo = LOGICOPND; $$.opnd.tipo = LOGICOPND; $$.opnd.atr.vallogic = 1; } | FALSO { - - - - - $$.tipo = LOGICAL; | FALSO { - - - - - $$.tipo = LOGICAL; $$.opnd.tipo = LOGICOPND; $$.opnd.tipo = LOGICOPND; $$.opnd.atr.vallogic = 0; } | ABPAR {- - - - -} Expressao FPAR { - - - - - $$.tipo = $3.tipo; $$.opnd = $3.opnd; }
41
Na produção do não-terminal Fator, com o operador NEG gera-se uma quádrupla, além de calcular o operando do lado esquerdo: Na produção do não-terminal Fator, com o operador NEG gera-se uma quádrupla, além de calcular o operando do lado esquerdo: Fator: NEG {- - - - -} Fator { if ( - - - - - ) Incompatibilidade ( - - - - - ); if ($3.tipo == FLOAT) $$.tipo = FLOAT; else $$.tipo = INTEGER; $$.opnd.tipo = VAROPND; $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = NovaTemp ($$.tipo); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd);}; Rodar com o arquivo inter012013. dat
42
Produções do não-terminal Termo: Produções do não-terminal Termo: Termo : Fator /* default: $$ = $1 */ |Termo OPMULT {- - - - -} Fator { switch ($2) { case MULT: case DIV: - - - - - $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = NovaTemp ($$.tipo); if ($2 == MULT) GeraQuadrupla (OPMULTIP, $1.opnd, $4.opnd, $$.opnd); GeraQuadrupla (OPMULTIP, $1.opnd, $4.opnd, $$.opnd); else GeraQuadrupla (OPDIV, $1.opnd, $4.opnd, $$.opnd); break; case RESTO: - - - - - $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = NovaTemp ($$.tipo); GeraQuadrupla (OPRESTO, $1.opnd, $4.opnd, $$.opnd); break;}}; Rodar com o arquivo inter012013. dat Fazer programação análoga para as produções dos não terminais ExprAux4, ExprAux3, ExprAux2, ExprAux1 e Expressao
43
Exercício 4.4: Inserir quádruplas para comandos de atribuição Exemplo: as quádruplas para a atribuição: Exemplo: as quádruplas para a atribuição: b1 := (i+3 >= j-2) && b2 sendo: int i, j; logic b1, b2; podem ser: MAIS, (VAR, i), (INT, 3), (VAR, ##1) MENOS, (VAR, j), (INT, 2), (VAR, ##2) GE, (VAR, ##1), (VAR, ##2), (VAR, ##3) AND, (VAR, ##3), (VAR, b2), (VAR, ##4) ATRIB, (VAR, ##4), (IDLE), (VAR, b1)
44
Exercício 4.5: Inserir quádruplas para comandos condicionais Primeiramente, sejam os comandos se sem senao Primeiramente, sejam os comandos se sem senao Exemplo: as quádruplas para o comando Exemplo: as quádruplas para o comando se (i < j) { i = i+3; n := v/h; } podem ser: 2) LT, (VAR, i), (VAR, j), (VAR, ##1) 2) LT, (VAR, i), (VAR, j), (VAR, ##1) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 8) NOP, (IDLE), (IDLE), (IDLE) 8) NOP, (IDLE), (IDLE), (IDLE) Usar os arquivos inter022013.y, inter022013.l e inter022013.dat
45
Arquivo inter022013.y: Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição Função RenumQuadruplas (q1, q2): Função RenumQuadruplas (q1, q2): Algumas quádruplas serão geradas fora de ordem Algumas quádruplas serão geradas fora de ordem Sua ordem deve ser corrigida Sua ordem deve ser corrigida Para fins didáticos, as quádruplas serão renumeradas Para fins didáticos, as quádruplas serão renumeradas Abrir o arquivo inter022013.dat Abrir o arquivo inter022013.dat Rodar flex, yacc, gcc e executável gerado Rodar flex, yacc, gcc e executável gerado A cada implementação, alterar os comentários em inter022013.dat A cada implementação, alterar os comentários em inter022013.dat
46
A programação para se sem senao está na produção do não- terminal CmdSe: A programação para se sem senao está na produção do não- terminal CmdSe: CmdSe: SE ABPAR {- - - - -} Expressao { - - - - - - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao ; É necessário acrescentar o campo quad na declaração %union: quadrupla quad;
47
A programação para se sem senao está na produção do não- terminal CmdSe: A programação para se sem senao está na produção do não- terminal CmdSe: CmdSe: SE ABPAR {- - - - -} Expressao { - - - - - - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao ; No arquivo inter022013.dat, tirar o comentário do se sem senao e rodar
48
CmdSe: SE ABPAR {- - - - -} Expressao { - - - - - - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao ; Expressao ----- ##nJF##n-----ROT $5 Comando NOP----- A quádrupla destino do desvio é gerada na produção de CmdSe NOP é eliminada na otimização do código intermediário ?
49
Sejam agora os comandos se com senao Sejam agora os comandos se com senao Exemplo: as quádruplas para os comandos Exemplo: as quádruplas para os comandos se (i < j) { i := i+3; n := v/h; } senao { v := h; i := j; } n := v; podem ser: 2) LT, (VAR, i), (VAR, j), (VAR, ##1) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 9) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 8) JUMP, (IDLE), (IDLE), (ROTULO, 12) 9) NOP, (IDLE), (IDLE), (IDLE) 10) ATRIB, (VAR, h), (IDLE), (VAR, v) 11) ATRIB, (VAR, j), (IDLE), (VAR, i) 12) NOP, (IDLE), (IDLE), (IDLE) 13) ATRIB, (VAR, v), (IDLE), (VAR, n)
50
A programação para se com senao está nas produções dos não-terminais CmdSe e CmdSenao: A programação para se com senao está nas produções dos não-terminais CmdSe e CmdSenao: CmdSe: SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $ $ = quadcorrente; $ $ = quadcorrente; $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao { if ($ 9->prox != quadcorrente) { quadaux = $ 9->prox; $ 9->prox = quadaux->prox; quadaux->prox = $ 9->prox->prox; $ 9->prox->prox = quadaux; RenumQuadruplas ($ 9, quadcorrente); }};
51
CmdSenao: | SENAO { - - - - - - - - - - opndaux.tipo = ROTOPND; opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { } Comando { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; No arquivo inter022013.dat, tirar o comentário do se com senao e rodar
52
CmdSe: SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {- - - - -} Comando { $ $ = quadcorrente; $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao {- - - - -} ; Expressao ----- ##nJF##n-----ROT Comando NOP----- $5 $9
53
CmdSenao:| SENAO { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expressao ----- ##nJF##n-----ROT Comando NOP----- $5 $9 JUMP----- ROT $2 As quádruplas NOP e JUMP foram geradas em ordem trocada ?
54
CmdSenao:| SENAO { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expressao ----- ##nJF##n-----ROT Comando NOP----- $5 $9 JUMP----- ROT $2 Comando NOP----- É preciso inverter a ordem das quádruplas NOP e JUMP ?
55
CmdSe: SE ABPAR {- - - - -} Expressao {- - - - -} FPAR {- - - - -} Comando { - - - - -} CmdSenao { if ($ 9->prox != quadcorrente) { quadaux = $ 9->prox; $ 9->prox = quadaux->prox; quadaux->prox = $<quad>9->prox->prox; $ 9->prox->prox = quadaux; RenumQuadruplas ($ 9, quadcorrente); }}; Comando NOP----- $9 JUMP----- ROT Comando NOP----- Se a quádrupla seguinte à $9 for a quádrupla corrente, o se não tem senao – não é preciso fazer troca quadaux
56
Exercício 4.6: Inserir quádruplas para o comando enquanto Exemplo: as quádruplas para o comando Exemplo: as quádruplas para o comando enquanto (i < j) i := j + h; i := 0; podem ser: 2) NOP, (IDLE), (IDLE), (IDLE) 2) NOP, (IDLE), (IDLE), (IDLE) 3) LT, (VAR, i), (VAR, j), (VAR, ##1) 3) LT, (VAR, i), (VAR, j), (VAR, ##1) 4) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 4) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 5) MAIS, (VAR, j), (VAR, h), (VAR, ##2) 5) MAIS, (VAR, j), (VAR, h), (VAR, ##2) 6) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 6) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 7) JUMP, (IDLE), (IDLE), (ROTULO, 2) 7) JUMP, (IDLE), (IDLE), (ROTULO, 2) 8) NOP, (IDLE), (IDLE), (IDLE) 8) NOP, (IDLE), (IDLE), (IDLE) 9) ATRIB, (INT, 0), (IDLE), (VAR, i) 9) ATRIB, (INT, 0), (IDLE), (VAR, i)
57
CmdEnquanto: ENQUANTO ABPAR Expressao FPAR Comando ; Expressao ----- ##nJF##n-----ROT Comando NOP----- NOP----- JUMP----- ROT ?
58
Exercício 4.7: Inserir quádruplas para comandos ler e escrever Exemplo: as quádruplas para os comandos Exemplo: as quádruplas para os comandos ler (a, b, c); escrever ("Valor de a+b:", a+b, "Valor de c:", c); podem ser: 2) PARAM, (VAR, a), (IDLE), (IDLE) 3) PARAM, (VAR, b), (IDLE), (IDLE) 4) PARAM, (VAR, c), (IDLE), (IDLE) 5) READ, (INT, 3), (IDLE), (IDLE) 6) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE), (IDLE) 9) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 10) PARAM, (VAR, c), (IDLE), (IDLE) 11) WRITE, (INT, 4), (IDLE), (IDLE) Os operadores de quádruplas PARAM, OPREAD e OPWRITE já estão declarados no programa inter022013.y
59
2) PARAM, (VAR, a), (IDLE), (IDLE) 3) PARAM, (VAR, b), (IDLE), (IDLE) 4) PARAM, (VAR, c), (IDLE), (IDLE) 5) READ, (INT, 3), (IDLE), (IDLE) 6) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE), (IDLE) 9) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 10) PARAM, (VAR, c), (IDLE), (IDLE) 11) WRITE, (INT, 4), (IDLE), (IDLE) Elementos de escrita também podem ser operandos de quádruplas São úteis contadores de argumentos para os comandos ler e escrever Isso será feito nas produções dos não-terminais ListVar e ListEscr
60
O atributo dos não-terminais ListVar e ListEscr deve ser o número de argumentos de suas listas O atributo dos não-terminais ListVar e ListEscr deve ser o número de argumentos de suas listas Deve-se acrescentar mais um campo na declaração %union: Deve-se acrescentar mais um campo na declaração %union: %union { - - - - - int nsubscr, nargs; - - - - - } Declaração do atributo dos não terminais ListVar e ListEscr: Declaração do atributo dos não terminais ListVar e ListEscr: %type ListVar ListEscr
61
Tal como uma expressão, o não terminal ElemEscr deve ter um operando de quádrupla Tal como uma expressão, o não terminal ElemEscr deve ter um operando de quádrupla Então deve haver uma declaração %type para ele: Então deve haver uma declaração %type para ele: %type Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator ElemEscr
62
Programação para o não-terminal ListVar que é usado na produção do não-terminal CmdLer: Programação para o não-terminal ListVar que é usado na produção do não-terminal CmdLer: ListVar: Variavel { - - - - - $$ = 1; GeraQuadrupla (PARAM, $1.opnd, opndidle, opndidle); } | ListVar VIRG { - - - - - } Variavel { - - - - - $$ = $1 + 1; GeraQuadrupla (PARAM, $4.opnd, opndidle, opndidle); }; $$ é o contador de argumentos de um comando ler
63
Programação para o não-terminal CmdLer: Programação para o não-terminal CmdLer: CmdLer: LER ABPAR { - - - - -} ListVar{ opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPREAD, opnd1, opndidle, opndidle); } FPAR PVIRG {printf (") ;\n");} ;
64
Programação para o não-terminal ElemEscr: Programação para o não-terminal ElemEscr: ElemEscr: CADEIA { printf ("%s ", $1); $$.opnd.tipo = CADOPND; $$.opnd.atr.valcad = malloc (strlen($1) + 1); strcpy ($$.opnd.atr.valcad, $1); } | Expressao/* default: $$ = $1 */ ; Obs.: $$.tipo da 1ª produção do não-terminal ElemEscr não é usado Portanto não é calculado
65
Programação para o não-terminal ListEscr: Programação para o não-terminal ListEscr: ListEscr: ElemEscr { $$ = 1; GeraQuadrupla (PARAM, $1.opnd, opndidle, opndidle); } | ListEscr VIRG {printf (", ");} ElemEscr { $$ = $1 + 1; GeraQuadrupla (PARAM, $4.opnd, opndidle, opndidle); }; $$ é o contador de argumentos de um comando escrever
66
Programação para o não-terminal CmdEscrever: Programação para o não-terminal CmdEscrever: CmdEscrever: ESCREVER ABPAR {- - - - -} ListEscr { opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPWRITE, opnd1, opndidle, opndidle); } FPAR PVIRG {printf (") ;\n");} ; No arquivo inter022013.dat, tirar o comentário dos comandos ler e escrever e rodar
67
Exercício 4.8: Inserir quádruplas para indexação Sejam as seguintes declarações e comandos: Sejam as seguintes declarações e comandos: int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); Acesso a um elemento genérico A[i,j]: Acesso a um elemento genérico A[i,j]: Uma vez conhecido o endereço inicial da matriz A, é necessário localizar o elemento A[i,j] Uma vez conhecido o endereço inicial da matriz A, é necessário localizar o elemento A[i,j] Seja a seguir o mapa de A[6,5] na memória: Seja a seguir o mapa de A[6,5] na memória:
68
Seja m o número de linhas e n o número de colunas da matriz A Seja m o número de linhas e n o número de colunas da matriz A O endereço do elemento A[i,j] é dado pela fórmula: O endereço do elemento A[i,j] é dado pela fórmula: Ender (A) + i * n + j Para m := 6, n := 5, o endereço de A[4,3] é Para m := 6, n := 5, o endereço de A[4,3] é Ender (A) + 23
69
No programa, cada índice pode ser uma expressão inteira No programa, cada índice pode ser uma expressão inteira Calcula-se o valor de cada índice, empilhando-o numa pilha de índices Calcula-se o valor de cada índice, empilhando-o numa pilha de índices Isso pode ser feito pela execução de uma quádrupla de operador IND: Isso pode ser feito pela execução de uma quádrupla de operador IND: IND, i, ----, ---- IND, i, ----, ---- IND, j, ----, ---- IND, j, ----, ----
70
Calcula-se o endereço de A[i,j], usando uma quádrupla de operador INDEX: Calcula-se o endereço de A[i,j], usando uma quádrupla de operador INDEX: INDEX, A, 2, temp1 Sua execução consiste em: Sua execução consiste em: Pegar as dimensões e o endereço de A na tabela de símbolos Pegar as dimensões e o endereço de A na tabela de símbolos Desempilhar dois índices Desempilhar dois índices Calcular o endereço, colocando-o na variável temp1 Calcular o endereço, colocando-o na variável temp1 A variável temp1 é portanto um ponteiro A variável temp1 é portanto um ponteiro
71
Quando o elemento A[i,j] está numa expressão, necessita-se do conteúdo do local apontado por temp1 Quando o elemento A[i,j] está numa expressão, necessita-se do conteúdo do local apontado por temp1 Para isso, pode-se usar uma quádrupla de operador CONTAPONT: Para isso, pode-se usar uma quádrupla de operador CONTAPONT: CONTAPONT, temp1, ----, temp2 int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); temp2 recebe o conteúdo do local apontado por temp1
72
Quando o elemento A[i,j] vai receber uma atribuição, o local apontado por temp1 é que vai receber isso Quando o elemento A[i,j] vai receber uma atribuição, o local apontado por temp1 é que vai receber isso Então, pode-se usar uma quádrupla de operador ATRIBPONT: Então, pode-se usar uma quádrupla de operador ATRIBPONT: ATRIBPONT, tempexpr, ----, temp1 int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); O local apontado por temp1 recebe o conteúdo de tempexpr
73
Quando o elemento A[i,j] vai receber um valor lido: Quando o elemento A[i,j] vai receber um valor lido: O valor lido é guardado numa temporária O valor lido é guardado numa temporária O local apontado por temp1 recebe o valor dessa temporária O local apontado por temp1 recebe o valor dessa temporária É conveniente colocar a leitura do elemento de uma variável indexada numa quádrupla separada: Duas quádruplas OPREAD int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); PARAM, tempread, ----, ---- OPREAD, 1, ----, ---- ATRIBPONT, tempread, ----, temp1
74
Exemplo: seja o seguinte programa: Exemplo: seja o seguinte programa: programa teste; var int i, j, k, A[10,10]; { i := 7; j := 5; k := A[i-3,j+2] + 5; A[10-i,9-j] := i + j * k; ler (i, j, A[2,3], k); ler (A[1,2]); } A seguir suas possíveis quádruplas
75
programa teste; var int i, j, k, A[10,10]; 1) OPENMOD, (MODULO, teste), (IDLE), (IDLE) { i := 7; j := 5; 2) ATRIB, (INT, 7), (IDLE), (VAR, i) 3) ATRIB, (INT, 5), (IDLE), (VAR, j)
76
k := A[i-3,j+2] + 5; 4) MENOS, (VAR, i), (INT, 3), (VAR, ##1) 5) IND, (VAR, ##1), (IDLE), (IDLE) 6) MAIS, (VAR, j), (INT, 2), (VAR, ##2) 7) IND, (VAR, ##2), (IDLE), (IDLE) 8) INDEX, (VAR, A), (INT, 2), (VAR, ##3) 9) CONTAPONT, (VAR, ##3), (IDLE), (VAR, ##4) 10) MAIS, (VAR, ##4), (INT, 5), (VAR, ##5) 11) ATRIB, (VAR, ##5), (IDLE), (VAR, k)
77
A[10-i,9-j] := i + j * k; 12) MENOS, (INT, 10), (VAR, i), (VAR, ##6) 13) IND, (VAR, ##6), (IDLE), (IDLE) 14) MENOS, (INT, 9), (VAR, j), (VAR, ##7) 15) IND, (VAR, ##7), (IDLE), (IDLE) 16) INDEX, (VAR, A), (INT, 2), (VAR, ##8) 17) MULT, (VAR, j), (VAR, k), (VAR, ##9) 18) MAIS, (VAR, i), (VAR, ##9), (VAR, ##10) 19) ATRIBPONT, (VAR, ##10), (IDLE), (VAR, ##8)
78
ler (i, j, A[2,3], k); 20) PARAM, (VAR, i), (IDLE), (IDLE) 21) PARAM, (VAR, j), (IDLE), (IDLE) 22) READ, (INT, 2), (IDLE), (IDLE) 23) IND, (INT, 2), (IDLE), (IDLE) 24) IND, (INT, 3), (IDLE), (IDLE) 25) INDEX, (VAR, A), (INT, 2), (VAR, ##11) 26) PARAM, (VAR, ##12), (IDLE), (IDLE) 27) READ, (INT, 1), (IDLE), (IDLE) 28) ATRIBPONT, (VAR, ##12), (IDLE), (VAR, ##11) 29) PARAM, (VAR, k), (IDLE), (IDLE) 30) READ, (INT, 1), (IDLE), (IDLE)
79
ler (A[1,2]); } 31) IND, (INT, 1), (IDLE), (IDLE) 32) IND, (INT, 2), (IDLE), (IDLE) 33) INDEX, (VAR, A), (INT, 2), (VAR, ##13) 34) PARAM, (VAR, ##14), (IDLE), (IDLE) 35) READ, (INT, 1), (IDLE), (IDLE) 36) ATRIBPONT, (VAR, ##14), (IDLE), (VAR, ##13)
Apresentações semelhantes
© 2024 SlidePlayer.com.br Inc.
All rights reserved.