1 / 81

CES-41 COMPILADORES Aulas Práticas - 2014

CES-41 COMPILADORES Aulas Práticas - 2014. Capítulo IV Código Intermediário no Yacc. O sub-set da Linguagem COMP-ITA-2014 , 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

Download Presentation

CES-41 COMPILADORES Aulas Práticas - 2014

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 - 2014 Capítulo IV Código Intermediário no Yacc

  2. O sub-set da Linguagem COMP-ITA-2014, 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 2014 • Seja o programa a seguir, escrito em Sub-Set2 2014, 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"); 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: 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. 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 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)

  6. 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 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)

  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 inter012014.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2014 • O arquivo inter012014.l é seu analisador léxico • O arquivo inter012014.y contém ainda declarações e funções para auxiliar a construção do código intermediário • Rodar esses arquivos com inter012014.dat • A seguir, uma descrição dessas declarações e funções

  15. celquad • Estrutura de uma quádrupla: typedefstructcelquadcelquad; typedefcelquad *quadrupla; structcelquad { int num, oper; operando opnd1, opnd2, result; quadruplaprox; }; • 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 oper opnd1 num opnd2 result prox

  16. operando tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) • Estrutura de um operando: typedefstructoperandooperando; structoperando { inttipo; atribopndatr; }; • 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

  17. operando tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) • Estrutura do atributo de um operando: typedef union atribopndatribopnd; union atribopnd { simbolosimb; intvalint; float valfloat; char valchar; char vallogic; char *valcad; quadruplarotulo; modhead modulo; }; • Tabela dos atributos conforme o tipo de operando:

  18. celmodhead modname • Estrutura de um cabeçalho de módulo: typedef struct celmodheadcelmodhead; typedefcelmodhead *modhead; struct celmodhead { simbolo modname; modhead prox; int modtip; quadruplalistquad; }; modtip prox  listquad

  19. Variáveis globais: quadruplaquadcorrente, quadaux; modhead codintermed, modcorrente; intoper, numquadcorrente; operando opnd1, opnd2, result, opndaux; intnumtemp; const operandoopndidle = {IDLEOPND, 0}; • quadcorrente: ponteiro para a celquad recém-alocada • codintermed: ponteiro que dá acesso a todo o código intermediário • modcorrente: ponteiro para a última celmodhead alocada • 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

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

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

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

  23. Protótipos das funções para o código intermediário: void InicCodIntermed (void); void InicCodIntermMod (simbolo); quadruplaGeraQuadrupla (int, operando, operando, operando); simboloNovaTemp (int); voidImprimeQuadruplas (void); voidRenumQuadruplas (quadrupla, quadrupla);

  24. codintermed modname modtip ● • Função InicCodIntermed: void InicCodIntermed () { codintermed = malloc (sizeof (celmodhead)); modcorrente = codintermed; modcorrente->listquad = NULL; modcorrente->prox = NULL; } prox ● listquad modcorrente

  25. codintermed simb tid cadeia modname modname modtip modtip ● ● • Função InicCodIntermMod (simbolosimb): void InicCodIntermMod (simbolosimb) { 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; } prox prox ● listquad listquad modcorrente num oper #### opnd1 #### opnd2#### result #### prox 0 ● quadcorrente

  26. Função GeraQuadrupla (oper, opnd1, opnd2, result): quadruplaGeraQuadrupla (intoper, 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; return quadcorrente; } num 452 oper X opnd1 YYYY opnd2 ZZZZ result WWWW prox num oper opnd1 opnd2 result prox ● quadcorrente 453 R SSSS TTTT valor retornado VVVV opnd2 result opnd1 oper R VVVV SSSS TTTT ●

  27. 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 • Função Novatemp (tip): simboloNovaTemp (inttip) { simbolosimb; inttemp, i, j; charnometemp[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; } 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 • 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 Termdo lado direito segundo operando: no atributo de Factor operando resultado: no atributo de Termdo lado esquerdo

  29. 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: %type <tipoexpr> Expression AuxExpr1 AuxExpx2 AuxExpr3 AuxExpr4 TermFactor • Agora, o atributo desses não-terminais deverá ter dois campos: o tipo e o operando

  30. Seja também a produção: Factor : Variable • É conveniente também que o não-terminalVariablecarregue 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: %type <simb> Variable • 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: typedefstructinfoexpressaoinfoexpressao; structinfoexpressao { int tipo; operando opnd; }; typedefstructinfovariavelinfovariavel; structinfovariavel { simbolosimb; operando opnd; }; • Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; charcarac; infoexpressaoinfoexpr; infovariavelinfovar; simbolosimb; int dim; int nsubscr; }

  32. Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; charcarac; infoexpressaoinfoexpr; infovariavelinfovar; simbolosimb; int dim; int nsubscr; } • Novas especificações para os atributos dos não-terminais envolvidos: %type <infovar> Variable %type <infoexpr> Expression AuxExpr1 AuxExpr2 AuxExpr3 AuxExpr4 TermFactor Antes era <simb> Antes era <tipoexpr>

  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 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-terminalProg: Prog : { InicTabSimb (); InicCodIntermed (); numtemp = 0; } PROGRAM ID {printf ("program %s\n", $3); simb = InsereSimb ($3, IDPROG, NAOVAR); InicCodIntermMod (simb); } LocDeclsStats { VerificaInicRef (); ImprimeTabSimb (); ImprimeQuadruplas (); } ; Acrescentar ao arquivo inter012014.y o código em destaque Rodar com o arquivo inter012014.dat

  35. Exercício 4.2: Inserir a quádrupla OPENMOD • Ainda na produção do não-terminalProg: Prog: {- - - - -} PROGRAM ID { - - - - - InicCodIntermMod (simb); opnd1.tipo = MODOPND; opnd1.atr.modulo = modcorrente; GeraQuadrupla (OPENMOD, opnd1, opndidle, opndidle); } LocDeclsStats { - - - - - } ; Acrescentar ao arquivo inter012014. y o código em destaque Rodar com o arquivo inter012014. dat

  36. Exercício 4.3: Inserir quádruplas para expressões sem variáveis indexadas • 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 • 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

  38. Na 1ª produção do não-terminalVariable(sem subscritos), calcula-se seu operando: Variable: ID { - - - - - $$.simb = simb; if ($$.simb != NULL) { if ($$.simb->array == VERDADE) if (usastr == FALSO) Esperado ("Subscrito\(s)"); else if ($$.simb->ndims != 1) Esperado ("Subscrito\(s)"); $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = $$.simb; } }

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

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

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

  42. Rodar com o arquivo inter012014. dat • Produções do não-terminalTerm: 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); elseGeraQuadrupla (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; } } ; 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: 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 • 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) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 8) NOP, (IDLE), (IDLE), (IDLE) Usar os arquivos inter022014.y, inter022014.l e inter022014.dat

  45. Arquivo inter022014.y: • Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição • FunçãoRenumQuadruplas (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 inter022014.dat • Rodar flex, yacc, gcc e executável gerado • A cada implementação, alterar os comentários em inter022014.dat

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

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

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

  49. Sejam agora os comandos if com else • 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: IfStat : IF { - - - - - } Expression { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJF, $3.opnd, opndidle, opndaux); } THEN {printf ("then\n");} Statement { $<quad>$ = quadcorrente; $<quad>4->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ElseStat{ if ($<quad>8->prox != quadcorrente) { quadaux = $<quad>8->prox; $<quad>8->prox = quadaux->prox; quadaux->prox = $<quad>8->prox->prox; $<quad>8->prox->prox = quadaux; RenumQuadruplas ($<quad>8, quadcorrente); } } ;

More Related