Compiladores Prof. Yandre Maldonado Compiladores - Prof. Yandre - 1.
CES-41 COMPILADORES Aulas Práticas - 2013
description
Transcript of CES-41 COMPILADORES Aulas Práticas - 2013
CES-41 CES-41 COMPILADORESCOMPILADORES
Aulas Práticas - 2013Aulas Práticas - 2013
Capítulo V Capítulo V Interpretação do Código Interpretação do Código
IntermediárioIntermediário
Código intermediário para linguagens sem Código intermediário para linguagens sem subprogramassubprogramas::
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
Local para valores das variáveis Local para valores das variáveis (temporárias ou não)(temporárias ou não)::
Na tabela de símbolos:Na tabela de símbolos:
Deve-se acrescentar os seguintes campos emDeve-se acrescentar os seguintes campos em celsimbcelsimb::
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;
Exemplo: sejam as declaraçõesExemplo: sejam as declarações
int x; real y; int A[4,3]; real B[5];int x; real y; int A[4,3]; real 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
Programa 5.1: Programa 5.1: Esqueleto do interpretador para Esqueleto do interpretador para a gramática das aulas de laba gramática das aulas de lab
Arquivos: Arquivos: pret012013.ypret012013.y, , pret012013.lpret012013.l e e pret012013.datpret012013.dat
A seguir, o estado inicial da função principal do A seguir, o estado inicial da função principal do interpretadorinterpretador, no final do arquivo , no final do arquivo pret012013.ypret012013.y
A ser completada durante a aula e durante a A ser completada durante a aula e durante a execução do projetoexecução do projeto
void InterpCodIntermed () {void InterpCodIntermed () {quadrupla quad, quadprox; char encerra;quadrupla quad, quadprox; char encerra;printf ("\n\nINTERPRETADOR:\n");printf ("\n\nINTERPRETADOR:\n");encerra = FALSE;encerra = FALSE;quad = codintermed->prox->listquad->prox;quad = codintermed->prox->listquad->prox;while (! encerra) {while (! encerra) {
printf ("\n%4d) %s", quad->num, printf ("\n%4d) %s", quad->num, nomeoperquad[quad->oper]);nomeoperquad[quad->oper]);
quadprox = quad->prox;quadprox = quad->prox;switch (quad->oper) {switch (quad->oper) {
case OPEXIT: encerra = TRUE; break;case OPEXIT: encerra = TRUE; break;}}if (! encerra) quad = quadprox;if (! encerra) quad = quadprox;
}}printf ("\n"); printf ("\n");
}}
quad
Definição do operador de quádrupla OPEXIT:Definição do operador de quádrupla OPEXIT:
#define#define OPEXITOPEXIT 2424
Para guardar valores das variáveis, cada célula Para guardar valores das variáveis, cada célula da tabela de símbolos terá os seguintes da tabela de símbolos terá os seguintes campos:campos:
int *valint;int *valint;float *valfloat;float *valfloat;
char *valchar, *vallogic;char *valchar, *vallogic;
Espaço para estes ponteiros serão alocados na execução da quádrupla OPENMOD
ProtótiposProtótipos de algumas funções para o de algumas funções para o interpretador (outras deverão ser construídas interpretador (outras deverão ser construídas na elaboração do projeto):na elaboração do projeto):
void InterpCodIntermed (void);void InterpCodIntermed (void);void AlocaVariaveis (void);void AlocaVariaveis (void);void ExecQuadWrite (quadrupla);void ExecQuadWrite (quadrupla);void ExecQuadMais (quadrupla);void ExecQuadMais (quadrupla);void ExecQuadLT (quadrupla);void ExecQuadLT (quadrupla);void ExecQuadAtrib (quadrupla);void ExecQuadAtrib (quadrupla);void ExecQuadRead (quadrupla);void ExecQuadRead (quadrupla);
Na produção do não-terminal Na produção do não-terminal ProgProg::
ProgProg : {- - - - -} PROGRAMA ID PVIRG {- - - - -} : {- - - - -} PROGRAMA ID PVIRG {- - - - -} Decls CmdComp {Decls CmdComp {
GeraQuadrupla (OPEXIT, opndidle, opndidle, GeraQuadrupla (OPEXIT, opndidle, opndidle, opndidle);opndidle);
VerificaInicRef ();VerificaInicRef (); ImprimeTabSimb ();ImprimeTabSimb (); ImprimeQuadruplas ();ImprimeQuadruplas (); InterpCodIntermed ();InterpCodIntermed ();
}};;
Rodar flex, yacc, gcc e executável
A seguir, o arquivo de dados
programa teste;programa teste;varvar
int a, b, c, i, j; real k; logic b1;int a, b, c, i, j; real k; logic b1; int A[5,4];int A[5,4];{{
escrever ("Valor 1: ", 14, "; Valor 2: ", 15.2, "; Valor escrever ("Valor 1: ", 14, "; Valor 2: ", 15.2, "; Valor 3: ", verdade);3: ", verdade);escrever ("Valor de 3+4: ", 3+4);escrever ("Valor de 3+4: ", 3+4);a := 1;a := 1;b := 2;b := 2;i := 3;i := 3;j := 4;j := 4;c := a + b + i + j + 20;c := a + b + i + j + 20;k := 12.6;k := 12.6;b1 := verdade;b1 := verdade;escrever ("c = ", c, "; k = ", k, "; b1 = ", b1, ";");escrever ("c = ", c, "; k = ", k, "; b1 = ", b1, ";");
i := 4; j := 5; b1 := verdade;i := 4; j := 5; b1 := verdade;se (b1) {i := j + 6;} senao {i := i + 15;}se (b1) {i := j + 6;} senao {i := i + 15;}escrever ("i = ", i);escrever ("i = ", i);
i := 4; j := 5; b1 := verdade;i := 4; j := 5; b1 := verdade;enquanto (b1) {i := i + j; b1 := falso;}enquanto (b1) {i := i + j; b1 := falso;}escrever ("i = ", i);escrever ("i = ", i);
i := 3;i := 3;k := 20.3;k := 20.3;escrever ("i = ", i, "; k = ", k);escrever ("i = ", i, "; k = ", k);
/*/* enquanto (i < k) {enquanto (i < k) {i := i + 4;i := i + 4;escrever ("i = ", i, "; k = ", k);escrever ("i = ", i, "; k = ", k);
} */} */
escrever ("Valor de i+k: ", i+k); escrever ("Valor de i+k: ", i+k); }}
Exercício 5.1:Exercício 5.1: Execução da quádrupla OPENMOD Execução da quádrupla OPENMOD
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPENMOD: AlocaVariaveis (); break;case OPENMOD: AlocaVariaveis (); break;
Função Função AlocaVariáveisAlocaVariáveis (já tem protótipo): (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
Exemplo: Exemplo: sejam as declaraçõessejam as declaraçõesint x; real A[5,4];int x; real 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
void AlocaVariaveis () {void AlocaVariaveis () {simbolo s; int simbolo s; int nelemalocnelemaloc, i, j;, i, j;printf ("\n\t\tAlocando as variaveis:");printf ("\n\t\tAlocando as variaveis:");for (i = 0; i < NCLASSHASH; i++)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 <= s->ndims; j++) nelemaloc *= s->dims[j];for (j = 1; j <= s->ndims; j++) nelemaloc *= s->dims[j]; switch (s->tvar) {switch (s->tvar) { case INTEGER:case INTEGER: s->valint = malloc (s->valint = malloc (nelemalocnelemaloc * sizeof (int)); break; * sizeof (int)); break; case FLOAT:case FLOAT: s->valfloat = malloc (s->valfloat = malloc (nelemalocnelemaloc * sizeof (float)); break; * sizeof (float)); break; case CHAR:case CHAR: s->valchar = malloc (s->valchar = malloc (nelemalocnelemaloc * sizeof (char)); break; * sizeof (char)); break; case LOGICAL:case LOGICAL: s->vallogic = malloc (s->vallogic = malloc (nelemalocnelemaloc * sizeof (char)); break; * sizeof (char)); break; }} printf ("\n\t\t\t%s: %d elemento(s) alocado(s) ", s->cadeia, printf ("\n\t\t\t%s: %d elemento(s) alocado(s) ", s->cadeia, nelemalocnelemaloc);); }} }} }}
}}
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
Exercício 5.2:Exercício 5.2: Execução da quádrupla PARAM Execução da quádrupla PARAM
Exemplo:Exemplo: seja o comando seja o comando
escrever ("Valor de a+b:", a+b, "Valor escrever ("Valor de a+b:", a+b, "Valor de c:", c);de c:", c);
Suas quádruplas:Suas quádruplas:1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE)1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE)2) MAIS, (VAR, a), (VAR, b), (VAR, ##1)2) MAIS, (VAR, a), (VAR, b), (VAR, ##1)3) PARAM, (VAR, ##1), (IDLE), (IDLE)3) PARAM, (VAR, ##1), (IDLE), (IDLE)4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE)4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE)5) PARAM, (VAR, c), (IDLE), (IDLE)5) PARAM, (VAR, c), (IDLE), (IDLE)6) WRITE, (INT, 4), (IDLE), (IDLE)6) WRITE, (INT, 4), (IDLE), (IDLE)
1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE)1) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE)2) MAIS, (VAR, a), (VAR, b), (VAR, ##1)2) MAIS, (VAR, a), (VAR, b), (VAR, ##1)3) PARAM, (VAR, ##1), (IDLE), (IDLE)3) PARAM, (VAR, ##1), (IDLE), (IDLE)4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE)4) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE)5) PARAM, (VAR, c), (IDLE), (IDLE)5) PARAM, (VAR, c), (IDLE), (IDLE)6) WRITE, (INT, 4), (IDLE), (IDLE)6) WRITE, (INT, 4), (IDLE), (IDLE)
CADEIA, Valor de a+b:
VAR, ##1CADEIA, Valor de c:
VAR, c
pilhaoperando (global)
Preenchida pelas 4 quádruplas PARAM
pilhaopndaux
A ser preenchida pela quádrupla
WRITE
Execução da quádrupla:Execução da quádrupla:
OPWRITE, (INT, 4), (IDLE), (IDLE)OPWRITE, (INT, 4), (IDLE), (IDLE)
1) Desempilhar 4 operandos de pilhaoperando, empilhando-os em pilhaopndaux
CADEIA, Valor de a+b:
VAR, ##1CADEIA, Valor de c:
VAR, c
pilhaoperando (global)
Preenchida pelas 4 quádruplas PARAM
pilhaopndaux
A ser preenchida pela quádrupla
WRITE
Execução da quádrupla:Execução da quádrupla:
OPWRITE, (INT, 4), (IDLE), (IDLE)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
Declarações para pilhas de operandos (já no Declarações para pilhas de operandos (já no arquivo arquivo pret012013.ypret012013.y):):
typedef struct nohopnd nohopnd;struct nohopnd {
operando opnd;nohopnd *prox;
};typedef nohopnd *pilhaoperando;pilhaoperando pilhaopnd, pilhaopndaux;
Funções para manipular pilhas de operandos (já Funções para manipular pilhas de operandos (já têm protótipos):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");
}
operando TopoOpnd (pilhaoperando P) {operando TopoOpnd (pilhaoperando P) {if (! VaziaOpnd (P)) return P->opnd;if (! VaziaOpnd (P)) return P->opnd;else printf ("\n\tTopo de pilha vazia\n");else printf ("\n\tTopo de pilha vazia\n");
}}
void InicPilhaOpnd (pilhaoperando *P) { void InicPilhaOpnd (pilhaoperando *P) { *P = NULL;*P = NULL;
}}
char VaziaOpnd (pilhaoperando P) {char VaziaOpnd (pilhaoperando P) {if (P == NULL) return 1; if (P == NULL) return 1; else return 0; else return 0;
}}
Programação para executar quádruplas Programação para executar quádruplas PARAMPARAM
No início da função No início da função InterpCodIntermedInterpCodIntermed::
printf ("\n\nINTERPRETADOR:\n");InicPilhaOpnd (&pilhaopnd);encerra = FALSO;quad = codintermed->listquad->prox;
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case PARAM: EmpilharOpnd (quad->opnd1, &pilhaopnd); break;
Exercício 5.3:Exercício 5.3: Execução da quádrupla OPWRITE Execução da quádrupla OPWRITE
Exemplo:Exemplo:
WRITE, (INT, 4), (IDLE), (IDLE)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
Escrita dos valores dos operandos:Escrita dos valores dos operandos:
O problema é encontrar o paradeiro do valor a ser impresso
Depende do tipo do operando, que pode ser:
Uma variável Uma constante inteira, real, caractere, lógica
ou cadeia de caracteres
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
? ? ?
Programação para executar quádruplas Programação para executar quádruplas OPWRITEOPWRITE::
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPWRITE: ExecQuadWrite (quad); break;
Função Função ExecQuadWriteExecQuadWrite (já tem protótipo): (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 <= quad->opnd1.atr.valint; i++) {EmpilharOpnd (TopoOpnd (pilhaopnd), &pilhaopndaux);DesempilharOpnd (&pilhaopnd);}
for (i = 1; i <= quad->opnd1.atr.valint; i++) {for (i = 1; i <= quad->opnd1.atr.valint; i++) {opndaux = TopoOpnd (pilhaopndaux);opndaux = TopoOpnd (pilhaopndaux);DesempilharOpnd (&pilhaopndaux);DesempilharOpnd (&pilhaopndaux);switch (opndaux.tipo) {switch (opndaux.tipo) {
case INTOPND:case INTOPND:printf ("%d", opndaux.atr.valint); break;printf ("%d", opndaux.atr.valint); break;
case REALOPND:case REALOPND:printf ("%g", opndaux.atr.valfloat); break;printf ("%g", opndaux.atr.valfloat); break;
case CHAROPND:case CHAROPND:printf ("%c", opndaux.atr.valchar); break;printf ("%c", opndaux.atr.valchar); break;
case LOGICOPND:case LOGICOPND:if (opndaux.atr.vallogic == 1) printf if (opndaux.atr.vallogic == 1) printf
("VERDADE");("VERDADE");else printf ("FALSO");else printf ("FALSO");break;break;
case CADOPND:case CADOPND:printf ("%s", opndaux.atr.valcad); printf ("%s", opndaux.atr.valcad); break ;break ;
case VAROPND:case VAROPND:switch (opndaux.atr.simb->tvar) {switch (opndaux.atr.simb->tvar) {case INTEGER:case INTEGER:printf ("%d", *(opndaux.atr.simb->valint)); printf ("%d", *(opndaux.atr.simb->valint)); break;break;case FLOAT:case FLOAT:printf ("%g", printf ("%g", *(opndaux.atr.simb->valfloat));break;*(opndaux.atr.simb->valfloat));break;case LOGICAL:case LOGICAL:if (*(opndaux.atr.simb->vallogic) == 1)if (*(opndaux.atr.simb->vallogic) == 1)printf ("VERDADE"); printf ("VERDADE"); else printf ("FALSO"); break;else printf ("FALSO"); break;case CHAR:case CHAR:printf ("%c", printf ("%c", *(opndaux.atr.simb->valchar)); break;*(opndaux.atr.simb->valchar)); break;}}break;break;}}}}printf ("\n");printf ("\n");
}} Executar observando os valores escritos pelas quádruplas OPWRITE
Exercício 5.4:Exercício 5.4: Execução da quádrupla OPMAIS 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
Programação para executar quádruplas Programação para executar quádruplas OPMAISOPMAIS::
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPMAIS: ExecQuadMais (quad); break;
Função Função ExecQuadMaisExecQuadMais (já tem protótipo): (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
switch (quad->opnd1.tipo) {switch (quad->opnd1.tipo) {case INTOPND:case INTOPND:tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break;tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break;case REALOPND:case REALOPND:tipo1 = REALOPND; valfloat1 = quad->opnd1.atr.valfloat; break;tipo1 = REALOPND; valfloat1 = quad->opnd1.atr.valfloat; break;case CHAROPND:case CHAROPND:tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break;tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break;case VAROPND:case VAROPND:switch (quad->opnd1.atr.simb->tvar) {switch (quad->opnd1.atr.simb->tvar) {case INTEGER:case INTEGER:tipo1 = INTOPND;tipo1 = INTOPND;valint1 = *(quad->opnd1.atr.simb->valint); break;valint1 = *(quad->opnd1.atr.simb->valint); break;case FLOAT:case FLOAT:tipo1 = REALOPND;tipo1 = REALOPND;valfloat1=*(quad->opnd1.atr.simb->valfloat);break;valfloat1=*(quad->opnd1.atr.simb->valfloat);break;case CHAR:case CHAR:tipo1 = INTOPND;tipo1 = INTOPND;valint1 = *(quad->opnd1.atr.simb->valchar); break;valint1 = *(quad->opnd1.atr.simb->valchar); break;}}break;break;}}
switch (quad->opnd2.tipo) {switch (quad->opnd2.tipo) {case INTOPND:case INTOPND:tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break;tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break;case REALOPND:case REALOPND:tipo2 = REALOPND; valfloat2 = quad->opnd2.atr.valfloat; break;tipo2 = REALOPND; valfloat2 = quad->opnd2.atr.valfloat; break;case CHAROPND:case CHAROPND:tipo2 = INTOPND; valint2 = quad->opnd2.atr.valchar; break;tipo2 = INTOPND; valint2 = quad->opnd2.atr.valchar; break;case VAROPND:case VAROPND:switch (quad->opnd2.atr.simb->tvar) {switch (quad->opnd2.atr.simb->tvar) {case INTEGER:case INTEGER:tipo2 = INTOPND;tipo2 = INTOPND;valint2 = *(quad->opnd2.atr.simb->valint); break;valint2 = *(quad->opnd2.atr.simb->valint); break;case FLOAT:case FLOAT:tipo2 = REALOPND;tipo2 = REALOPND;valfloat2=*(quad->opnd2.atr.simb->valfloat);break;valfloat2=*(quad->opnd2.atr.simb->valfloat);break;case CHAR:case CHAR:tipo2 = INTOPND;tipo2 = INTOPND;valint2=*(quad->opnd2.atr.simb->valchar);break;valint2=*(quad->opnd2.atr.simb->valchar);break;}}break;break;}}
switch (quad->result.atr.simb->tvar) {switch (quad->result.atr.simb->tvar) {case INTEGER:case INTEGER:*(quad->result.atr.simb->valint) = valint1 + valint2;*(quad->result.atr.simb->valint) = valint1 + valint2;break;break;case FLOAT:case FLOAT:if (tipo1 == INTOPND && tipo2 == INTOPND)if (tipo1 == INTOPND && tipo2 == INTOPND)*(quad->result.atr.simb->valfloat) = valint1 + valint2;*(quad->result.atr.simb->valfloat) = valint1 + valint2;if (tipo1 == INTOPND && tipo2 == REALOPND)if (tipo1 == INTOPND && tipo2 == REALOPND)*(quad->result.atr.simb->valfloat) = valint1 + valfloat2;*(quad->result.atr.simb->valfloat) = valint1 + valfloat2;if (tipo1 == REALOPND && tipo2 == INTOPND)if (tipo1 == REALOPND && tipo2 == INTOPND)*(quad->result.atr.simb->valfloat) = valfloat1 + valint2;*(quad->result.atr.simb->valfloat) = valfloat1 + valint2;if (tipo1 == REALOPND && tipo2 == REALOPND)if (tipo1 == REALOPND && tipo2 == REALOPND)*(quad->result.atr.simb->valfloat) = valfloat1 + valfloat2;*(quad->result.atr.simb->valfloat) = valfloat1 + valfloat2;break;break;}}
}}Executar observando os valores escritos de resultados de somas
Exercício 5.5:Exercício 5.5: Execução da quádrupla OPATRIB Execução da quádrupla OPATRIB
Exemplo:Exemplo: seja a atribuição: seja a atribuição: b1 := (i+3 >= j-2) b1 := (i+3 >= j-2) && b2&& b2
Suas quádruplas Suas quádruplas podem ser: podem ser:
MAIS, (VAR, i), (INT, 3), (VAR, ##1)MAIS, (VAR, i), (INT, 3), (VAR, ##1)MENOS, (VAR, j), (INT, 2), (VAR, ##2)MENOS, (VAR, j), (INT, 2), (VAR, ##2)GE, (VAR, ##1), (VAR, ##2), (VAR, ##3)GE, (VAR, ##1), (VAR, ##2), (VAR, ##3)AND, (VAR, ##3), (VAR, b2), (VAR, ##4)AND, (VAR, ##3), (VAR, b2), (VAR, ##4)ATRIB, (VAR, ##4), (IDLE), (VAR, b1)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
Programação para executar quádruplas Programação para executar quádruplas OPATRIBOPATRIB::
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPATRIB: ExecQuadAtrib (quad); break;
Função Função ExecQuadAtribExecQuadAtrib (já tem protótipo): (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
switch (quad->opnd1.tipo) {switch (quad->opnd1.tipo) {case INTOPND:case INTOPND:tipo1 = INTOPND;tipo1 = INTOPND;valint1 = quad->opnd1.atr.valint; break;valint1 = quad->opnd1.atr.valint; break;case REALOPND:case REALOPND:tipo1 = REALOPND;tipo1 = REALOPND;valfloat1 = quad->opnd1.atr.valfloat; break;valfloat1 = quad->opnd1.atr.valfloat; break;case CHAROPND:case CHAROPND:tipo1 = CHAROPND;tipo1 = CHAROPND;valchar1 = quad->opnd1.atr.valchar; break;valchar1 = quad->opnd1.atr.valchar; break;case LOGICOPND:case LOGICOPND:tipo1 = LOGICOPND;tipo1 = LOGICOPND;vallogic1 = quad->opnd1.atr.vallogic; break;vallogic1 = quad->opnd1.atr.vallogic; break;
case VAROPND:case VAROPND:switch (quad->opnd1.atr.simb->tvar) {switch (quad->opnd1.atr.simb->tvar) {case INTEGER:case INTEGER:tipo1 = INTOPND;tipo1 = INTOPND;valint1 = *(quad->opnd1.atr.simb->valint); break;valint1 = *(quad->opnd1.atr.simb->valint); break;case FLOAT:case FLOAT:tipo1 = REALOPND;tipo1 = REALOPND;valfloat1=*(quad->opnd1.atr.simb->valfloat);break;valfloat1=*(quad->opnd1.atr.simb->valfloat);break;case CHAR:case CHAR:tipo1 = CHAROPND;tipo1 = CHAROPND;valchar1=*(quad->opnd1.atr.simb->valchar);break;valchar1=*(quad->opnd1.atr.simb->valchar);break;case LOGICAL:case LOGICAL:tipo1 = LOGICOPND;tipo1 = LOGICOPND;vallogic1 = *(quad->opnd1.atr.simb->vallogic);vallogic1 = *(quad->opnd1.atr.simb->vallogic);break;break;}}break;break;}}
switch (quad->result.atr.simb->tvar) {switch (quad->result.atr.simb->tvar) {case INTEGER:case INTEGER:if (tipo1 == INTOPND) *(quad->result.atr.simb->valint) = valint1;if (tipo1 == INTOPND) *(quad->result.atr.simb->valint) = valint1;if (tipo1 == CHAROPND)*(quad->result.atr.simb->valint)=valchar1;if (tipo1 == CHAROPND)*(quad->result.atr.simb->valint)=valchar1;break;break;case CHAR:case CHAR:if (tipo1 == INTOPND) *(quad->result.atr.simb->valchar) = valint1;if (tipo1 == INTOPND) *(quad->result.atr.simb->valchar) = valint1;if (tipo1==CHAROPND)*(quad->result.atr.simb->valchar)=valchar1;if (tipo1==CHAROPND)*(quad->result.atr.simb->valchar)=valchar1;break;break;case LOGICAL: *(quad->result.atr.simb->vallogic) = vallogic1; case LOGICAL: *(quad->result.atr.simb->vallogic) = vallogic1; break;break;case FLOAT:case FLOAT:if (tipo1 == INTOPND)if (tipo1 == INTOPND)*(quad->result.atr.simb->valfloat) = valint1;*(quad->result.atr.simb->valfloat) = valint1;if (tipo1 == REALOPND)if (tipo1 == REALOPND)*(quad->result.atr.simb->valfloat) = valfloat1;*(quad->result.atr.simb->valfloat) = valfloat1;if (tipo1 == CHAROPND)if (tipo1 == CHAROPND)*(quad->result.atr.simb->valfloat) = valchar1;*(quad->result.atr.simb->valfloat) = valchar1;break;break;}}
}}Executar observando os valores das variáveis que recebem atribuição
Exercício 5.6:Exercício 5.6: Execução das quádruplas Execução das quádruplas OPJUMP e OPJFOPJUMP e OPJF
Exemplo:Exemplo: seja o comando seja o comando enquanto (i < j) enquanto (i < j) i := j + h;i := j + h;
Suas quádruplas: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)
Nova declaração na função Nova declaração na função InterpCodIntermedInterpCodIntermed::
char condicao;char condicao;
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPJUMP: quadprox = quad->result.atr.rotulo; case OPJUMP: quadprox = quad->result.atr.rotulo; break;break;case OPJF:case OPJF:if (quad->opnd1.tipo == LOGICOPND)if (quad->opnd1.tipo == LOGICOPND)condicao = quad->opnd1.atr.vallogic;condicao = quad->opnd1.atr.vallogic;if (quad->opnd1.tipo == VAROPND)if (quad->opnd1.tipo == VAROPND)condicao = *(quad->opnd1.atr.simb->vallogic);condicao = *(quad->opnd1.atr.simb->vallogic);if (! condicao)if (! condicao)quadprox = quad->result.atr.rotulo;quadprox = quad->result.atr.rotulo;break;break; Executar observando os desvios
efetuados pelos comandos se-senao e enquanto
Exercício 5.7:Exercício 5.7: Execução da quádrupla OPLT Execução da quádrupla OPLT
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPLT: ExecQuadLT (quad); break;case OPLT: ExecQuadLT (quad); break;
Função Função ExecQuadLTExecQuadLT (já tem protótipo): (já tem protótipo):
void ExecQuadLT (quadrupla quad) {void ExecQuadLT (quadrupla quad) {int tipo1, tipo2, valint1, valint2;int tipo1, tipo2, valint1, valint2;float valfloat1, valfloat2;float valfloat1, valfloat2;
switch (quad->opnd1.tipo) {switch (quad->opnd1.tipo) {case INTOPND:case INTOPND:tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break;tipo1 = INTOPND; valint1 = quad->opnd1.atr.valint; break;case REALOPND:case REALOPND:tipo1 = REALOPND; valfloat1=quad-tipo1 = REALOPND; valfloat1=quad->opnd1.atr.valfloat;break;>opnd1.atr.valfloat;break;case CHAROPND:case CHAROPND:tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break;tipo1 = INTOPND; valint1 = quad->opnd1.atr.valchar; break;case VAROPND:case VAROPND:switch (quad->opnd1.atr.simb->tvar) {switch (quad->opnd1.atr.simb->tvar) {case INTEGER: tipo1 = INTOPND;case INTEGER: tipo1 = INTOPND;valint1 = *(quad->opnd1.atr.simb->valint);valint1 = *(quad->opnd1.atr.simb->valint);break;break;case FLOAT: tipo1 = REALOPND;case FLOAT: tipo1 = REALOPND;valfloat1 = *(quad->opnd1.atr.simb->valfloat);valfloat1 = *(quad->opnd1.atr.simb->valfloat);break;break;case CHAR: tipo1 = INTOPND;case CHAR: tipo1 = INTOPND;valint1 = *(quad->opnd1.atr.simb->valchar);valint1 = *(quad->opnd1.atr.simb->valchar);break;break;}}break;break;}}
switch (quad->opnd2.tipo) {switch (quad->opnd2.tipo) {case INTOPND:case INTOPND:tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break;tipo2 = INTOPND; valint2 = quad->opnd2.atr.valint; break;case REALOPND:case REALOPND:tipo2=REALOPND;valfloat2 = quad-tipo2=REALOPND;valfloat2 = quad->opnd2.atr.valfloat;break;>opnd2.atr.valfloat;break;case CHAROPND:case CHAROPND:tipo2 = INTOPND;valint2 = quad->opnd2.atr.valchar; break;tipo2 = INTOPND;valint2 = quad->opnd2.atr.valchar; break;case VAROPND:case VAROPND:switch (quad->opnd2.atr.simb->tvar) {switch (quad->opnd2.atr.simb->tvar) {case INTEGER: tipo2 = INTOPND;case INTEGER: tipo2 = INTOPND;valint2 = *(quad->opnd2.atr.simb->valint);valint2 = *(quad->opnd2.atr.simb->valint);break;break;case FLOAT: tipo2 = REALOPND;case FLOAT: tipo2 = REALOPND;valfloat2 = *(quad->opnd2.atr.simb->valfloat);valfloat2 = *(quad->opnd2.atr.simb->valfloat);break;break;case CHAR: tipo2 = INTOPND;case CHAR: tipo2 = INTOPND;valint2 = *(quad->opnd2.atr.simb->valchar);valint2 = *(quad->opnd2.atr.simb->valchar);break;break;}}break;break;}}
if (tipo1 == INTOPND && tipo2 == INTOPND)if (tipo1 == INTOPND && tipo2 == INTOPND)*(quad->result.atr.simb->vallogic) = valint1 < *(quad->result.atr.simb->vallogic) = valint1 <
valint2;valint2;if (tipo1 == INTOPND && tipo2 == REALOPND)if (tipo1 == INTOPND && tipo2 == REALOPND)
*(quad->result.atr.simb->vallogic) = valint1 < *(quad->result.atr.simb->vallogic) = valint1 < valfloat2;valfloat2;if (tipo1 == REALOPND && tipo2 == INTOPND)if (tipo1 == REALOPND && tipo2 == INTOPND)
*(quad->result.atr.simb->vallogic) = valfloat1 < *(quad->result.atr.simb->vallogic) = valfloat1 < valint2;valint2;if (tipo1 == REALOPND && tipo2 == REALOPND)if (tipo1 == REALOPND && tipo2 == REALOPND)
*(quad->result.atr.simb->vallogic) = valfloat1 < *(quad->result.atr.simb->vallogic) = valfloat1 < valfloat2;valfloat2;
}}
Eliminar os comentários de Eliminar os comentários de pret012013.datpret012013.dat e e rodarrodar
Exercício 5.8:Exercício 5.8: Execução da quádrupla READ Execução da quádrupla READ
Exemplo:Exemplo: seja o comando seja o comando
ler (a, b, c);ler (a, b, c);
Suas quádruplas:Suas quádruplas:1) PARAM, (VAR, a), (IDLE), (IDLE1) PARAM, (VAR, a), (IDLE), (IDLE2) PARAM, (VAR, b), (IDLE), (IDLE)2) PARAM, (VAR, b), (IDLE), (IDLE)3) PARAM, (VAR, c), (IDLE), (IDLE)3) PARAM, (VAR, c), (IDLE), (IDLE)4) READ, (INT, 3), (IDLE), (IDLE)4) READ, (INT, 3), (IDLE), (IDLE)
1) PARAM, (VAR, a), (IDLE), (IDLE1) PARAM, (VAR, a), (IDLE), (IDLE2) PARAM, (VAR, b), (IDLE), (IDLE)2) PARAM, (VAR, b), (IDLE), (IDLE)3) PARAM, (VAR, c), (IDLE), (IDLE)3) PARAM, (VAR, c), (IDLE), (IDLE)4) READ, (INT, 3), (IDLE), (IDLE))4) READ, (INT, 3), (IDLE), (IDLE))
VAR, aVAR, bVAR, c
pilhaoperando (global)
Preenchida pelas 3 quádruplas PARAM
pilhaopndaux
A ser preenchida pela quádrupla
READ
Execução da quádrupla:Execução da quádrupla:
OPREAD, (INT, 3), (IDLE), (IDLE)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, aVAR, bVAR, c
Execução da quádrupla:Execução da quádrupla:
OPREAD, (INT, 3), (IDLE), (IDLE)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, cVAR, bVAR, a
Leitura dos valores dos operandos: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
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
? ? ?
Programação para executar quádruplas Programação para executar quádruplas OPREADOPREAD::
No switch da função No switch da função InterpCodIntermedInterpCodIntermed::
case OPREAD: ExecQuadRead (quad); break;
Os dados de entrada para a execução do programa ficarão num arquivo denominado “entrada”
Nova variável global: FILE *finput;
Associação com o arquivo de entrada, no início da função InterpCodIntermedInterpCodIntermed::finput = fopen ("entrada", "r");
Função Função ExecQuadReadExecQuadRead (já tem protótipo): (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 <= quad->opnd1.atr.valint; i++) {
EmpilharOpnd (TopoOpnd (pilhaopnd), &pilhaopndaux);
DesempilharOpnd (&pilhaopnd);}
for (i = 1; i <= quad->opnd1.atr.valint; i++) {for (i = 1; i <= quad->opnd1.atr.valint; i++) {opndaux = TopoOpnd (pilhaopndaux);opndaux = TopoOpnd (pilhaopndaux);DesempilharOpnd (&pilhaopndaux);DesempilharOpnd (&pilhaopndaux);
switch (opndaux.atr.simb->tvar) {switch (opndaux.atr.simb->tvar) { case INTEGER:case INTEGER: fscanf (fscanf (finputfinput, "%d", opndaux.atr.simb-, "%d", opndaux.atr.simb-
>valint); break;>valint); break; case FLOAT:case FLOAT: fscanf (fscanf (finputfinput, "%g", opndaux.atr.simb-, "%g", opndaux.atr.simb-
>valfloat);break;>valfloat);break; case LOGICAL:case LOGICAL: fscanf (fscanf (finputfinput, "%d", opndaux.atr.simb-, "%d", opndaux.atr.simb-
>vallogic); break;>vallogic); break; case CHAR:case CHAR: fscanf (fscanf (finputfinput, "%c", opndaux.atr.simb-, "%c", opndaux.atr.simb-
>valchar); break;>valchar); break; }}
}}}}
Executar com o arquivo pret022013.dat
Seu conteúdo e o do arquivo entrada vem a seguir
Arquivo Arquivo pret022013.datpret022013.dat::
programa teste;var
int i, j, k; real x, y; logic a, b; carac m, n;{
ler (i, j, x, b);escrever ("i: ", i, "; j: ", j, "; x: ", x, "; b: ", b);k := i + j;y := x + 3.4;a := i < j;escrever ("k: ", k, "; y: ", y, "; a: ", a);
ler (m); n := m + ' ';
escrever ("m: ", m, "; n: ", n);}
Arquivo entrada:
30 20 3.14 1W