1 / 54

CES-41 COMPILADORES Aulas Práticas - 2013

CES-41 COMPILADORES Aulas Práticas - 2013. Capítulo V Interpretação do Código Intermediário. Código intermediário para linguagens sem subprogramas :. Interpretação: Colocar um ponteiro na 1ª quádrupla executável

harsha
Download Presentation

CES-41 COMPILADORES Aulas Práticas - 2013

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CES-41 COMPILADORESAulas Práticas - 2013 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: Deve-se acrescentar os seguintes campos emcelsimb: dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic Poderia ser usada union int *valint; float *valfloat; char *valchar, *vallogic; Espaço para estes ponteiros serão alocados na execução da quádrupla OPENMOD

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

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

  6. voidInterpCodIntermed () { quadruplaquad, quadprox; char encerra; printf ("\n\nINTERPRETADOR:\n"); encerra = FALSE; 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 = TRUE; break; } if (! encerra) quad = quadprox; } printf ("\n"); } quad

  7. Definição do operador de quádrupla OPEXIT: #define OPEXIT 24 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; 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): voidInterpCodIntermed (void); voidAlocaVariaveis (void); voidExecQuadWrite (quadrupla); voidExecQuadMais (quadrupla); voidExecQuadLT (quadrupla); void ExecQuadAtrib (quadrupla); void ExecQuadRead (quadrupla);

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

  10. programa teste; var int a, b, c, i, j; real k; logic b1; int A[5,4]; { escrever ("Valor 1: ", 14, "; Valor 2: ", 15.2, "; Valor 3: ", verdade); escrever ("Valor de 3+4: ", 3+4); a := 1; b := 2; i := 3; j := 4; c := a + b + i + j + 20; k := 12.6; b1 := verdade; escrever ("c = ", c, "; k = ", k, "; b1 = ", b1, ";");

  11. i := 4; j := 5; b1 := verdade; se (b1) {i := j + 6;} senao {i := i + 15;} escrever ("i = ", i); i := 4; j := 5; b1 := verdade; enquanto (b1) {i := i + j; b1 := falso;} escrever ("i = ", i); i := 3; k := 20.3; escrever ("i = ", i, "; k = ", k); /* enquanto (i < k) { i := i + 4; escrever ("i = ", i, "; k = ", k); } */ escrever ("Valor de i+k: ", i+k); }

  12. Exercício 5.1: Execução da quádrupla OPENMOD No switch da função InterpCodIntermed: case OPENMOD: AlocaVariaveis (); break; 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; real A[5,4]; dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic A v r s 3 # 5 4 ? ? ? dims - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic cadeia tid tvar inic ref array ndims x v i n ? ? ? Apenas um elemento inteiro alocado para x 5*4 = 20 elementos reais alocados para A

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

  15. Exercício 5.2: Execução da quádrupla PARAM Exemplo: seja o comando escrever ("Valor de a+b:", a+b, "Valor de c:", c); 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) VAR, c CADEIA, Valor de c: VAR, ##1 CADEIA, Valor de a+b: 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 VAR, c CADEIA, Valor de c: VAR, ##1 CADEIA, Valor de a+b: 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 pret012013.y): typedefstructnohopndnohopnd; structnohopnd { operando opnd; nohopnd *prox; }; typedefnohopnd *pilhaoperando; pilhaoperandopilhaopnd, pilhaopndaux;

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

  21. operando TopoOpnd (pilhaoperando P) { if (! VaziaOpnd (P)) return P->opnd; elseprintf ("\n\tTopo de pilha vazia\n"); } voidInicPilhaOpnd (pilhaoperando *P) { *P = NULL; } charVaziaOpnd (pilhaoperando P) { if (P == NULL) return 1; elsereturn 0; }

  22. Programação para executar quádruplas PARAM 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: case PARAM: EmpilharOpnd (quad->opnd1, &pilhaopnd); break;

  23. Exercício 5.3: Execução da quádrupla OPWRITE 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 impresso 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 dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic A v r s 3 # 5 4 ? ? ? dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic x v i n ? ? ?

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

  27. for (i = 1; i <= quad->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 ("VERDADE"); else printf ("FALSO"); break; case CADOPND: printf ("%s", opndaux.atr.valcad); break ;

  28. case VAROPND: switch (opndaux.atr.simb->tvar) { case INTEGER: printf ("%d", *(opndaux.atr.simb->valint)); break; case FLOAT: printf ("%g", *(opndaux.atr.simb->valfloat));break; case LOGICAL: if (*(opndaux.atr.simb->vallogic) == 1) printf ("VERDADE"); else printf ("FALSO"); break; case CHAR: printf ("%c", *(opndaux.atr.simb->valchar)); break; } break; } } printf ("\n"); } Executar observando os valores escritos pelas quádruplas OPWRITE

  29. Exercício 5.4: Execução da quádrupla OPMAIS Exemplo: 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: case OPMAIS: ExecQuadMais (quad); break; Função ExecQuadMais (já tem protótipo): voidExecQuadMais (quadruplaquad) { int tipo1, tipo2, valint1, valint2; float valfloat1, valfloat2; Guardam os valores a serem somados, conforme os tipos Guardam os tipos dos valores a serem somados

  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 INTEGER: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case FLOAT: tipo1 = REALOPND; valfloat1=*(quad->opnd1.atr.simb->valfloat);break; case CHAR: 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 INTEGER: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valint); break; case FLOAT: tipo2 = REALOPND; valfloat2=*(quad->opnd2.atr.simb->valfloat);break; case CHAR: tipo2 = INTOPND; valint2=*(quad->opnd2.atr.simb->valchar);break; } break; }

  33. switch (quad->result.atr.simb->tvar) { case INTEGER: *(quad->result.atr.simb->valint) = valint1 + valint2; break; case FLOAT: 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 Suasquádruplaspodem 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: case OPATRIB: ExecQuadAtrib (quad); break; Função ExecQuadAtrib (já tem protótipo): voidExecQuadAtrib (quadruplaquad) { int tipo1, valint1; float valfloat1; char valchar1, vallogic1; Guardam os valores a serem atribuídos, conforme os tipos Guarda o tipo do valor a ser atribuído

  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 INTEGER: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case FLOAT: tipo1 = REALOPND; valfloat1=*(quad->opnd1.atr.simb->valfloat);break; case CHAR: tipo1 = CHAROPND; valchar1=*(quad->opnd1.atr.simb->valchar);break; case LOGICAL: tipo1 = LOGICOPND; vallogic1 = *(quad->opnd1.atr.simb->vallogic); break; } break; }

  38. switch (quad->result.atr.simb->tvar) { case INTEGER: if (tipo1 == INTOPND) *(quad->result.atr.simb->valint) = valint1; if (tipo1 == CHAROPND)*(quad->result.atr.simb->valint)=valchar1; break; case CHAR: if (tipo1 == INTOPND) *(quad->result.atr.simb->valchar) = valint1; if (tipo1==CHAROPND)*(quad->result.atr.simb->valchar)=valchar1; break; case LOGICAL: *(quad->result.atr.simb->vallogic) = vallogic1; break; case FLOAT: 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 enquanto (i < j) i := j + h; Suas quádruplas: 2) NOP, (IDLE), (IDLE), (IDLE) 3) LT, (VAR, i), (VAR, j), (VAR, ##1) 4) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 5) MAIS, (VAR, j), (VAR, h), (VAR, ##2) 6) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 7) JUMP, (IDLE), (IDLE), (ROTULO, 2) 8) NOP, (IDLE), (IDLE), (IDLE)

  40. Nova declaração na função InterpCodIntermed: charcondicao; 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 se-senao e enquanto

  41. Exercício 5.7: Execução da quádrupla OPLT No switch da função InterpCodIntermed: case OPLT: ExecQuadLT (quad); break; Função ExecQuadLT (já tem protótipo): voidExecQuadLT (quadruplaquad) { 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 INTEGER: tipo1 = INTOPND; valint1 = *(quad->opnd1.atr.simb->valint); break; case FLOAT: tipo1 = REALOPND; valfloat1 = *(quad->opnd1.atr.simb->valfloat); break; case CHAR: 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 INTEGER: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valint); break; case FLOAT: tipo2 = REALOPND; valfloat2 = *(quad->opnd2.atr.simb->valfloat); break; case CHAR: tipo2 = INTOPND; valint2 = *(quad->opnd2.atr.simb->valchar); break; } break; }

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

  45. Exercício 5.8: Execução da quádrupla READ Exemplo: seja o comando ler (a, b, c); 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, c VAR, b VAR, a 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 VAR, c VAR, b VAR, a pilhaoperando (global) Preenchida pelas 3 quádruplas PARAM pilhaopndaux A ser preenchida pela quádrupla READ

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

  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 dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic A v r s 3 # 5 4 ? ? ? dims cadeia tid tvar inic ref array ndims - - - - - - - - - - - - - - - - - - - valint valfloat valchar vallogic x v i n ? ? ?

More Related