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

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

CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo V Interpretação do Código Intermediário.

Apresentações semelhantes


Apresentação em tema: "CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo V Interpretação do Código Intermediário."— Transcrição da apresentação:

1 CES-41 COMPILADORES Aulas Práticas Capítulo V Interpretação do Código Intermediário

2  Código intermediário para linguagens sem subprogramas : Interpretação: Colocar um ponteiro na 1ª quádrupla executável Executar cada quádrupla, sequencialmente, até encontrar aquela de operador OPEXIT As quádruplas de desvio alteram a sequência quad

3 Local para valores das variáveis (temporárias ou não): Na tabela de símbolos: Na tabela de símbolos: Deve-se acrescentar os seguintes campos em celsimb: Deve-se acrescentar os seguintes campos em celsimb: cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic Poderia ser usada union Espaço para estes ponteiros serão alocados na execução da quádrupla OPENMOD int *valint; float *valfloat; char *valchar, *vallogic;

4 Exemplo: sejam as declarações int x; float y; int A[4,3]; float B[5]; x v i n ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic y v r n ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic A v i s 2 # 4 3 ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic B v r s 1 # 5 ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic Alocações na execução de OPENMOD

5 Programa 5.1: Esqueleto do interpretador para a gramática das aulas de lab Arquivos: pret y, pret l e pret dat Arquivos: pret y, pret l e pret dat A seguir, o estado inicial da função principal do interpretador, no final do arquivo pret y A seguir, o estado inicial da função principal do interpretador, no final do arquivo pret y  A ser completada durante a aula e durante a execução do projeto

6 void InterpCodIntermed () { quadrupla quad, quadprox; char encerra; printf ("\n\nINTERPRETADOR:\n"); encerra = FALSO; quad = codintermed->prox->listquad->prox; while (! encerra) { printf ("\n%4d) %s", quad->num, nomeoperquad[quad->oper]); quadprox = quad->prox; switch (quad->oper) { case OPEXIT: encerra = VERDADE; break; } if (! encerra) quad = quadprox; } printf ("\n"); } quad

7 Definição do operador de quádrupla OPEXIT: Definição do operador de quádrupla OPEXIT: #defineOPEXIT24 Para guardar valores das variáveis, cada célula da tabela de símbolos terá os seguintes campos: Para guardar valores das variáveis, cada célula da tabela de símbolos terá os seguintes campos: int *valint; float *valfloat; char *valchar, *vallogic; char *valchar, *vallogic; Espaço para estes ponteiros serão alocados na execução da quádrupla OPENMOD

8 Protótipos de algumas funções para o interpretador (outras deverão ser construídas na elaboração do projeto): Protótipos de algumas funções para o interpretador (outras deverão ser construídas na elaboração do projeto): void InterpCodIntermed (void); void AlocaVariaveis (void); void ExecQuadWrite (quadrupla); void ExecQuadMais (quadrupla); void ExecQuadLT (quadrupla); void ExecQuadAtrib (quadrupla); void ExecQuadRead (quadrupla);

9 Na produção do não-terminal Prog: Na produção do não-terminal Prog: Prog: { } PROGRAM ID { } LocDecls Stats { GeraQuadrupla (OPEXIT, opndidle, opndidle, opndidle); GeraQuadrupla (OPEXIT, opndidle, opndidle, opndidle); VerificaInicRef (); VerificaInicRef (); ImprimeTabSimb (); ImprimeTabSimb (); ImprimeQuadruplas (); ImprimeQuadruplas (); InterpCodIntermed (); InterpCodIntermed ();}; Rodar flex, yacc, gcc e executável A seguir, o arquivo de dados

10 program teste local { int a, b, c, i, j; float k; logic b1; int A[5,4]; int A[5,4];} statements { write ("Valor 1: ", 14, "; Valor 2: ", 15.2, "; Valor 3: ", true); write ("Valor de 3+4: ", 3+4); a = 1; b = 2; i = 3; j = 4; c = a + b + i + j + 20; k = 12.6; b1 = true; write ("c = ", c, "; k = ", k, "; b1 = ", b1, ";");

11 i = 4; j = 5; b1 = true; if b1 then {i = j + 6;} else {i = i + 15;} write ("i = ", i); i = 4; j = 5; b1 = true; while b1 do {i = i + j; b1 = false;} write ("i = ", i); i = 3; k = 20.3; write ("i = ", i, "; k = ", k); /*while (i < k) { i = i + 4; write ("i = ", i, "; k = ", k); } */ write ("Valor de i+k: ", i+k); }

12 Exercício 5.1: Execução da quádrupla OPENMOD No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPENMOD: AlocaVariaveis (); break; Função AlocaVariáveis (já tem protótipo): Função AlocaVariáveis (já tem protótipo):   Percorre todas as classes da TabSimb   Para cada classe, visita todas as células   Para cada célula de tipo IDVAR, aloca espaço para o valor da variável correspondente   É preciso examinar o tipo e a dimensão da variável

13 Exemplo: sejam as declarações int x; float A[5,4]; cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic x v i n ? ? ? Apenas um elemento inteiro alocado para x A v r s 3 # 5 4 ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic 5*4 = 20 elementos reais alocados para A

14 void AlocaVariaveis () { simbolo s; int nelemaloc, i, j; printf ("\n\t\tAlocando as variaveis:"); for (i = 0; i < NCLASSHASH; i++) if (tabsimb[i]) { if (tabsimb[i]) { for (s = tabsimb[i]; s != NULL; s = s->prox){ for (s = tabsimb[i]; s != NULL; s = s->prox){ if (s->tid == IDVAR) { if (s->tid == IDVAR) { nelemaloc = 1; nelemaloc = 1; if (s->array) if (s->array) for (j = 1; j ndims; j++) nelemaloc *= s->dims[j]; for (j = 1; j ndims; j++) nelemaloc *= s->dims[j]; switch (s->tvar) { switch (s->tvar) { case INTEIRO: case INTEIRO: s->valint = malloc (nelemaloc * sizeof (int)); break; s->valint = malloc (nelemaloc * sizeof (int)); break; case REAL: case REAL: s->valfloat = malloc (nelemaloc * sizeof (float)); break; s->valfloat = malloc (nelemaloc * sizeof (float)); break; case CARACTERE: case CARACTERE: s->valchar = malloc (nelemaloc * sizeof (char)); break; s->valchar = malloc (nelemaloc * sizeof (char)); break; case LOGICO: case LOGICO: s->vallogic = malloc (nelemaloc * sizeof (char)); break; s->vallogic = malloc (nelemaloc * sizeof (char)); break; } printf ("\n\t\t\t%s: %d elemento(s) alocado(s) ", s->cadeia, nelemaloc); printf ("\n\t\t\t%s: %d elemento(s) alocado(s) ", s->cadeia, nelemaloc); } } } }} Executar e verificar a alocação das variáveis na execução de OPENMOD nelemaloc: número de elementos alocados para cada variável cadeia ndims dims valint valfloat valchar vallogic x ? ? ? s

15 Exercício 5.2: Execução da quádrupla PARAM Exemplo: seja o comando write ("Valor de a+b:", a+b, "Valor de c:", c); write ("Valor de a+b:", a+b, "Valor de c:", c); Suas quádruplas: Suas quádruplas: 1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 2) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 3) PARAM, (VAR, ##1), (IDLE), (IDLE) 4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 5) PARAM, (VAR, c), (IDLE), (IDLE) 6) WRITE, (INT, 4), (IDLE), (IDLE)

16 1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 2) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 3) PARAM, (VAR, ##1), (IDLE), (IDLE) 4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 5) PARAM, (VAR, c), (IDLE), (IDLE) 6) WRITE, (INT, 4), (IDLE), (IDLE) CADEIA, Valor de a+b: VAR, ##1 CADEIA, Valor de c: VAR, c pilhaoperando (global) Preenchida pelas 4 quádruplas PARAM pilhaopndaux A ser preenchida pela quádrupla WRITE

17 Execução da quádrupla: OPWRITE, (INT, 4), (IDLE), (IDLE) 1) Desempilhar 4 operandos de pilhaoperando, empilhando-os em pilhaopndaux CADEIA, Valor de a+b: VAR, ##1 CADEIA, Valor de c: VAR, c pilhaoperando (global) Preenchida pelas 4 quádruplas PARAM pilhaopndaux A ser preenchida pela quádrupla WRITE

18 Execução da quádrupla: OPWRITE, (INT, 4), (IDLE), (IDLE) 2) Desempilhar 4 operandos de pilhaopndaux, imprimindo seus atributos CADEIA, Valor de a+b: VAR, ##1 CADEIA, Valor de c: VAR, c pilhaoperando (global) Esvaziada pela quádrupla WRITE pilhaopndaux Preenchida pela quádrupla WRITE

19 Declarações para pilhas de operandos (já no arquivo pret y): Declarações para pilhas de operandos (já no arquivo pret y): typedef struct nohopnd nohopnd; struct nohopnd { operando opnd; nohopnd *prox; }; typedef nohopnd *pilhaoperando; pilhaoperando pilhaopnd;

20 Funções para manipular pilhas de operandos (já têm protótipos): Funções para manipular pilhas de operandos (já têm protótipos): void EmpilharOpnd (operando x, pilhaoperando *P) { nohopnd *temp; temp = *P; *P = (nohopnd *) malloc (sizeof (nohopnd)); (*P)->opnd = x; (*P)->prox = temp; } void DesempilharOpnd (pilhaoperando *P) { nohopnd *temp; if (! VaziaOpnd (*P)) { temp = *P; *P = (*P)->prox; free (temp); } else printf ("\n\tDelecao em pilha vazia\n"); }

21 operando TopoOpnd (pilhaoperando P) { if (! VaziaOpnd (P)) return P->opnd; else printf ("\n\tTopo de pilha vazia\n"); } void InicPilhaOpnd (pilhaoperando *P) { *P = NULL; } char VaziaOpnd (pilhaoperando P) { if (P == NULL) return 1; else return 0; }

22 Programação para executar quádruplas PARAM No início da função InterpCodIntermed: No início da função InterpCodIntermed: printf ("\n\nINTERPRETADOR:\n"); InicPilhaOpnd (&pilhaopnd); encerra = FALSO; quad = codintermed->listquad->prox; No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case PARAM: EmpilharOpnd (quad->opnd1, &pilhaopnd); break;

23 Exercício 5.3: Execução da quádrupla OPWRITE Exemplo: Exemplo: WRITE, (INT, 4), (IDLE), (IDLE) A execução compreende os passos:   Inicializar a pilha auxiliar de operandos   Transportar os operandos da pilha oficial para a auxiliar   Desempilhar cada operando da pilha auxiliar, imprimindo seu atributo

24 Escrita dos valores dos operandos: O problema é encontrar o paradeiro do valor a ser escrito Depende do tipo do operando, que pode ser:   Uma variável   Uma constante inteira, real, caractere, lógica ou cadeia de caracteres

25 Se for uma variável, ela pode ser inteira, real, caractere ou lógica:   O valor do operando fica então guardado na TabSimb A v r s 3 # 5 4 ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic x v i n ? ? ?

26 Programação para executar quádruplas OPWRITE: No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPWRITE: ExecQuadWrite (quad); break; Função ExecQuadWrite (já tem protótipo): Função ExecQuadWrite (já tem protótipo): void ExecQuadWrite (quadrupla quad) { int i; operando opndaux; pilhaoperando pilhaopndaux; printf ("\n\t\tEscrevendo: \n\n"); InicPilhaOpnd (&pilhaopndaux); for (i = 1; i opnd1.atr.valint; i++) { EmpilharOpnd (TopoOpnd (pilhaopnd), &pilhaopndaux); DesempilharOpnd (&pilhaopnd); }

27 for (i = 1; i opnd1.atr.valint; i++) { opndaux = TopoOpnd (pilhaopndaux); DesempilharOpnd (&pilhaopndaux); switch (opndaux.tipo) { case INTOPND: printf ("%d", opndaux.atr.valint); break; case REALOPND: printf ("%g", opndaux.atr.valfloat); break; case CHAROPND: printf ("%c", opndaux.atr.valchar); break; case LOGICOPND: if (opndaux.atr.vallogic == 1) printf ("TRUE"); else printf ("FALSE"); break; case CADOPND: printf ("%s", opndaux.atr.valcad); break ;

28 case VAROPND: switch (opndaux.atr.simb->tvar) { case INTEIRO: printf ("%d", *(opndaux.atr.simb->valint)); break; case REAL: printf ("%g", *(opndaux.atr.simb->valfloat));break; *(opndaux.atr.simb->valfloat));break; case LOGICO: if (*(opndaux.atr.simb->vallogic) == 1) printf ("TRUE"); else printf ("FALSE"); break; case CARACTERE: printf ("%c", *(opndaux.atr.simb->valchar)); break; *(opndaux.atr.simb->valchar)); break;}break;}} printf ("\n"); } Executar observando os valores escritos pelas quádruplas OPWRITE cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic x v i n ? ? ?

29 Exercício 5.4: Execução da quádrupla OPMAIS Exemplo: Exemplo: MAIS, (VAR, a), (REAL, 12.5), (VAR, ##1) MAIS, (VAR, a), (REAL, 12.5), (VAR, ##1) O problema agora é encontrar o paradeiro dos elementos a serem somados e onde guardar o resultado da soma Tudo depende do tipo do operando e da temporária que vai receber o resultado, que podem ser:   Uma variável   Uma constante inteira, real, caractere

30 Programação para executar quádruplas OPMAIS: No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPMAIS: ExecQuadMais (quad); break; Função ExecQuadMais (já tem protótipo): Função ExecQuadMais (já tem protótipo): void ExecQuadMais (quadrupla quad) { int tipo1, tipo2, valint1, valint2; float valfloat1, valfloat2; Guardam os tipos dos valores a serem somados Guardam os valores a serem somados, conforme os tipos

31 switch (quad->opnd1.tipo) { case INTOPND: tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break; case REALOPND: tipo1 = REALOPND; valfloat1 = quad->opnd1.atr.valfloat; break; case CHAROPND: tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break; case VAROPND: switch (quad->opnd1.atr.simb->tvar) { case INTEIRO: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case REAL: tipo1 = REALOPND; valfloat1=*(quad->opnd1.atr.simb->valfloat);break; case CARACTERE: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valchar); break; }break;}

32 switch (quad->opnd2.tipo) { case INTOPND: tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break; case REALOPND: tipo2 = REALOPND; valfloat2 = quad->opnd2.atr.valfloat; break; case CHAROPND: tipo2 = INTOPND; valint2 = quad->opnd2.atr.valchar; break; case VAROPND: switch (quad->opnd2.atr.simb->tvar) { case INTEIRO: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valint); break; case REAL: tipo2 = REALOPND; valfloat2=*(quad->opnd2.atr.simb->valfloat);break; case CARACTERE: tipo2 = INTOPND; valint2=*(quad->opnd2.atr.simb->valchar);break;}break;}

33 switch (quad->result.atr.simb->tvar) { case INTEIRO: *(quad->result.atr.simb->valint) = valint1 + valint2; break; case REAL: if (tipo1 == INTOPND && tipo2 == INTOPND) *(quad->result.atr.simb->valfloat) = valint1 + valint2; if (tipo1 == INTOPND && tipo2 == REALOPND) *(quad->result.atr.simb->valfloat) = valint1 + valfloat2; if (tipo1 == REALOPND && tipo2 == INTOPND) *(quad->result.atr.simb->valfloat) = valfloat1 + valint2; if (tipo1 == REALOPND && tipo2 == REALOPND) *(quad->result.atr.simb->valfloat) = valfloat1 + valfloat2; break;}} Executar observando os valores escritos de resultados de somas

34 Exercício 5.5: Execução da quádrupla OPATRIB Exemplo: seja a atribuição: b1 = (i+3 >= j-2) && b2 Exemplo: seja a atribuição: b1 = (i+3 >= j-2) && b2 Suas quádruplas 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) O problema agora é encontrar o paradeiro do valor a ser atribuído e onde guardá-lo Tudo depende dos tipos dos operandos envolvidos

35 Programação para executar quádruplas OPATRIB: No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPATRIB: ExecQuadAtrib (quad); break; Função ExecQuadAtrib (já tem protótipo): Função ExecQuadAtrib (já tem protótipo): void ExecQuadAtrib (quadrupla quad) { int tipo1, valint1; float valfloat1; char valchar1, vallogic1; Guarda o tipo do valor a ser atribuído Guardam os valores a serem atribuídos, conforme os tipos

36 switch (quad->opnd1.tipo) { case INTOPND: tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break; case REALOPND: tipo1 = REALOPND; valfloat1 = quad->opnd1.atr.valfloat; break; case CHAROPND: tipo1 = CHAROPND; valchar1 = quad->opnd1.atr.valchar; break; case LOGICOPND: tipo1 = LOGICOPND; vallogic1 = quad->opnd1.atr.vallogic; break;

37 case VAROPND: switch (quad->opnd1.atr.simb->tvar) { case INTEIRO: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case REAL: tipo1 = REALOPND; valfloat1=*(quad->opnd1.atr.simb->valfloat);break; case CARACTERE: tipo1 = CHAROPND; valchar1=*(quad->opnd1.atr.simb->valchar);break; case LOGICO: tipo1 = LOGICOPND; vallogic1 = *(quad->opnd1.atr.simb->vallogic); break;}break;}

38 switch (quad->result.atr.simb->tvar) { case INTEIRO: if (tipo1 == INTOPND) *(quad->result.atr.simb->valint) = valint1; if (tipo1 == CHAROPND)*(quad->result.atr.simb->valint)=valchar1; break; case CARACTERE: if (tipo1 == INTOPND) *(quad->result.atr.simb->valchar) = valint1; if (tipo1==CHAROPND)*(quad->result.atr.simb->valchar)=valchar1; break; case LOGICO: *(quad->result.atr.simb->vallogic) = vallogic1; break; case REAL: if (tipo1 == INTOPND) *(quad->result.atr.simb->valfloat) = valint1; if (tipo1 == REALOPND) *(quad->result.atr.simb->valfloat) = valfloat1; if (tipo1 == CHAROPND) *(quad->result.atr.simb->valfloat) = valchar1; break;}} Executar observando os valores das variáveis que recebem atribuição

39 Exercício 5.6: Execução das quádruplas OPJUMP e OPJF Exemplo: seja o comando while i < j do i = j + h; Exemplo: seja o comando while i < j do i = j + h; Suas quádruplas: 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)

40 Nova declaração na função InterpCodIntermed: Nova declaração na função InterpCodIntermed: char condicao; No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPJUMP: quadprox = quad->result.atr.rotulo; break; case OPJF: if (quad->opnd1.tipo == LOGICOPND) condicao = quad->opnd1.atr.vallogic; if (quad->opnd1.tipo == VAROPND) condicao = *(quad->opnd1.atr.simb->vallogic); if (! condicao) quadprox = quad->result.atr.rotulo; break; Executar observando os desvios efetuados pelos comandos if-else e while

41 Exercício 5.7: Execução da quádrupla OPLT No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPLT: ExecQuadLT (quad); break; Função ExecQuadLT (já tem protótipo): Função ExecQuadLT (já tem protótipo): void ExecQuadLT (quadrupla quad) { int tipo1, tipo2, valint1, valint2; float valfloat1, valfloat2;

42 switch (quad->opnd1.tipo) { case INTOPND: tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break; case REALOPND: tipo1 = REALOPND; valfloat1=quad->opnd1.atr.valfloat;break; case CHAROPND: tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break; case VAROPND: switch (quad->opnd1.atr.simb->tvar) { case INTEIRO: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case REAL: tipo1 = REALOPND; valfloat1 = *(quad->opnd1.atr.simb->valfloat); break; case CARACTERE: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valchar); break;}break;}

43 switch (quad->opnd2.tipo) { case INTOPND: tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break; case REALOPND: tipo2=REALOPND;valfloat2 = quad->opnd2.atr.valfloat;break; case CHAROPND: tipo2 = INTOPND;valint2 = quad->opnd2.atr.valchar; break; case VAROPND: switch (quad->opnd2.atr.simb->tvar) { case INTEIRO: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valint); break; case REAL: tipo2 = REALOPND; valfloat2 = *(quad->opnd2.atr.simb->valfloat); break; case CARACTERE: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valchar); break;}break;}

44 if (tipo1 == INTOPND && tipo2 == INTOPND) *(quad->result.atr.simb->vallogic) = valint1 result.atr.simb->vallogic) = valint1 < valint2; if (tipo1 == INTOPND && tipo2 == REALOPND) *(quad->result.atr.simb->vallogic) = valint1 result.atr.simb->vallogic) = valint1 < valfloat2; if (tipo1 == REALOPND && tipo2 == INTOPND) *(quad->result.atr.simb->vallogic) = valfloat1 result.atr.simb->vallogic) = valfloat1 < valint2; if (tipo1 == REALOPND && tipo2 == REALOPND) *(quad->result.atr.simb->vallogic) = valfloat1 result.atr.simb->vallogic) = valfloat1 < valfloat2;} Eliminar os comentários de pret dat e rodar Eliminar os comentários de pret dat e rodar

45 Exercício 5.8: Execução da quádrupla READ Exemplo: seja o comando read (a, b, c); read (a, b, c); Suas quádruplas: Suas quádruplas: 1) PARAM, (VAR, a), (IDLE), (IDLE 2) PARAM, (VAR, b), (IDLE), (IDLE) 3) PARAM, (VAR, c), (IDLE), (IDLE) 4) READ, (INT, 3), (IDLE), (IDLE)

46 1) PARAM, (VAR, a), (IDLE), (IDLE 2) PARAM, (VAR, b), (IDLE), (IDLE) 3) PARAM, (VAR, c), (IDLE), (IDLE) 4) READ, (INT, 3), (IDLE), (IDLE)) VAR, a VAR, b VAR, c pilhaoperando (global) Preenchida pelas 3 quádruplas PARAM pilhaopndaux A ser preenchida pela quádrupla READ

47 Execução da quádrupla: OPREAD, (INT, 3), (IDLE), (IDLE) 1) Desempilhar 3 operandos de pilhaoperando, empilhando-os em pilhaopndaux pilhaoperando (global) Preenchida pelas 3 quádruplas PARAM pilhaopndaux A ser preenchida pela quádrupla READ VAR, a VAR, b VAR, c

48 Execução da quádrupla: OPREAD, (INT, 3), (IDLE), (IDLE) 2) Desempilhar 3 operandos de pilhaopndaux, lendo valores para seus atributos pilhaoperando (global) Esvaziada pela quádrupla READ pilhaopndaux Preenchida pela quádrupla READ VAR, c VAR, b VAR, a

49 Leitura dos valores dos operandos: O problema é encontrar o local para guardar o valor lido É uma variável e depende do tipo, que pode ser:   Inteiro, real, caractere ou lógico

50 O valor lido deve ser guardado na TabSimb A v r s 3 # 5 4 ? ? ? cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic cadeia tid tvar inic ref array ndims dims valint valfloat valchar vallogic x v i n ? ? ?

51 Programação para executar quádruplas OPREAD: No switch da função InterpCodIntermed: No switch da função InterpCodIntermed: case OPREAD: ExecQuadRead (quad); break; Os dados de entrada para a execução do programa ficarão num arquivo denominado “entrada2014” Nova variável global: FILE *finput; InterpCodIntermed: Associação com o arquivo de entrada, no início da função InterpCodIntermed: finput = fopen ("entrada2014", "r");

52 Função ExecQuadRead (já tem protótipo): Função ExecQuadRead (já tem protótipo): void ExecQuadRead (quadrupla quad) { int i; operando opndaux; pilhaoperando pilhaopndaux; printf ("\n\t\tLendo: \n"); InicPilhaOpnd (&pilhaopndaux); for (i = 1; i opnd1.atr.valint; i++) { EmpilharOpnd (TopoOpnd (pilhaopnd), &pilhaopndaux); DesempilharOpnd (&pilhaopnd); }

53 for (i = 1; i opnd1.atr.valint; i++) { opndaux = TopoOpnd (pilhaopndaux); DesempilharOpnd (&pilhaopndaux); switch (opndaux.atr.simb->tvar) { switch (opndaux.atr.simb->tvar) { case INTEIRO: case INTEIRO: fscanf (finput, "%d", opndaux.atr.simb->valint); break; fscanf (finput, "%d", opndaux.atr.simb->valint); break; case REAL: case REAL: fscanf (finput, "%g", opndaux.atr.simb->valfloat);break; fscanf (finput, "%g", opndaux.atr.simb->valfloat);break; case LOGICO: case LOGICO: fscanf (finput, "%d", opndaux.atr.simb->vallogic); break; fscanf (finput, "%d", opndaux.atr.simb->vallogic); break; case CARACTERE: case CARACTERE: fscanf (finput, "%c", opndaux.atr.simb->valchar); break; fscanf (finput, "%c", opndaux.atr.simb->valchar); break; }}} Executar com o arquivo pret dat Seu conteúdo e o do arquivo entrada2014 vem a seguir

54 Arquivo pret dat: Arquivo pret dat: program teste local { int i, j, k; float x, y; logic a, b; char m, n; } statements { read (i, j, x, b); write ("i: ", i, "; j: ", j, "; x: ", x, "; b: ", b); k = i + j; y = x + 3.4; a = i < j; write ("k: ", k, "; y: ", y, "; a: ", a); read (m); n = m + ' '; write ("m: ", m, "; n: ", n); } Arquivo entrada2014: W


Carregar ppt "CES-41 COMPILADORES Aulas Práticas - 2014 Capítulo V Interpretação do Código Intermediário."

Apresentações semelhantes


Anúncios Google