CES41 COMPILADORES Aulas Prticas 2019 Captulo IV Cdigo

  • Slides: 79
Download presentation
CES-41 COMPILADORES Aulas Práticas - 2019 Capítulo IV Código Intermediário no Yacc

CES-41 COMPILADORES Aulas Práticas - 2019 Capítulo IV Código Intermediário no Yacc

n O sub-set da Linguagem COMP-ITA-2019, usado no final do capítulo anterior, contém: -

n O sub-set da Linguagem COMP-ITA-2019, usado no final do capítulo anterior, contém: - Comandos de atribuição, compostos, de entrada e saída, condicionais, while, variáveis escalares e indexadas n Seja essa linguagem chamada de Sub-Set 2 2019 n Seja o programa a seguir, escrito em Sub-Set 2 2019, para encontrar números primos

program Primos { local: logic achou; int n, div, resto, cont, num; statements: read

program Primos { local: logic achou; int n, div, resto, cont, num; statements: read (n); if (n > 0) { num <- 1; cont <- 0; while (cont < n) { num <- num + 1; div <- 2; achou <- false; while (achou = false && div * div <= num) { resto <- num % div; if (resto = 0) achou <- true; else div <- div + 1; } if (achou = false) { write (num, "n"); cont <- cont + 1; } }

n Um possível código intermediário não otimizado: program Primos { local: logic achou; int

n Um possível código intermediário não otimizado: program Primos { local: logic achou; int n, div, resto, cont, num; 1) OPENMOD, (MODULO, Primos), (IDLE) read (n); 2) PARAM, (VAR, n), (IDLE) 3) READ, (INT, 1), (IDLE)

if (n > 0) { - - } NOP: no operation Todos os desvios

if (n > 0) { - - } NOP: no operation Todos os desvios serão feitos para quádruplas com NOP’s 4) GT, (VAR, n), (INT, 0), (VAR, ##1) 5) JF, (VAR, ##1), (IDLE), (ROTULO, 42) Facilitam a programação - - Devem ser eliminadas na 42) NOP, (IDLE), (IDLE) fase de otimização num <- 1; cont <- 0; 6) ATRIB, (INT, 1), (IDLE), (VAR, num) 7) ATRIB, (INT, 0), (IDLE), (VAR, cont)

while (cont < n) { - - } NOP: no operation Todos os desvios

while (cont < n) { - - } NOP: no operation Todos os desvios serão feitos para quádruplas com NOP’s 8) NOP, (IDLE), (IDLE) 9) LT, (VAR, cont), (VAR, n), (VAR, ##2) 10) JF, (VAR, ##2), (IDLE), (ROTULO, 41) Facilitam a programação - - Devem ser eliminadas na 40) JUMP, (IDLE), (ROTULO, 8) fase de otimização 41) NOP, (IDLE), (IDLE) num <- num + 1; div <- 2; achou <- false; 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)

while (achou = false && div * div <= num) { - - }

while (achou = false && div * div <= num) { - - } 15) NOP, (IDLE), (IDLE) 16) EQ, (VAR, achou), (LOGIC, 0), (VAR, ##4) 17) MULT, (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), (ROTULO, 15) 32) NOP, (IDLE), (IDLE)

resto <- num % div; if (resto = 0) achou <- true; else div

resto <- num % div; if (resto = 0) achou <- true; else 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), (ROTULO, 30) 27) NOP, (IDLE), (IDLE) 28) MAIS, (VAR, div), (INT, 1), (VAR, ##10) 29) ATRIB, (VAR, ##10), (IDLE), (VAR, div) 30) NOP, (IDLE), (IDLE)

if (achou = false) {write (num); cont <- cont + 1; } 33) EQ,

if (achou = false) {write (num); cont <- cont + 1; } 33) EQ, (VAR, achou), (LOGIC, 0), (VAR, ##11) 34) JF, (VAR, ##11), (IDLE), (ROTULO, 39) 35) PARAM, (VAR, num), (IDLE) 36) WRITE, 1, (IDLE) 37) MAIS, (VAR, cont), (INT, 1), (VAR, ##12) 38) ATRIB, (VAR, ##12), (IDLE), (VAR, cont) 39) NOP, (IDLE), (IDLE) Cada linha do código intermediário chama-se quádrupla

Estrutura de dados para o código intermediário de linguagens contendo subprogramas:

Estrutura de dados para o código intermediário de linguagens contendo subprogramas:

Cada lista de quádruplas fica acoplada a um modhead Cada lista de quádruplas tem

Cada lista de quádruplas fica acoplada a um modhead Cada lista de quádruplas tem um nó-lider As quádruplas do módulo Analise destinam-se a: Alocar as variáveis globais Acionar a execução do módulo principal (main) E encerrar tudo no final

Estrutura de dados para código intermediário de linguagens sem subprogramas: O primeiro modhead seria

Estrutura de dados para código intermediário de linguagens sem subprogramas: O primeiro modhead seria dispensável Ele é usado prevendo a implementação do módulo global

A primeira quádrupla é uma quádrupla-líder, sem conteúdo Esta estrutura será usada nas próximas

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

Programa 4. 1: n O arquivo inter 012019. y tem um analisador semântico quase

Programa 4. 1: n O arquivo inter 012019. y tem um analisador semântico quase acabado para a linguagem Sub-Set 2 2019 n O arquivo inter 012019. l é seu analisador léxico n O arquivo inter 012019. y contém ainda declarações e funções para auxiliar a construção do código intermediário n Rodar esses arquivos com inter 012019. dat n A seguir, uma descrição dessas declarações e

celquad Estrutura de uma quádrupla: num n oper typedef struct celquad; opnd 2 typedef

celquad Estrutura de uma quádrupla: num n oper typedef struct celquad; opnd 2 typedef celquad *quadrupla; prox struct celquad { int num, oper; operando opnd 1, opnd 2, result; quadrupla prox; }; n opnd 1 result O campo numera as quádruplas Não é necessário na compilação - Foi colocado por razões didáticas - n Um operando tem dois campos: o tipo e o atributo

n Estrutura de um operando: typedef struct operando; struct operando { int tipo; atribopnd

n Estrutura de um operando: typedef struct operando; struct operando { int tipo; atribopnd atr; }; n operando tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) Os tipos dos operandos são: - Operando vazio (idle) Nome de variável Constantes inteira, real, lógica e caractere Cadeia de caracteres Rótulo de quádruplas (ponteiro para quádruplas) Nome de módulo

n Estrutura do atributo de um operando: operando tipo typedef union atribopnd; atr union

n Estrutura do atributo de um operando: operando tipo typedef union atribopnd; atr union atribopnd { (simb, valint, valfloat, simbolo simb; int valint; float valfloat; valchar, vallogic, valcad, rotulo, modulo) char valchar; char vallogic; char *valcad; quadrupla rotulo; modhead modulo; }; n Tabela dos atributos conforme o tipo de operando: Tipo Idle Atributo Tipo Atributo - Constante caractere valchar Nome de variável simb Cadeia de caracteres valcad Constante inteira valint Rótulo de quádrupla rotulo Constante real valfloat Constante lógica vallogic Nome de módulo modulo

n Estrutura de um cabeçalho de módulo: celmodhead modname prox listquad typedef struct celmodhead;

n Estrutura de um cabeçalho de módulo: celmodhead modname prox listquad typedef struct celmodhead; typedef celmodhead *modhead; struct celmodhead { simbolo modname; modhead prox; quadrupla listquad; };

n Variáveis globais: quadrupla quadcorrente, quadaux; modhead codintermed, modcorrente; int oper, numquadcorrente; operando opnd

n Variáveis globais: quadrupla quadcorrente, quadaux; modhead codintermed, modcorrente; int oper, numquadcorrente; operando opnd 1, opnd 2, result, opndaux; int numtemp; const operando opndidle = {IDLEOPND, 0}; n quadcorrente: ponteiro para a celquad recém-alocada n codintermed: ponteiro que dá acesso a todo o código intermediário n modcorrente: ponteiro para a última celmodhead alocada n numtemp: usada para controlar a concessão de nomes a variáveis temporárias n opndidle: constante do tipo operando para preencher

n Novas definições para os tipos dos identificadores: #define n IDPROG IDVAR IDFUNC 1

n Novas definições para os tipos dos identificadores: #define n IDPROG IDVAR IDFUNC 1 2 3 Relembrando as definições para os tipos de variáveis: #define NAOVAR 0 #define INTEIRO LOGICO REAL CARACTERE 1 2 3 4

n Definições de constantes para operadores de quádruplas: #define #define #define n OPOR OPAND

n Definições de constantes para operadores de quádruplas: #define #define #define n OPOR OPAND OPLT OPLE 4 OPGT OPGE OPEQ OPNE OPMAIS OPMENOS 1 2 3 5 6 7 8 9 10 #define #define #define Esta lista deverá aumentar durante o OPMULTIP OPDIV OPRESTO OPMENUN OPNOT OPATRIB OPENMOD NOP OPJUMP OPJF 11 12 13 14 15 16 17 18 19 20

n Definições de constantes para os tipos dos operandos: #define #define #define IDLEOPND VAROPND

n Definições de constantes para os tipos dos operandos: #define #define #define IDLEOPND VAROPND INTOPND REALOPND CHAROPND LOGICOPND CADOPND ROTOPND MODOPND 0 1 2 3 4 5 6 7 8

n Protótipos das funções para o código intermediário: void Inic. Cod. Intermed (void); void

n Protótipos das funções para o código intermediário: void Inic. Cod. Intermed (void); void Inic. Cod. Interm. Mod (simbolo); quadrupla Gera. Quadrupla (int, operando, operando); simbolo Nova. Temp (int); void Imprime. Quadruplas (void); void Renum. Quadruplas (quadrupla, quadrupla);

n codintermed Função Inic. Cod. Intermed: modname prox ● ● listquad modcorrente void Inic.

n codintermed Função Inic. Cod. Intermed: modname prox ● ● listquad modcorrente void Inic. Cod. Intermed () { codintermed = malloc (sizeof (celmodhead)); modcorrente = codintermed; modcorrente->listquad = NULL; modcorrente->prox = NULL; }

n Função Inic. Cod. Interm. Mod (simbolo simb): codintermed simb cadeia tid modname prox

n Função Inic. Cod. Interm. Mod (simbolo simb): codintermed simb cadeia tid modname prox ● ● listquad modname prox ● listquad void Inic. Cod. Interm. Mod (simbolo simb) { modcorrente->prox = malloc (sizeof (celmodhead)); modcorrente = modcorrente->prox; modcorrente->prox = NULL; 0 num modcorrente->modname = simb; oper #### modcorrente->listquad = malloc (sizeof (celquad)); opnd 1 #### quadcorrente = modcorrente->listquad; opnd 2 #### quadcorrente->prox = NULL; result #### numquadcorrente = 0; prox ● quadcorrente->num = numquadcorrente; quadcorrent } e

n Função Gera. Quadrupla (oper, opnd 1, opnd 2, result): quadrupla Gera. Quadrupla (int

n Função Gera. Quadrupla (oper, opnd 1, opnd 2, result): quadrupla Gera. Quadrupla (int oper, operando opnd 1, operando opnd 2, operando result) { num 452 quadcorrente->prox = malloc (sizeof (celquad)); oper X opnd 1 YYYY quadcorrente = quadcorrente->prox; opnd 2 ZZZZ quadcorrente->oper = oper; result WWWW quadcorrente->opnd 1 = opnd 1; ● prox quadcorrente->opnd 2 = opnd 2; quadcorrente->result = result; 453 num e R oper quadcorrente->prox = NULL; opnd 1 SSSS numquadcorrente ++; opnd 2 TTTT quadcorrente->num = numquadcorrente; opnd 2 TTTT result VVVV valor return quadcorrente; retornado prox ● oper R opnd 1 SSSS result VVVV }

n Função Novatemp (tip): Gera um nome para uma nova variável temporária simbolo Nova.

n Função Novatemp (tip): Gera um nome para uma nova variável temporária simbolo Nova. Temp (int tip) { O nome começa com ## e termina com um número simbolo simb; int temp, i, j; char nometemp[10] = "##", s[10] = {0}; O número é a soma do último utilizado +1 numtemp ++; temp = numtemp; for (i = 0; temp > 0; temp /= 10, i++) O nome é inserido na s[i] = temp % 10 + '0'; Tab. Simb e marcado como inicializado e referenciado i --; for (j = 0; j <= i; j++) Retorna um ponteiro para a célula inserida na Tab. Simb nometemp[2+i-j] = s[j]; simb = Insere. Simb (nometemp, IDVAR, tip); simb->inic = simb->ref = VERDADE; simb->array = FALSO; return simb; O tipo da nova variável vem como argumento }

n Os operandos para as quádruplas que calculam o valor de expressões devem estar

n 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 n Exemplo: seja a produção Term : Term MULTOP Factor Deve ser gerada a quádrupla com: operador correspondente ao atributo de MULTOP primeiro operando: no atributo de Term do lado direito segundo operando: no atributo de Factor operando resultado: no atributo de Term do lado esquerdo

n Não-terminais para a montagem de expressões: Expression, Aux. Expr 1, Aux. Expx 2,

n Não-terminais para a montagem de expressões: Expression, Aux. Expr 1, Aux. Expx 2, Aux. Expr 3, Aux. Expr 4, Term, Factor n Esses não-terminais já guardam seus tipos em seus atributos, para os testes de compatibilidade entre operadores e operandos: %type <tipoexpr> Expression Aux. Expr 1 Aux. Expx 2 Aux. Expr 3 Aux. Expr 4 Term Factor n Agora, o atributo desses não-terminais deverá ter dois campos: o tipo e o operando

n Seja também a produção: Factor : Variable n É conveniente também que o

n Seja também a produção: Factor : Variable n É conveniente também que o não-terminal Variable carregue um operando em seu atributo, para que o operando de Factor receba esse operando n Esse não-terminal já guarda em seu atributo um ponteiro para a Tab. Simb, para os testes de compatibilidade entre operadores e operandos: %type <simb> Variable n Agora, o atributo desse não-terminal deverá ter dois campos:

n Novas declarações para atributos de expressões e variáveis: typedef struct infoexpressao; struct infoexpressao

n Novas declarações para atributos de expressões e variáveis: typedef struct infoexpressao; struct infoexpressao { int tipo; operando opnd; }; typedef struct infovariavel; struct infovariavel { simbolo simb; operando opnd; }; n 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;

n Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint;

n 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; } n Novas especificações para os atributos dos nãoterminais envolvidos: Antes era <simb> %type <infovar> %type <infoexpr> Factor Variable Expression Aux. Expr 1 Aux. Expr 2 Aux. Expr 3 Aux. Expr 4 Term Antes era <tipoexpr>

n Nas produções onde aparecem não-terminais envolvidos no cálculo de expressões foi trocado $$

n 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. n Nas ocorrências de atributos do não terminal Variable, foi trocado $$ por $$. simb e $1, $2, etc. por $1. simb, $2. simb, etc.

Exercício 4. 1: Inicializar o código intermediário e a lista de quádruplas do único

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) n Na produção do não-terminal Prog: Prog : { Inic. Tab. Simb (); Inic. Cod. Intermed (); numtemp = 0; } PROGRAM ID OPBRACE {printf ("program %s {n", $3); simb = Insere. Simb ($3, IDPROG, NAOVAR); Inic. Cod. Interm. Mod (simb); } Decls Stats CLBRACE {printf ("}n"); Acrescentar ao arquivo Verifica. Inic. Ref (); Imprime. Tab. Simb (); inter 012019. y o código em destaque Imprime. Quadruplas (); Rodar com o arquivo } inter 012019. dat ;

Exercício 4. 2: Inserir a quádrupla OPENMOD n Ainda na produção do não-terminal Prog:

Exercício 4. 2: Inserir a quádrupla OPENMOD n Ainda na produção do não-terminal Prog: {- - -} PROGRAM ID OPBRACE { ----Inic. Cod. Interm. Mod (simb); opnd 1. tipo = MODOPND; opnd 1. atr. modulo = modcorrente; Gera. Quadrupla (OPENMOD, opnd 1, opndidle, opndidle); } Decls Stats CLBRACE { Acrescentar ao arquivo ----inter 012019. y o código em destaque } Rodar com o arquivo ; inter 012019. dat

Exercício 4. 3: Inserir quádruplas para expressões sem variáveis indexadas n Exemplo: as quádruplas

Exercício 4. 3: Inserir quádruplas para expressões sem variáveis indexadas n Exemplo: as quádruplas para a expressão: (i+3 >= j-2) && b 2 sendo: int i, j; logic b 2; 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, b 2), (VAR, ##4)

n É necessária uma programação em todos os nãoterminais envolvendo expressões n Em toda

n É necessária uma programação em todos os nãoterminais envolvendo expressões n 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 n 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 não-terminais de expressões

n Na produção do não-terminal Variable, calcula-se seu operando, quando não há subscritos: Variable:

n Na produção do não-terminal Variable, calcula-se seu operando, quando não há subscritos: Variable: ID { - - - } Subscripts { $$. simb = $<simb>2; if ($$. simb != NULL) { if ($$. simb->array == FALSO && - - -) - - else if ($$. simb->array == VERDADE && - -) - - - else if ($$. simb->ndims != $3) Incompatibilidade (- - - -); $$. opnd. tipo = VAROPND; if ($3 == 0) $$. opnd. atr. simb = $$. simb; } }

n Nas produções sem operadores do não-terminal Factor, calcula-se seu operando: Factor : Variable

n Nas produções sem operadores do não-terminal Factor, calcula-se seu operando: Factor : Variable { if ($1. simb != NULL) { - - - $$. tipo = $1. simb->tvar; $$. opnd = $1. opnd; } } | INTCT { - - - $$. tipo = INTEIRO; $$. opnd. tipo = INTOPND; $$. opnd. atr. valint = $1; } | FLOATCT { - - - $$. tipo = REAL; $$. opnd. tipo = REALOPND; $$. opnd. atr. valfloat = $1; }

Factor: CHARCT { - - - $$. tipo = CARACTERE; $$. opnd. tipo =

Factor: CHARCT { - - - $$. tipo = CARACTERE; $$. opnd. tipo = CHAROPND; $$. opnd. atr. valchar = $1; } | TRUE { - - - $$. tipo = LOGICO; $$. opnd. tipo = LOGICOPND; $$. opnd. atr. vallogic = 1; } | FALSE { - - - $$. tipo = LOGICO; $$. opnd. tipo = LOGICOPND; $$. opnd. atr. vallogic = 0; } | OPPAR {- - -} Expression CLPAR { - - - $$. tipo = $3. tipo; $$. opnd = $3. opnd; }

n Na produção do não-terminal Factor, com o operador NEG gera-se uma quádrupla, além

n Na produção do não-terminal Factor, com o operador NEG gera-se uma quádrupla, além de calcular o operando do lado esquerdo: Factor : NEG {- - -} Factor { if ( - - - ) Incompatibilidade ( - - - ); if ($3. tipo == REAL) $$. tipo = REAL; else $$. tipo = INTEIRO; $$. opnd. tipo = VAROPND; $$. opnd. atr. simb = Nova. Temp ($$. tipo); Gera. Quadrupla (OPMENUN, $3. opnd, opndidle, $$. opnd); } ; Rodar com o arquivo inter 012019. dat

n Produções do não-terminal Term: Term : Factor /* default: $$ = $1 */

n Produções do não-terminal Term: Term : Factor /* default: $$ = $1 */ | Term MULTOP {- - -} Factor { switch ($2) { case MULT: case DIV: - - $$. opnd. tipo = VAROPND; $$. opnd. atr. simb = Nova. Temp ($$. tipo); if ($2 == MULT) Gera. Quadrupla (OPMULTIP, $1. opnd, $4. opnd, $$. opnd); else Gera. Quadrupla (OPDIV, $1. opnd, $4. opnd, $$. opnd);

Exercício 4. 4: Inserir quádruplas para comandos de atribuição n Exemplo: as quádruplas para

Exercício 4. 4: Inserir quádruplas para comandos de atribuição n Exemplo: as quádruplas para a atribuição: b 1 <- (i+3 >= j-2) && b 2; sendo: int i, j; logic b 1, b 2; 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, b 2), (VAR, ##4) ATRIB, (VAR, ##4), (IDLE), (VAR, b 1)

Exercício 4. 5: Inserir quádruplas para comandos condicionais n Primeiramente, sejam os comandos if

Exercício 4. 5: Inserir quádruplas para comandos condicionais n Primeiramente, sejam os comandos if sem else n Exemplo: as quádruplas para o comando if (i < j) { i <- i+3; n <- v/h; } podem ser: 2) LT, (VAR, i), (VAR, j), (VAR, ##1) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 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) Usar os arquivos inter 022019. y, inter 022019. l e inter 022019. dat

Arquivo inter 022019. y: n Gera quádruplas para abrir módulo, operadores de expressões e

Arquivo inter 022019. y: n Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição n Função Renum. Quadruplas (q 1, q 2): - n n n Algumas quádruplas serão geradas fora de ordem Sua ordem deve ser corrigida Para fins didáticos, as quádruplas serão renumeradas Abrir o arquivo inter 022019. dat Rodar flex, yacc, gcc e executável gerado A cada implementação, alterar os comentários em

n A programação para if sem else está na produção do não-terminal If. Stat:

n A programação para if sem else está na produção do não-terminal If. Stat: If. Stat : IF OPPAR {- - -} Expression { ----opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJF, $4. opnd, opndidle, opndaux); } CLPAR {printf (“)n"); } Statement { $<quad>5 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } Else. Stat É necessário acrescentar o campo quad na ; declaração %union: quadrupla quad;

n A programação para if sem else está na produção do não-terminal If. Stat:

n A programação para if sem else está na produção do não-terminal If. Stat: If. Stat : IF OPPAR {- - -} Expression { ----opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJF, $4. opnd, opndidle, opndaux); } CLPAR {printf (“)n"); } Statement { $<quad>5 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } Else. Stat No arquivo inter 022019. dat, tirar o comentário do if sem else e rodar ;

If. Stat : IF {- - -} OPPAR Expression { ----opndaux. tipo = ROTOPND;

If. Stat : IF {- - -} OPPAR Expression { ----opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJF, $4. opnd, opndidle, opndaux); } CLPAR {printf (“)n"); } Statement { $<quad>5 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } Else. Stat ; $5 Expression A quádrupla destino do desvio é gerada na produção de If. Stat NOP é eliminada na otimização do código intermediário ----- ##n JF ##n ----- ROT Statement NOP ----- ?

n Sejam agora os comandos if com else n Exemplo: as quádruplas para os

n Sejam agora os comandos if com else n Exemplo: as quádruplas para os comandos if (i < j) { i <- i+3; n <- v/h; } else { v <- h; i <- j; } n <- v; 2) LT, (VAR, i), (VAR, j), (VAR, ##1) podem ser: 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), (ROTULO, 12) 9) NOP, (IDLE), (IDLE) 10) ATRIB, (VAR, h), (IDLE), (VAR, v) 11) ATRIB, (VAR, j), (IDLE), (VAR, i) 12) NOP, (IDLE), (IDLE) 13) ATRIB, (VAR, v), (IDLE), (VAR, n)

n A programação para if com else está nas produções dos não-terminais If. Stat

n A programação para if com else está nas produções dos não-terminais If. Stat e Else. Stat: If. Stat : IF { - - - } OPPAR Expression { - - opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJF, $4. opnd, opndidle, opndaux); } CLPAR {printf (")n"); } Statement { $<quad>$ = quadcorrente; $<quad>5 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } Else. Stat { if ($<quad>9 ->prox != quadcorrente) { quadaux = $<quad>9 ->prox; $<quad>9 ->prox = quadaux->prox; quadaux->prox = $<quad>9 ->prox; $<quad>9 ->prox = quadaux; Renum. Quadruplas ($<quad>9, quadcorrente); } } ;

Else. Stat : | ELSE { ----opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla

Else. Stat : | ELSE { ----opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJUMP, opndidle, opndaux); } Statement { $<quad>2 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } ; No arquivo inter 022019. dat, tirar o comentário do if com else e rodar

If. Stat : IF { - - - } OPPAR Expression { - -

If. Stat : IF { - - - } OPPAR Expression { - - opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJF, $4. opnd, opndidle, opndaux); } CLPAR {printf (")n"); } Statement { $<quad>$ = quadcorrente; $<quad>5 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } Else. Stat { - - - } ; $5 Expression $9 ----- ##n JF ##n ----- ROT Statement NOP -----

Else. Stat : | ELSE { - - opndaux. tipo = ROTOPND; $<quad>$ =

Else. Stat : | ELSE { - - opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJUMP, opndidle, opndaux); } Statement { $<quad>2 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } JUMP -----ROT Expression $2 ; $5 ----- ##n JF ##n ----- ROT Statement $9 NOP ----- As quádruplas NOP e JUMP foram geradas em ordem trocada ?

Else. Stat : | ELSE { - - opndaux. tipo = ROTOPND; $<quad>$ =

Else. Stat : | ELSE { - - opndaux. tipo = ROTOPND; $<quad>$ = Gera. Quadrupla (OPJUMP, opndidle, opndaux); } Statement { $<quad>2 ->result. atr. rotulo = Gera. Quadrupla (NOP, opndidle, opndidle); } JUMP -----ROT Expression $2 ; $5 ----- ##n JF ##n ----- ROT NOP Statement $9 NOP ----- Statement ----- É preciso inverter a ordem das quádruplas NOP e JUMP ?

If. Stat : IF {- - -} OPPAR Expression {- - -} CLPAR {-

If. Stat : IF {- - -} OPPAR Expression {- - -} CLPAR {- - -} Statement { - - -} Else. Stat { if ($<quad>9 ->prox != quadcorrente) { Statement $9 quadaux = $<quad>9 ->prox; $<quad>9 ->prox = quadaux->prox; quadaux->prox = $<quad>9 ->prox; $<quad>9 ->prox = quadaux; Renum. Quadruplas ($<quad>9, quadaux); NOP JUMP ----- ----- ROT quadaux Statement } } ; Se a quádrupla seguinte à $9 for a quádrupla corrente, o if não tem else – não é preciso fazer troca NOP -----

Exercício 4. 6: Inserir quádruplas para o comando while n Exemplo: as quádruplas para

Exercício 4. 6: Inserir quádruplas para o comando while n Exemplo: as quádruplas para o comando while (i < j) i <- j + h; i <- 0; podem ser: 2) NOP, (IDLE), (IDLE) 3) LT, (VAR, i), (VAR, j), (VAR, ##1) 4) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 5) MAIS, (VAR, j), (VAR, h), (VAR, ##2) 6) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 7) JUMP, (IDLE), (ROTULO, 2) 8) NOP, (IDLE), (IDLE) 9) ATRIB, (INT, 0), (IDLE), (VAR, i)

While. Stat : WHILE OPPAR Expression CLPAR Statement ; NOP ----- Expression ----- ##n

While. Stat : WHILE OPPAR Expression CLPAR Statement ; NOP ----- Expression ----- ##n JF ##n ----- ROT Statement JUMP NOP ----- ROT ----- ?

Exercício 4. 7: Inserir quádruplas para comandos read e write n Exemplo: as quádruplas

Exercício 4. 7: Inserir quádruplas para comandos read e write n Exemplo: as quádruplas para os comandos read (a, b, c); write ("Valor de a+b: ", a+b, "Valor de c: ", c); podem ser: Os operadores de quádruplas PARAM, OPREAD e OPWRITE já estão declarados no programa inter 022019. y 2) PARAM, (VAR, a), (IDLE) 3) PARAM, (VAR, b), (IDLE) 4) PARAM, (VAR, c), (IDLE) 5) READ, (INT, 3), (IDLE) 6) PARAM, (CADEIA, Valor de a+b: ), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE) 9) PARAM, (CADEIA, Valor de c: ), (IDLE) 10) PARAM, (VAR, c), (IDLE)

2) PARAM, (VAR, a), (IDLE) 3) PARAM, (VAR, b), (IDLE) 4) PARAM, (VAR, c),

2) PARAM, (VAR, a), (IDLE) 3) PARAM, (VAR, b), (IDLE) 4) PARAM, (VAR, c), (IDLE) 5) READ, (INT, 3), (IDLE) 6) PARAM, (CADEIA, Valor de a+b: ), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE) 9) PARAM, (CADEIA, Valor de c: ), (IDLE) 10) PARAM, (VAR, c), (IDLE) 11) WRITE, (INT, 4), (IDLE) Elementos de escrita também podem ser operandos de quádruplas São úteis contadores de argumentos para os comandos read e write Isso será feito nas produções dos nãoterminais Read. List e Write. List

n O atributo dos não-terminais Read. List e Write. List deve ser o número

n O atributo dos não-terminais Read. List e Write. List deve ser o número de argumentos de suas listas n Deve-se acrescentar mais um campo na declaração %union: %union { ----int nsubscr, nargs; ----} n Declaração do atributo dos não terminais Read. List e Write. List: %type <nargs> Read. List Write. List

n Tal como uma expressão, o não terminal Write. Elem terá um operando de

n Tal como uma expressão, o não terminal Write. Elem terá um operando de quádrupla n Então deve haver uma declaração %type para ele: %type Aux. Expr 2 Term <infoexpr> Expression Aux. Expr 1 Aux. Expr 3 Aux. Expr 4 Factor Write. Elem

n Programação para o não-terminal Read. List que é usado na produção do não-terminal

n Programação para o não-terminal Read. List que é usado na produção do não-terminal Read. Stat: Read. List : Variable { - - $$ = 1; Gera. Quadrupla (PARAM, $1. opnd, opndidle); } | Read. List COMMA { - - - } Variable { - - $$ = $1 + 1; Gera. Quadrupla (PARAM, $4. opnd, opndidle); } ; $$ é o contador de argumentos de um comando read

n Programação para o não-terminal Read. Stat: Read. Stat : READ OPPAR { -

n Programação para o não-terminal Read. Stat: Read. Stat : READ OPPAR { - - -} Read. List { opnd 1. tipo = INTOPND; opnd 1. atr. valint = $4; Gera. Quadrupla (OPREAD, opnd 1, opndidle); } CLPAR SCOLON {printf (") ; n"); } ;

n Programação para o não-terminal Write. Elem: Write. Elem : STRING { printf ("%s

n Programação para o não-terminal Write. Elem: Write. Elem : STRING { printf ("%s ", $1); $$. opnd. tipo = CADOPND; $$. opnd. atr. valcad = malloc (strlen($1) + 1); strcpy ($$. opnd. atr. valcad, $1); } | Expression /* default: $$ = $1 */ ; Obs. : $$. tipo da 1ª produção do não-terminal Write. Elem não é usado Portanto não é calculado

n Programação para o não-terminal Write. List: Write. List : Write. Elem { $$

n Programação para o não-terminal Write. List: Write. List : Write. Elem { $$ = 1; Gera. Quadrupla (PARAM, $1. opnd, opndidle); } | Write. List COMMA {printf (", "); } Write. Elem { $$ = $1 + 1; Gera. Quadrupla (PARAM, $4. opnd, opndidle); } ; $$ é o contador de argumentos de um comando write

n Programação para o não-terminal Write. Stat: Write. Stat : WRITE OPPAR {- -

n Programação para o não-terminal Write. Stat: Write. Stat : WRITE OPPAR {- - -} Write. List { opnd 1. tipo = INTOPND; opnd 1. atr. valint = $4; Gera. Quadrupla (OPWRITE, opnd 1, opndidle); } CLPAR SCOLON {printf (") ; n"); } ; No arquivo inter 022019. dat, tirar o comentário dos comandos read e write e rodar

Exercício 4. 8: Inserir quádruplas para indexação n Sejam as seguintes declarações e comandos:

Exercício 4. 8: Inserir quádruplas para indexação n 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; read (i, j, A[i+j, 2*i-j]); n Acesso a um elemento genérico A[i, j]: - n 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:

n Seja m o número de linhas e n o número de colunas da

n Seja m o número de linhas e n o número de colunas da matriz A n O endereço do elemento A[i, j] é dado pela fórmula: Ender (A) + i * n + j n Para m = 6, n = 5, o endereço de A[4, 3] é Ender (A) + 23

n No programa, cada índice pode ser uma expressão inteira Exemplo: A[10 -i, 2*j+3]

n No programa, cada índice pode ser uma expressão inteira Exemplo: A[10 -i, 2*j+3] n Calcula-se o valor de cada índice, empilhando-o numa pilha de índices n Isso pode ser feito pela execução de uma quádrupla de operador IND: IND, i , ---- , --- IND, j , ----

n Calcula-se o endereço de A[i, j], usando uma quádrupla de operador INDEX: INDEX

n Calcula-se o endereço de A[i, j], usando uma quádrupla de operador INDEX: INDEX , A , 2 , temp 1 n Sua execução consiste em: - Pegar as dimensões e o endereço de A na tabela de símbolos - Desempilhar dois índices - Calcular o endereço, colocando-o na variável temp 1 n A variável temp 1 é portanto

n Quando o elemento A[i, j] está numa expressão, necessita-se do conteúdo do local

n Quando o elemento A[i, j] está numa expressão, necessita-se do conteúdo do local apontado por temp 1 n Para isso, pode-se usar uma quádrupla de operador CONTAPONT: CONTAPONT , temp 1 , ---- , temp 2 recebe o conteúdo do local apontado por temp 1 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; read (i, j, A[i+j, 2*i-j]);

n Quando o elemento A[i, j] vai receber uma atribuição, o local apontado por

n Quando o elemento A[i, j] vai receber uma atribuição, o local apontado por temp 1 é que vai receber isso n Então, pode-se usar uma quádrupla de operador ATRIBPONT: ATRIBPONT , tempexpr , ---- , temp 1 O local apontado por temp 1 recebe o conteúdo de tempexpr 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; read (i, j, A[i+j, 2*i-j]);

n Quando o elemento A[i, j] vai receber um valor lido: O valor lido

n Quando o elemento A[i, j] vai receber um valor lido: O valor lido é guardado numa nova temporária - O local apontado por temp 1 recebe o valor dessa temporária - PARAM , tempread , ---- , --- OPREAD , 1 , ---- , ---ATRIBPONT , tempread , ---- , temp 1 É 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; read (i, j, A[i+j, 2*i-j]);

n Exemplo: seja o seguinte programa: program teste { local: int i, j, k,

n Exemplo: seja o seguinte programa: program teste { local: int i, j, k, A[10, 10]; statements: i <- 7; j <- 5; k <- A[i-3, j+2] + 5; A[10 -i, 9 -j] <- i + j * k; read (i, j, A[2, 3], k); read (A[1, 2]); } A seguir suas possíveis quádruplas

program teste { local: int i, j, k, A[10, 10]; 1) OPENMOD, (MODULO, teste),

program teste { local: int i, j, k, A[10, 10]; 1) OPENMOD, (MODULO, teste), (IDLE) statements: i <- 7; j <- 5; 2) ATRIB, (INT, 7), (IDLE), (VAR, i) 3) ATRIB, (INT, 5), (IDLE), (VAR, j)

k <- A[i-3, j+2] + 5; 4) MENOS, (VAR, i), (INT, 3), (VAR, ##1)

k <- A[i-3, j+2] + 5; 4) MENOS, (VAR, i), (INT, 3), (VAR, ##1) 5) IND, (VAR, ##1), (IDLE) 6) MAIS, (VAR, j), (INT, 2), (VAR, ##2) 7) IND, (VAR, ##2), (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)

A[10 -i, 9 -j] <- i + j * k; 12) MENOS, (INT, 10),

A[10 -i, 9 -j] <- i + j * k; 12) MENOS, (INT, 10), (VAR, i), (VAR, ##6) 13) IND, (VAR, ##6), (IDLE) 14) MENOS, (INT, 9), (VAR, j), (VAR, ##7) 15) IND, (VAR, ##7), (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)

read (i, j, A[2, 3], k); 20) PARAM, (VAR, i), (IDLE) 21) PARAM, (VAR,

read (i, j, A[2, 3], k); 20) PARAM, (VAR, i), (IDLE) 21) PARAM, (VAR, j), (IDLE) 22) READ, (INT, 2), (IDLE) 23) IND, (INT, 2), (IDLE) 24) IND, (INT, 3), (IDLE) 25) INDEX, (VAR, A), (INT, 2), (VAR, ##11) 26) PARAM, (VAR, ##12), (IDLE) 27) READ, (INT, 1), (IDLE) 28) ATRIBPONT, (VAR, ##12), (IDLE), (VAR, ##11) 29) PARAM, (VAR, k), (IDLE) 30) READ, (INT, 1), (IDLE)

read (A[1, 2]); } 31) IND, (INT, 1), (IDLE) 32) IND, (INT, 2), (IDLE)

read (A[1, 2]); } 31) IND, (INT, 1), (IDLE) 32) IND, (INT, 2), (IDLE) 33) INDEX, (VAR, A), (INT, 2), (VAR, ##13) 34) PARAM, (VAR, ##14), (IDLE) 35) READ, (INT, 1), (IDLE) 36) ATRIBPONT, (VAR, ##14), (IDLE), (VAR, ##13)