1 / 78

CES-41 COMPILADORES Aulas Práticas - 2012

CES-41 COMPILADORES Aulas Práticas - 2012. Capítulo IV Código Intermediário no Yacc. O sub-set da Linguagem COMP-ITA-2012 , usado no final do capítulo anterior, contém: Comandos de atribuição, compostos, entrada e saída, condicionais, enquanto, variáveis escalares e indexadas

yuma
Download Presentation

CES-41 COMPILADORES Aulas Práticas - 2012

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

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

  3. primos { locais: logico achou; int n, div, resto, cont, num; comandos: ler (n); se (n > 0) { num <- 0; cont <- 0; enquanto (cont < n) { num <- num + 1; div <- 2; achou <- falso; enquanto (achou = falso && div * div <= num) { resto <- num % div; se (resto = 0) achou <- verdade; senao div <- div + 1; } se (achou = falso) {escrever (num); cont <- cont + 1;} } } }

  4. Um possível código intermediário não otimizado: primos { locais: logico achou; int n, div, resto, cont, num; 1) OPENMOD, (MODULO, primos), (IDLE), (IDLE) ler (n); 2) PARAM, (VAR, n), (IDLE), (IDLE) 3) READ, 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 se (n > 0) { - - - - - } 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 enquanto (cont < n) { - - - - - } 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 <- falso; 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. enquanto (achou = falso && div * div <= num) { - - - - - } 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; se (resto = 0) achou <- verdade; senao 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. se (achou = falso) {escrever (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 ##global destinam-se a: alocar as variáveis globais chamar o módulo principal e encerrar tudo no final

  12. Estrutura de dados para código intermediário de linguagens sem subprogramas: 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

  13. Programa 4.1: • O arquivo inter012012.y tem um analisador semântico quase acabado para a linguagem Sub-Set2 2012 • O arquivo inter012012.l é seu analisador léxico • O arquivo inter012012.y contém ainda declarações e funções para auxiliar a construção do código intermediário • Rodar esses arquivos com inter012012.dat • A seguir, uma descrição dessas declarações e funções

  14. 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

  15. 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

  16. 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:

  17. 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

  18. 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

  19. #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 NOTVAR 0 #define INTEGER 1 #define LOGIC 2 #define FLOAT 3 #define CHAR 4

  20. 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

  21. 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

  22. 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);

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

  24. 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

  25. 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 ●

  26. 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 = TRUE; simb->array = FALSE;return simb; } O tipo da nova variável vem como argumento

  27. 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 Termo : Termo OPMULT Fator Deve ser gerada a quádrupla com: operador correspondente ao atributo de OPMULT primeiro operando: no atributo de Termo do lado direito segundo operando: no atributo de Fator operando resultado: no atributo de Termo do lado esquerdo

  28. Não-terminais para a montagem de expressões: Expressao, ExprAux1, ExprAux2, ExprAux3, ExprAux4, Termo, Fator • Esses não-terminais já guardam seus tipos em seus atributos, para os testes de compatibilidade entre operadores e operandos: %type <tipoexpr> Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator • Agora, o atributo desses não-terminais deverá ter dois campos: o tipo e o operando

  29. Seja também a produção: Fator : Variavel • É conveniente também que o não-terminalVariavelcarregue um operando em seu atributo, para que o operando de Fator 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> Variavel • Agora, o atributo desse não-terminal deverá ter dois campos: o referido ponteiro e o operando

  30. 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; }

  31. 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> Variavel %type <infoexpr> Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator Antes era <simb> Antes era <tipoexpr>

  32. 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 Variavel, foi trocado $$ por $$.simb e $1, $2, etc. por $1.simb, $2.simb, etc.

  33. 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-terminalPrograma: Programa : { InicTabSimb (); InicCodIntermed (); numtemp = 0; } ID ABCHAVE { printf ("\n%s {\n", $2); simb =InsereSimb ($2, IDPROG, NOTVAR); InicCodIntermMod (simb); } DeclLocsCmds FCHAVE { printf ("}\n"); VerificaInicRef (); ImprimeTabSimb (); ImprimeQuadruplas (); } ; Acrescentar ao arquivo inter012012.y o código em destaque Rodar com o arquivo inter012012.dat

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

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

  36. É 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

  37. Na produção do não-terminalVariavel, calcula-se seu operando: Variavel: ID {- - - - -} ListSubscr { $$.simb = $<simb>2; if ($$.simb != NULL) { if (- - - - -) NaoEsperado ("Subscrito\(s)"); else if (- - - - -) Esperado ("Subscrito\(s)"); else if (- - - - -) Incompatibilidade (- - - - -); $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = $$.simb; } } ;

  38. Nas produções sem operadores do não-terminalFator, calcula-se seu operando: Fator : Variavel { if ($1.simb != NULL) { - - - - - $$.tipo = $1.simb->tvar; $$.opnd = $1.opnd; } } | CTINT { - - - - - $$.tipo = INTEGER; $$.opnd.tipo = INTOPND; $$.opnd.atr.valint = $1; } | CTREAL { - - - - - $$.tipo = FLOAT; $$.opnd.tipo = REALOPND; $$.opnd.atr.valfloat = $1; }

  39. Fator: CTCARAC { - - - - - $$.tipo = CHAR; $$.opnd.tipo = CHAROPND; $$.opnd.atr.valchar = $1; } | VERDADE { - - - - - $$.tipo = LOGIC; $$.opnd.tipo = LOGICOPND; $$.opnd.atr.vallogic = 1; } | FALSO { - - - - - $$.tipo = LOGIC; $$.opnd.tipo = LOGICOPND; $$.opnd.atr.vallogic = 0; } | ABPAR {- - - - -} Expressao FPAR { - - - - - $$.tipo = $3.tipo; $$.opnd = $3.opnd; }

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

  41. Rodar com o arquivo inter012012. dat • Produções do não-terminalTermo: Termo : Fator | Termo OPMULT {- - - - -} Fator { 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

  42. 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; logico 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)

  43. Exercício 4.5: Inserir quádruplas para comandos condicionais • Primeiramente, sejam os comandos se sem senao • Exemplo: as quádruplas para o comando se (i < j) { 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 inter022012.y, inter022012.l e inter022012.dat

  44. Arquivo inter022012.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 inter022012.dat • Rodar flex, yacc, gcc e executável gerado • A cada implementação, alterar os comentários em inter022012.dat

  45. A programação para se sem senao está na produção do não-terminalCmdSe: CmdSe : SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $<quad>5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }CmdSenao ; É necessário acrescentar o campo quadna declaração %union:quadruplaquad;

  46. A programação para se sem senao está na produção do não-terminalCmdSe: CmdSe : SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $<quad>5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }CmdSenao ; No arquivo inter022012.dat, tirar o comentário do se sem senaoe rodar

  47. CmdSe : SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $<quad>5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }CmdSenao ; $5 Expressao ----- JF NOP ----- ##n ----- ----- ----- ----- ##n ----- ROT A quádrupla destino do desvio é gerada na produção de CmdSe NOP é eliminada na otimização do código intermediário ? Comando

  48. Sejam agora os comandos se com senao • Exemplo: as quádruplas para os comandos se (i < j) { i <- i+3; n <- v/h; } senao { 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)

  49. A programação para se com senao está nas produções dos não-terminais CmdSe e CmdSenao: CmdSe : SE ABPAR {- - - - -} Expressao { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR {printf (") ");} Comando { $<quad>$ = quadcorrente; $<quad>5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao{ if ($<quad>9->prox != quadcorrente) { quadaux = $<quad>9->prox; $<quad>9->prox = quadaux->prox; quadaux->prox = $<quad>9->prox->prox; $<quad>9->prox->prox = quadaux; RenumQuadruplas ($<quad>9, quadcorrente); } } ;

  50. CmdSenao : | SENAO { - - - - - opndaux.tipo = ROTOPND; $<quad>$ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { $<quad>2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } ; No arquivo inter022012.dat, tirar o comentário do se com senaoe rodar

More Related