0 then { num = 1; cont = 0; while cont < n do { num = num + 1; div = 2; achou = false; while achou == false && div * div <= num do { resto = num % div; if resto == 0 then achou = true; else div = div + 1; } if achou == false then { write (num, "\n"); cont = cont + 1; }}}}"> 0 then { num = 1; cont = 0; while cont < n do { num = num + 1; div = 2; achou = false; while achou == false && div * div <= num do { resto = num % div; if resto == 0 then achou = true; else div = div + 1; } if achou == false then { write (num, "\n"); cont = cont + 1; }}}}">

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

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

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

Apresentações semelhantes


Apresentação em tema: "CES-41 COMPILADORES Aulas Práticas - 2015 Capítulo IV Código Intermediário no Yacc."— Transcrição da apresentação:

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

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

3 program primos local {logic achou; int n, div, resto, cont, num;} statements { read (n); write (n, " primeiros numeros naturais primos:\n\n"); write (n, " primeiros numeros naturais primos:\n\n"); if n > 0 then { num = 1; cont = 0; while cont < n do { num = num + 1; div = 2; achou = false; while achou == false && div * div <= num do { resto = num % div; if resto == 0 then achou = true; else div = div + 1; } if achou == false then { write (num, "\n"); cont = cont + 1; }}}}

4 Um possível código intermediário não otimizado: 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), (IDLE) read (n); 2) PARAM, (VAR, n), (IDLE), (IDLE) 3) READ, (INT, 1), (IDLE), (IDLE)

5 if n > 0 then { - - - - - } 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 NOP’s Facilitam a programação Devem ser eliminadas na fase de otimização

6 while cont < n do { - - - - - } 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 = 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) NOP: no operation Todos os desvios serão feitos para quádruplas com NOP’s Facilitam a programação Devem ser eliminadas na fase de otimização

7 while achou == false && div * div <= num do { - - - - - } 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; if resto == 0 then 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), (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 if achou == false then {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), (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 de tipo glob destinam-se a: Alocar as variáveis globais Acionar a execução do módulo principal (main) E encerrar tudo no final Cada lista de quádruplas tem um nó-lider

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

13 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 inter012015.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2015 O arquivo inter012015.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2015 O arquivo inter012015.l é seu analisador léxico O arquivo inter012015.l é seu analisador léxico O arquivo inter012015.y contém ainda declarações e funções para auxiliar a construção do código intermediário O arquivo inter012015.y contém ainda declarações e funções para auxiliar a construção do código intermediário Rodar esses arquivos com inter012015.dat Rodar esses arquivos com inter012015.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  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)  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 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 IDGLOB5 #define NAOVAR0 #define INTEIRO1 #define LOGICO2 #define REAL3 #define CARACTERE4

21 Definições de constantes para operadores de quádruplas: Definições de constantes para operadores de quádruplas: Esta lista deverá aumentar durante o desenvolvimento do projeto Esta lista deverá aumentar durante o desenvolvimento do projeto #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 = VERDADE; simb->array = FALSO; 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 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

29 Não-terminais para a montagem de expressões: Não-terminais para a montagem de expressões: Expression, AuxExpr1, AuxExpx2, AuxExpr3, AuxExpr4, Term, Factor 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 Expression AuxExpr1 AuxExpx2 AuxExpr3 AuxExpr4 Term Factor 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: Factor : Variable É conveniente também que o não-terminal Variable carregue um operando em seu atributo, para que o operando de Factor receba esse operando É conveniente também que o não-terminal Variable carregue um operando em seu atributo, para que o operando de Factor 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 Variable %type Variable 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 Variable %type Expression AuxExpr1 AuxExpr2 AuxExpr3 AuxExpr4 Term Factor 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 Variable, foi trocado $$ por $$.simb e $1, $2, etc. por $1.simb, $2.simb, etc. Nas ocorrências de atributos do não terminal Variable, 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; InicTabSimb (); InicCodIntermed (); numtemp = 0; } PROGRAM ID {printf ("program %s\n", $3); } PROGRAM ID {printf ("program %s\n", $3); simb = InsereSimb ($3, IDPROG, NAOVAR); simb = InsereSimb ($3, IDPROG, NAOVAR); InicCodIntermMod (simb); InicCodIntermMod (simb); } LocDecls Stats { } LocDecls Stats { VerificaInicRef (); ImprimeTabSimb (); VerificaInicRef (); ImprimeTabSimb (); ImprimeQuadruplas (); }; Acrescentar ao arquivo inter012015.y o código em destaque Rodar com o arquivo inter012015.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:{- - - - -} PROGRAM ID { - - - - - 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); } LocDecls Stats { - - - - - - - - - - }; Acrescentar ao arquivo inter012015.y o código em destaque Rodar com o arquivo inter012015.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 Variable (sem subscritos), calcula-se seu operando: Na 1ª produção do não-terminal Variable (sem subscritos), calcula-se seu operando: Variable: ID { - - - - - $$.simb = simb; $$.simb = simb; if ($$.simb != NULL) { if ($$.simb != NULL) { if ($$.simb->array == VERDADE) if ($$.simb->array == VERDADE) Esperado ("Subscrito\(s)"); $$.opnd.tipo = VAROPND; $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = $$.simb; $$.opnd.atr.simb = $$.simb; } }

39 Nas produções sem operadores do não-terminal Factor, calcula-se seu operando: 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.tipo = INTOPND; $$.opnd.atr.valint = $1; } | FLOATCT { - - - - - $$.tipo = REAL; | FLOATCT { - - - - - $$.tipo = REAL; $$.opnd.tipo = REALOPND; $$.opnd.tipo = REALOPND; $$.opnd.atr.valfloat = $1; }

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

41 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: 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.tipo = VAROPND; $$.opnd.atr.simb = NovaTemp ($$.tipo); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd);}; Rodar com o arquivo inter012015. dat

42 Produções do não-terminal Term: 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 = 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 inter012015. 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 if sem else Primeiramente, sejam os comandos if sem else Exemplo: as quádruplas para o comando Exemplo: as quádruplas para o comando if i < j then { 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 inter022015.y, inter022015.l e inter022015.dat

45 Arquivo inter022015.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  Sua ordem deve ser corrigida  Para fins didáticos, as quádruplas serão renumeradas Abrir o arquivo inter022015.dat Abrir o arquivo inter022015.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 inter022015.dat A cada implementação, alterar os comentários em inter022015.dat

46 A programação para if sem else está na produção do não- terminal IfStat: A programação para if sem else está na produção do não- terminal IfStat: IfStat: IF {- - - - -} Expression { - - - - - opndaux.tipo = ROTOPND; $ $ = $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $ 4->result.atr.rotulo = $ 4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat } ElseStat; É necessário acrescentar o campo quad na declaração %union: quadrupla quad;

47 A programação para if sem else está na produção do não- terminal IfStat: A programação para if sem else está na produção do não- terminal IfStat: IfStat: IF {- - - - -} Expression { - - - - - opndaux.tipo = ROTOPND; $ $ = $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $ 4->result.atr.rotulo = $ 4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat } ElseStat; No arquivo inter022015.dat, tirar o comentário do if sem else e rodar

48 IfStat: IF {- - - - -} Expression { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $ 4->result.atr.rotulo = $ 4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat } ElseStat; Expression ----- ##nJF##n-----ROT $4 Statement NOP----- A quádrupla destino do desvio é gerada na produção de IfStat NOP é eliminada na otimização do código intermediário ?

49 Sejam agora os comandos if com else Sejam agora os comandos if com else Exemplo: as quádruplas para os comandos Exemplo: as quádruplas para os comandos if i < j then { i = i+3; n = v/h; } else { 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 if com else está nas produções dos não- terminais IfStat e ElseStat: A programação para if com else está nas produções dos não- terminais IfStat e ElseStat: IfStat: IF { - - - - - } Expression { - - - - - opndaux.tipo = ROTOPND; opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $ $ = quadcorrente; $ $ = quadcorrente; $ 4->result.atr.rotulo = $ 4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat { } ElseStat { if ($ 8->prox != quadcorrente) { if ($ 8->prox != quadcorrente) { quadaux = $ 8->prox; quadaux = $ 8->prox; $ 8->prox = quadaux->prox; $ 8->prox = quadaux->prox; quadaux->prox = $ 8->prox->prox; quadaux->prox = $ 8->prox->prox; $ 8->prox->prox = quadaux; $ 8->prox->prox = quadaux; RenumQuadruplas ($ 8, quadcorrente); RenumQuadruplas ($ 8, quadcorrente); } };

51 ElseStat: | ELSE { - - - - - - - - - - opndaux.tipo = ROTOPND; opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Statement { } Statement { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; No arquivo inter022015.dat, tirar o comentário do if com else e rodar

52 IfStat: IF { - - - - - } Expression { - - - - - opndaux.tipo = ROTOPND; opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); $ $ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $ $ = quadcorrente; $ $ = quadcorrente; $ 4->result.atr.rotulo = $ 4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat { - - - - - } } ElseStat { - - - - - }; Expression ----- ##nJF##n-----ROT Statement NOP----- $4 $8

53 ElseStat:| ELSE { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Statement { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expression ----- ##nJF##n-----ROT Statement NOP----- $4 $8 JUMP----- ROT $2 As quádruplas NOP e JUMP foram geradas em ordem trocada ?

54 ElseStat:| ELSE { - - - - - opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Statement { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expression ----- ##nJF##n-----ROT Statement NOP----- $4 $8 JUMP----- ROT $2 Statement NOP----- É preciso inverter a ordem das quádruplas NOP e JUMP ?

55 IfStat: IF {- - - - -} Expression {- - - - -} THEN {- - - - -} Statement { - - - - -} ElseStat { if ($ 8->prox != quadcorrente) { quadaux = $ 8->prox; $ 8->prox = quadaux->prox; quadaux->prox = $<quad>8->prox->prox; $ 8->prox->prox = quadaux; RenumQuadruplas ($ 8, quadaux); }}; Statement NOP----- $8 JUMP----- ROT Statement NOP----- Se a quádrupla seguinte à $8 for a quádrupla corrente, o if não tem else – não é preciso fazer troca quadaux

56 Exercício 4.6: Inserir quádruplas para o comando while Exemplo: as quádruplas para o comando Exemplo: as quádruplas para o comando while i < j do 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 WhileStat: WHILE Expression DO Statement ; Expression ----- ##nJF##n-----ROT Statement NOP----- NOP----- JUMP----- ROT ?

58 Exercício 4.7: Inserir quádruplas para comandos read e write Exemplo: as quádruplas para os comandos Exemplo: as quádruplas para os comandos read (a, b, c); write ("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 inter022015.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 read e write Isso será feito nas produções dos não-terminais ReadList e WriteList

60 O atributo dos não-terminais ReadList e WriteList deve ser o número de argumentos de suas listas O atributo dos não-terminais ReadList e WriteList 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 ReadList e WriteList: Declaração do atributo dos não terminais ReadList e WriteList: %type ReadList WriteList

61 Tal como uma expressão, o não terminal WriteElem terá um operando de quádrupla Tal como uma expressão, o não terminal WriteElem 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 Expression AuxExpr1 AuxExpr2 AuxExpr3 AuxExpr4 Term Factor WriteElem AuxExpr3 AuxExpr4 Term Factor WriteElem

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

63 Programação para o não-terminal ReadStat: Programação para o não-terminal ReadStat: ReadStat: READ OPPAR { - - - - -} ReadList{ opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPREAD, opnd1, opndidle, opndidle); } CLPAR SCOLON {printf (") ;\n");} ;

64 Programação para o não-terminal WriteElem: Programação para o não-terminal WriteElem: WriteElem: 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 WriteElem não é usado Portanto não é calculado

65 Programação para o não-terminal WriteList: Programação para o não-terminal WriteList: WriteList: WriteElem { $$ = 1; GeraQuadrupla (PARAM, $1.opnd, opndidle, opndidle); } | WriteList COMMA {printf (", ");} WriteElem { $$ = $1 + 1; GeraQuadrupla (PARAM, $4.opnd, opndidle, opndidle); }; $$ é o contador de argumentos de um comando write

66 Programação para o não-terminal WriteStat: Programação para o não-terminal WriteStat: WriteStat: WRITE OPPAR {- - - - -} WriteList { opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPWRITE, opnd1, opndidle, opndidle); } CLPAR SCOLON {printf (") ;\n");} ; No arquivo inter022015.dat, tirar o comentário dos comandos read e write 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; read (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] 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 Exemplo: A[10-i,2*j+3] 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  Desempilhar dois índices  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; read (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; read (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 nova 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; read (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: 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

75 program teste Local { int i, j, k, A[10,10];} 1) OPENMOD, (MODULO, teste), (IDLE), (IDLE) statements { 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 read (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 read (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)


Carregar ppt "CES-41 COMPILADORES Aulas Práticas - 2015 Capítulo IV Código Intermediário no Yacc."

Apresentações semelhantes


Anúncios Google