CES-41 COMPILADORES Aulas Práticas - 2013 Capítulo IV Código Intermediário no Yacc.

Slides:



Advertisements
Apresentações semelhantes
IFTO ESTRUTURA DE DADOS AULA 05 Prof. Manoel Campos da Silva Filho
Advertisements

Aula T10 – BCC202 Listas – Parte 2 Túlio Toffolo www. decom. ufop
Programação em Java Prof. Maurício Braga
Programação em Java Prof. Maurício Braga
Introdução à Programação Engenharia da Computação
Capítulo II – Algoritmos e Programas
Estruturas de Repetição
Linguagem de Programação VI Tipos de Dados Compostos - structs
Listas encadeadas Prof. Rosana Palazon.
Listas duplamente encadeadas
Ludwig Krippahl, 2007 Programação para as Ciências Experimentais 2006/7 Teórica 3.
Software Básico Silvio Fernandes
Excel Profa. Cristina M. Nunes.
Algoritmos e Estrutura de Dados I
1 Tipos definidos O programador pode definir seus próprios tipos de dados tipos complexos usados da mesma forma que os simples declaram-se variáveis utilizando-se.
Árvores.
EXPRESSÕES ARITMÉTICAS
Estruturas de Dados e Algoritmos
LPG - I: Ponteiros e Vetores/Matrizes UDESC - SBS
Estruturas de Dados I Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Estruturas de Dados II Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Estruturas de Dados II Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Instrutor: Nilo Menezes
Aula 4 Nomes, Vinculações, Tipos e Escopos
Ponteiros.
Lista Encadeada Circular Lista Duplamente Encadeada
Tratamento de Ficheiros
Programação Baseada em Objectos Desenho de TAD
Listas Encadeadas.
Revisão da Linguagem C.
Classes e objetos Arrays e Sobrecarga
Classes e objetos P. O. O. Prof. Grace.
Apontadores ou Ponteiros
O Portal do Estudante de Computação
exercícios listas encadeadas
Árvores binárias de pesquisa com balanceamento
Estruturas de Dados com Jogos
Estruturas de Dados com Jogos
Funções Universidade Federal de Ouro Preto - UFOP
Principais operações em Listas TPA Listas Simples Inserção no Final 1.void insereNofinalDaLista(Lista *l, Elemento e){ 2.Lista paux,p; 3. p.
Estrutura de dados II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Entendendo as definições de classe
Seminário 1: Revisão de C
Denise Guliato Faculdade de Computação – UFU
Semana 03 Comandos de desvio de fluxo. Expressões lógicas.
EXERCÍCIOS PARA GUARDA-REDES
Prof. Ricardo Santos PONTEIROS
1 2 Observa ilustração. Cria um texto. Observa ilustração.
Aula 6 - Estruturas de Controle
Linguagem e Ambiente Scratch
CES-41 COMPILADORES Aulas Práticas Capítulo V Interpretação do Código Intermediário.
Geração de Código Intermediário
Capítulo II Gramáticas e Linguagens
Estruturas de Dados Aula 11: TAD Pilha
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática
Comandos SQL.
Estruturas de Dados Aula 17: Estruturas Genéricas
Aula prática 2 Operadores e Expressões Comandos de Decisão Comentários
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática
CES-41 COMPILADORES Aulas Práticas Capítulo II A Ferramenta Yacc.
CES-41 COMPILADORES Aulas Práticas Capítulo III Análise Semântica no Yacc.
CES-41 COMPILADORES Aulas Práticas
CES-10 INTRODUÇÃO À COMPUTAÇÃO
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2014 Capítulo X Encadeamento de Estruturas por Ponteiros.
CES-41 COMPILADORES Aulas Práticas Capítulo IV Código Intermediário no Yacc.
CES-41 COMPILADORES Aulas Práticas Capítulo III Análise Semântica no Yacc.
CES-41 COMPILADORES Aulas Práticas
CES-41 COMPILADORES Aulas Práticas
CES-41 COMPILADORES Aulas Práticas
Transcrição da apresentação:

CES-41 COMPILADORES Aulas Práticas Capítulo IV Código Intermediário no Yacc

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

programa primos; var logic achou; int n, div, resto, cont, num; { ler (n); escrever (n, " primeiros numeros naturais primos:\n\n"); escrever (n, " primeiros numeros naturais primos:\n\n"); se (n > 0) { num := 1; 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, "\n"); cont := cont + 1; }}} senao escrever ("O valor de entrada deveria ser maior que zero"); senao escrever ("O valor de entrada deveria ser maior que zero");}

Um possível código intermediário não otimizado: Um possível código intermediário não otimizado: programa primos; var logic achou; int n, div, resto, cont, num; 1) OPENMOD, (MODULO, primos), (IDLE), (IDLE) ler (n); 2) PARAM, (VAR, n), (IDLE), (IDLE) 3) READ, (INT, 1), (IDLE), (IDLE)

se (n > 0) { } 4) GT, (VAR, n), (INT, 0), (VAR, ##1) 5) JF, (VAR, ##1), (IDLE), (ROTULO, 42) ) NOP, (IDLE), (IDLE), (IDLE) num := 0; cont := 0; 6) ATRIB, (INT, 0), (IDLE), (VAR, num) 7) ATRIB, (INT, 0), (IDLE), (VAR, cont) NOP: no operation Todos os desvios serão feitos para quádruplas com NOPs 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) ) 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) NOP: no operation Todos os desvios serão feitos para quádruplas com NOPs Facilitam a programação Devem ser eliminadas na fase de otimização

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) ) JUMP, (IDLE), (IDLE), (ROTULO, 15) 32) NOP, (IDLE), (IDLE), (IDLE)

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)

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

Estrutura de dados para o código intermediário de linguagens contendo subprogramas:

Cada lista de quádruplas fica acoplada a um mod-head As quádruplas do módulo prog destinam-se a: alocar as variáveis do programa principal (globais) executar o programa principal e encerrar tudo no final

A lista de mod-heads tem um nó-líder e cada lista de quádruplas também tem

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

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

Estrutura de uma quádrupla: Estrutura de uma quádrupla: typedef struct celquad celquad; typedef celquad *quadrupla; struct celquad { int num, oper; operando opnd1, opnd2, result; quadrupla prox; }; O campo num numera as quádruplas O campo num numera as quádruplas Não é necessário na compilação Não é necessário na compilação Foi colocado por razões didáticas Foi colocado por razões didáticas Um operando tem dois campos: o tipo e o atributo Um operando tem dois campos: o tipo e o atributo operopnd1 opnd2result prox num celquad

Estrutura de um operando: Estrutura de um operando: typedef struct operando operando; struct operando { int tipo; atribopnd atr; }; Os tipos dos operandos são: Os tipos dos operandos são: Operando vazio (idle) Operando vazio (idle) Nome de variável Nome de variável Constantes inteira, real, lógica e caractere Constantes inteira, real, lógica e caractere Cadeia de caracteres Cadeia de caracteres Rótulo de quádruplas (ponteiro para quádruplas) Rótulo de quádruplas (ponteiro para quádruplas) Nome de módulo Nome de módulo tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) operando

Estrutura do atributo de um operando: Estrutura do atributo de um operando: typedef union atribopnd atribopnd; union atribopnd { simbolo simb; int valint; float valfloat; char valchar; char vallogic; char *valcad; quadrupla rotulo; modhead modulo; }; Tabela dos atributos conforme o tipo de operando: Tabela dos atributos conforme o tipo de operando: TipoAtributoTipoAtributo Idle-Constante caracterevalchar Nome de variávelsimbCadeia de caracteresvalcad Constante inteiravalintRótulo de quádruplarotulo Constante realvalfloatNome de módulomodulo Constante lógicavallogic tipo atr (simb, valint, valfloat, valchar, vallogic, valcad, rotulo, modulo) operando

Estrutura de um cabeçalho de módulo: Estrutura de um cabeçalho de módulo: typedef struct celmodhead celmodhead; typedef celmodhead *modhead; struct celmodhead { simbolo modname; modhead prox; int modtip; quadrupla listquad; }; modname modtip celmodhead prox listquad

Variáveis globais: Variáveis globais: quadrupla quadcorrente, quadaux; modhead codintermed, modcorrente; int oper, numquadcorrente; operando opnd1, opnd2, result, opndaux; int numtemp; const operando opndidle = {IDLEOPND, 0}; quadcorrente: ponteiro para a celquad recém-alocada quadcorrente: ponteiro para a celquad recém-alocada codintermed: ponteiro que dá acesso a todo o código intermediário codintermed: ponteiro que dá acesso a todo o código intermediário modcorrente: ponteiro para a última celmodhead alocada modcorrente: ponteiro para a última celmodhead alocada numtemp: usada para controlar a concessão de nomes a variáveis temporárias 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 opndidle: constante do tipo operando para preencher operandos vazios nas quádruplas

Novas definições para os tipos dos identificadores: Novas definições para os tipos dos identificadores: Relembrando as definições para os tipos de variáveis: Relembrando as definições para os tipos de variáveis: #define IDPROG1 #define IDVAR2 #define IDFUNC3 #define IDPROC4 #define NOTVAR0 #define INTEGER1 #define LOGIC2 #define FLOAT3 #define CHAR4

Definições de constantes para operadores de quádruplas: Definições de constantes para operadores de quádruplas: #defineOPOR1 #defineOPAND2 #define OPLT 3 #define OPLE 4 #defineOPGT 5 #defineOPGE6 #defineOPEQ7 #defineOPNE8 #defineOPMAIS9 #defineOPMENOS10 #defineOPMULTIP11 #defineOPDIV12 #defineOPRESTO13 #defineOPMENUN14 #defineOPNOT15 #defineOPATRIB16 #defineOPENMOD17 #defineNOP18 #defineOPJUMP19 #defineOPJF20

Definições de constantes para os tipos dos operandos: Definições de constantes para os tipos dos operandos: #defineIDLEOPND0 #defineVAROPND1 #defineINTOPND2 #defineREALOPND3 #defineCHAROPND4 #defineLOGICOPND5 #defineCADOPND6 #defineROTOPND7 #defineMODOPND8

Protótipos das funções para o código intermediário: Protótipos das funções para o código intermediário: void InicCodIntermed (void); void InicCodIntermMod (simbolo); quadrupla GeraQuadrupla (int, operando, operando, operando); simbolo NovaTemp (int); void ImprimeQuadruplas (void); void RenumQuadruplas (quadrupla, quadrupla);

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

Função InicCodIntermMod (simbolo simb): Função InicCodIntermMod (simbolo simb): void InicCodIntermMod (simbolo simb) { 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; } codintermed simb num oper #### opnd1 #### opnd2 #### result #### prox quadcorrente 0 modname modtip prox listquad modname modtip prox listquad modcorrente cadeiatid

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

Função Novatemp (tip): Função Novatemp (tip): simbolo NovaTemp (int tip) { simbolo simb; int temp, i, j; char nometemp[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; } 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 O tipo da nova variável vem como argumento

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

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

Seja também a produção: Seja também a produção: Fator : Variavel É conveniente também que o não-terminal Variavel carregue um operando em seu atributo, para que o operando de Fator receba esse operando É conveniente também que o não-terminal Variavel carregue 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: Esse não-terminal já guarda em seu atributo um ponteiro para a TabSimb, para os testes de compatibilidade entre operadores e operandos: %type Variavel %type Variavel Agora, o atributo desse não-terminal deverá ter dois campos: Agora, o atributo desse não-terminal deverá ter dois campos: o referido ponteiro e o operando

Novas declarações para atributos de expressões e variáveis: Novas declarações para atributos de expressões e variáveis: typedef struct infoexpressao infoexpressao; struct infoexpressao { int tipo; operando opnd; }; typedef struct infovariavel infovariavel; struct infovariavel { simbolo simb; operando opnd; }; Novos campos para a declaração %union: Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; char carac; infoexpressao infoexpr; infovariavel infovar; simbolo simb; int dim; int nsubscr; }

Novos campos para a declaração %union: Novos campos para a declaração %union: %union { char cadeia[50]; int atr, valint; float valreal; char carac; infoexpressao infoexpr; infovariavel infovar; simbolo simb; int dim; int nsubscr; simbolo simb; int dim; int nsubscr;} Novas especificações para os atributos dos não-terminais envolvidos: Novas especificações para os atributos dos não-terminais envolvidos: %type Variavel %type Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator Antes era

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 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. Nas ocorrências de atributos do não terminal Variavel, foi trocado $$ por $$.simb e $1, $2, etc. por $1.simb, $2.simb, etc.

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-terminal Prog: Na produção do não-terminal Prog: Prog:{ InicTabSimb (); InicCodIntermed (); numtemp = 0; } PROGRAMA ID PVIRG { printf ("programa %s ;\n", $3); simb = InsereSimb ($3, IDPROG, NOTVAR); simb = InsereSimb ($3, IDPROG, NOTVAR); InicCodIntermMod (simb); InicCodIntermMod (simb); } Decls CmdComp { VerificaInicRef (); ImprimeTabSimb (); VerificaInicRef (); ImprimeTabSimb (); ImprimeQuadruplas (); ImprimeQuadruplas (); }; Acrescentar ao arquivo inter y o código em destaque Rodar com o arquivo inter dat

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

Exercício 4.3: Inserir quádruplas para expressões sem variáveis indexadas Exemplo: as quádruplas para a expressão: 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)

É necessária uma programação em todos os não-terminais envolvendo expressões É 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 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 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

Na 1ª produção do não-terminal Variavel (sem subscritos), calcula-se seu operando: Na 1ª produção do não-terminal Variavel (sem subscritos), calcula-se seu operando: Variavel: ID { $$.simb = simb; $$.simb = simb; if ($$.simb != NULL) { if ($$.simb != NULL) { if ( ) Esperado ("Subscrito\(s)"); $$.opnd.tipo = VAROPND; $$.opnd.atr.simb = $$.simb; $$.opnd.atr.simb = $$.simb; }};

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

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

Na produção do não-terminal Fator, com o operador NEG gera-se uma quádrupla, além de calcular o operando do lado esquerdo: Na produção do não-terminal Fator, 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.tipo = VAROPND; $$.opnd.atr.simb = NovaTemp ($$.tipo); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd); GeraQuadrupla (OPMENUN, $3.opnd, opndidle, $$.opnd);}; Rodar com o arquivo inter dat

Produções do não-terminal Termo: Produções do não-terminal Termo: Termo : Fator /* default: $$ = $1 */ |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); GeraQuadrupla (OPMULTIP, $1.opnd, $4.opnd, $$.opnd); else GeraQuadrupla (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;}}; Rodar com o arquivo inter dat Fazer programação análoga para as produções dos não terminais ExprAux4, ExprAux3, ExprAux2, ExprAux1 e Expressao

Exercício 4.4: Inserir quádruplas para comandos de atribuição Exemplo: as quádruplas para a 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)

Exercício 4.5: Inserir quádruplas para comandos condicionais Primeiramente, sejam os comandos se sem senao Primeiramente, sejam os comandos se sem senao Exemplo: as quádruplas para o comando 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) 2) LT, (VAR, i), (VAR, j), (VAR, ##1) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 3) JF, (VAR, ##1), (IDLE), (ROTULO, 8) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 4) MAIS, (VAR, i), (INT, 3), (VAR, ##2) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 5) ATRIB, (VAR, ##2), (IDLE), (VAR, i) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 6) DIV, (VAR, v), (VAR, h), (VAR, ##3) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 7) ATRIB, (VAR, ##3), (IDLE), (VAR, n) 8) NOP, (IDLE), (IDLE), (IDLE) 8) NOP, (IDLE), (IDLE), (IDLE) Usar os arquivos inter y, inter l e inter dat

Arquivo inter y: Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição Gera quádruplas para abrir módulo, operadores de expressões e comandos de atribuição Função RenumQuadruplas (q1, q2): Função RenumQuadruplas (q1, q2): Algumas quádruplas serão geradas fora de ordem Algumas quádruplas serão geradas fora de ordem Sua ordem deve ser corrigida Sua ordem deve ser corrigida Para fins didáticos, as quádruplas serão renumeradas Para fins didáticos, as quádruplas serão renumeradas Abrir o arquivo inter dat Abrir o arquivo inter dat Rodar flex, yacc, gcc e executável gerado Rodar flex, yacc, gcc e executável gerado A cada implementação, alterar os comentários em inter dat A cada implementação, alterar os comentários em inter dat

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

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

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

Sejam agora os comandos se com senao Sejam agora os comandos se com senao Exemplo: as quádruplas para os comandos 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)

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

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

CmdSe: SE ABPAR { } Expressao { opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux); } FPAR { } Comando { $ $ = quadcorrente; $ 5->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); } CmdSenao { } ; Expressao ##nJF##n-----ROT Comando NOP----- $5 $9

CmdSenao:| SENAO { opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expressao ##nJF##n-----ROT Comando NOP----- $5 $9 JUMP----- ROT $2 As quádruplas NOP e JUMP foram geradas em ordem trocada ?

CmdSenao:| SENAO { opndaux.tipo = ROTOPND; $ $ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux); } Comando { $ 2->result.atr.rotulo = GeraQuadrupla (NOP, opndidle, opndidle, opndidle); }; Expressao ##nJF##n-----ROT Comando NOP----- $5 $9 JUMP----- ROT $2 Comando NOP----- É preciso inverter a ordem das quádruplas NOP e JUMP ?

CmdSe: SE ABPAR { } Expressao { } FPAR { } Comando { } CmdSenao { if ($ 9->prox != quadcorrente) { quadaux = $ 9->prox; $ 9->prox = quadaux->prox; quadaux->prox = $<quad>9->prox->prox; $ 9->prox->prox = quadaux; RenumQuadruplas ($ 9, quadcorrente); }}; Comando NOP----- $9 JUMP----- ROT Comando NOP----- Se a quádrupla seguinte à $9 for a quádrupla corrente, o se não tem senao – não é preciso fazer troca quadaux

Exercício 4.6: Inserir quádruplas para o comando enquanto Exemplo: as quádruplas para o comando Exemplo: as quádruplas para o comando enquanto (i < j) i := j + h; i := 0; podem ser: 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) 9) ATRIB, (INT, 0), (IDLE), (VAR, i) 9) ATRIB, (INT, 0), (IDLE), (VAR, i)

CmdEnquanto: ENQUANTO ABPAR Expressao FPAR Comando ; Expressao ##nJF##n-----ROT Comando NOP----- NOP----- JUMP----- ROT ?

Exercício 4.7: Inserir quádruplas para comandos ler e escrever Exemplo: as quádruplas para os comandos Exemplo: as quádruplas para os comandos ler (a, b, c); escrever ("Valor de a+b:", a+b, "Valor de c:", c); podem ser: 2) PARAM, (VAR, a), (IDLE), (IDLE) 3) PARAM, (VAR, b), (IDLE), (IDLE) 4) PARAM, (VAR, c), (IDLE), (IDLE) 5) READ, (INT, 3), (IDLE), (IDLE) 6) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE), (IDLE) 9) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 10) PARAM, (VAR, c), (IDLE), (IDLE) 11) WRITE, (INT, 4), (IDLE), (IDLE) Os operadores de quádruplas PARAM, OPREAD e OPWRITE já estão declarados no programa inter y

2) PARAM, (VAR, a), (IDLE), (IDLE) 3) PARAM, (VAR, b), (IDLE), (IDLE) 4) PARAM, (VAR, c), (IDLE), (IDLE) 5) READ, (INT, 3), (IDLE), (IDLE) 6) PARAM, (CADEIA, Valor de a+b:), (IDLE), (IDLE) 7) MAIS, (VAR, a), (VAR, b), (VAR, ##1) 8) PARAM, (VAR, ##1), (IDLE), (IDLE) 9) PARAM, (CADEIA, Valor de c:), (IDLE), (IDLE) 10) PARAM, (VAR, c), (IDLE), (IDLE) 11) WRITE, (INT, 4), (IDLE), (IDLE) Elementos de escrita também podem ser operandos de quádruplas São úteis contadores de argumentos para os comandos ler e escrever Isso será feito nas produções dos não-terminais ListVar e ListEscr

O atributo dos não-terminais ListVar e ListEscr deve ser o número de argumentos de suas listas O atributo dos não-terminais ListVar e ListEscr deve ser o número de argumentos de suas listas Deve-se acrescentar mais um campo na declaração %union: Deve-se acrescentar mais um campo na declaração %union: %union { int nsubscr, nargs; } Declaração do atributo dos não terminais ListVar e ListEscr: Declaração do atributo dos não terminais ListVar e ListEscr: %type ListVar ListEscr

Tal como uma expressão, o não terminal ElemEscr deve ter um operando de quádrupla Tal como uma expressão, o não terminal ElemEscr deve ter um operando de quádrupla Então deve haver uma declaração %type para ele: Então deve haver uma declaração %type para ele: %type Expressao ExprAux1 ExprAux2 ExprAux3 ExprAux4 Termo Fator ElemEscr

Programação para o não-terminal ListVar que é usado na produção do não-terminal CmdLer: Programação para o não-terminal ListVar que é usado na produção do não-terminal CmdLer: ListVar: Variavel { $$ = 1; GeraQuadrupla (PARAM, $1.opnd, opndidle, opndidle); } | ListVar VIRG { } Variavel { $$ = $1 + 1; GeraQuadrupla (PARAM, $4.opnd, opndidle, opndidle); }; $$ é o contador de argumentos de um comando ler

Programação para o não-terminal CmdLer: Programação para o não-terminal CmdLer: CmdLer: LER ABPAR { } ListVar{ opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPREAD, opnd1, opndidle, opndidle); } FPAR PVIRG {printf (") ;\n");} ;

Programação para o não-terminal ElemEscr: Programação para o não-terminal ElemEscr: ElemEscr: CADEIA { printf ("%s ", $1); $$.opnd.tipo = CADOPND; $$.opnd.atr.valcad = malloc (strlen($1) + 1); strcpy ($$.opnd.atr.valcad, $1); } | Expressao/* default: $$ = $1 */ ; Obs.: $$.tipo da 1ª produção do não-terminal ElemEscr não é usado Portanto não é calculado

Programação para o não-terminal ListEscr: Programação para o não-terminal ListEscr: ListEscr: ElemEscr { $$ = 1; GeraQuadrupla (PARAM, $1.opnd, opndidle, opndidle); } | ListEscr VIRG {printf (", ");} ElemEscr { $$ = $1 + 1; GeraQuadrupla (PARAM, $4.opnd, opndidle, opndidle); }; $$ é o contador de argumentos de um comando escrever

Programação para o não-terminal CmdEscrever: Programação para o não-terminal CmdEscrever: CmdEscrever: ESCREVER ABPAR { } ListEscr { opnd1.tipo = INTOPND; opnd1.atr.valint = $4; GeraQuadrupla (OPWRITE, opnd1, opndidle, opndidle); } FPAR PVIRG {printf (") ;\n");} ; No arquivo inter dat, tirar o comentário dos comandos ler e escrever e rodar

Exercício 4.8: Inserir quádruplas para indexação Sejam as seguintes declarações e comandos: Sejam as seguintes declarações e comandos: int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); Acesso a um elemento genérico A[i,j]: Acesso a um elemento genérico A[i,j]: Uma vez conhecido o endereço inicial da matriz A, é necessário localizar o elemento A[i,j] Uma vez conhecido o endereço inicial da matriz A, é necessário localizar o elemento A[i,j] Seja a seguir o mapa de A[6,5] na memória: Seja a seguir o mapa de A[6,5] na memória:

Seja m o número de linhas e n o número de colunas da matriz A Seja m o número de linhas e n o número de colunas da matriz A O endereço do elemento A[i,j] é dado pela fórmula: O endereço do elemento A[i,j] é dado pela fórmula: Ender (A) + i * n + j Para m := 6, n := 5, o endereço de A[4,3] é Para m := 6, n := 5, o endereço de A[4,3] é Ender (A) + 23

No programa, cada índice pode ser uma expressão inteira No programa, cada índice pode ser uma expressão inteira Calcula-se o valor de cada índice, empilhando-o numa pilha de índices Calcula-se o valor de cada índice, empilhando-o numa pilha de índices Isso pode ser feito pela execução de uma quádrupla de operador IND: Isso pode ser feito pela execução de uma quádrupla de operador IND: IND, i, ----, ---- IND, i, ----, ---- IND, j, ----, ---- IND, j, ----, ----

Calcula-se o endereço de A[i,j], usando uma quádrupla de operador INDEX: Calcula-se o endereço de A[i,j], usando uma quádrupla de operador INDEX: INDEX, A, 2, temp1 Sua execução consiste em: Sua execução consiste em: Pegar as dimensões e o endereço de A na tabela de símbolos Pegar as dimensões e o endereço de A na tabela de símbolos Desempilhar dois índices Desempilhar dois índices Calcular o endereço, colocando-o na variável temp1 Calcular o endereço, colocando-o na variável temp1 A variável temp1 é portanto um ponteiro A variável temp1 é portanto um ponteiro

Quando o elemento A[i,j] está numa expressão, necessita-se do conteúdo do local apontado por temp1 Quando o elemento A[i,j] está numa expressão, necessita-se do conteúdo do local apontado por temp1 Para isso, pode-se usar uma quádrupla de operador CONTAPONT: Para isso, pode-se usar uma quádrupla de operador CONTAPONT: CONTAPONT, temp1, ----, temp2 int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); temp2 recebe o conteúdo do local apontado por temp1

Quando o elemento A[i,j] vai receber uma atribuição, o local apontado por temp1 é que vai receber isso Quando o elemento A[i,j] vai receber uma atribuição, o local apontado por temp1 é que vai receber isso Então, pode-se usar uma quádrupla de operador ATRIBPONT: Então, pode-se usar uma quádrupla de operador ATRIBPONT: ATRIBPONT, tempexpr, ----, temp1 int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); O local apontado por temp1 recebe o conteúdo de tempexpr

Quando o elemento A[i,j] vai receber um valor lido: Quando o elemento A[i,j] vai receber um valor lido: O valor lido é guardado numa temporária O valor lido é guardado numa temporária O local apontado por temp1 recebe o valor dessa temporária O local apontado por temp1 recebe o valor dessa temporária É conveniente colocar a leitura do elemento de uma variável indexada numa quádrupla separada: Duas quádruplas OPREAD int i, j, k, A[6,5]; i := 4; j := 3; k := A[i,j-2] + 7; A[10-i,2*j+3] := i + j * k; ler (i, j, A[i+j,2*i-j]); PARAM, tempread, ----, ---- OPREAD, 1, ----, ---- ATRIBPONT, tempread, ----, temp1

Exemplo: seja o seguinte programa: Exemplo: seja o seguinte programa: programa teste; var int i, j, k, A[10,10]; { i := 7; j := 5; k := A[i-3,j+2] + 5; A[10-i,9-j] := i + j * k; ler (i, j, A[2,3], k); ler (A[1,2]); } A seguir suas possíveis quádruplas

programa teste; var int i, j, k, A[10,10]; 1) OPENMOD, (MODULO, teste), (IDLE), (IDLE) { i := 7; j := 5; 2) ATRIB, (INT, 7), (IDLE), (VAR, i) 3) ATRIB, (INT, 5), (IDLE), (VAR, j)

k := A[i-3,j+2] + 5; 4) MENOS, (VAR, i), (INT, 3), (VAR, ##1) 5) IND, (VAR, ##1), (IDLE), (IDLE) 6) MAIS, (VAR, j), (INT, 2), (VAR, ##2) 7) IND, (VAR, ##2), (IDLE), (IDLE) 8) INDEX, (VAR, A), (INT, 2), (VAR, ##3) 9) CONTAPONT, (VAR, ##3), (IDLE), (VAR, ##4) 10) MAIS, (VAR, ##4), (INT, 5), (VAR, ##5) 11) ATRIB, (VAR, ##5), (IDLE), (VAR, k)

A[10-i,9-j] := i + j * k; 12) MENOS, (INT, 10), (VAR, i), (VAR, ##6) 13) IND, (VAR, ##6), (IDLE), (IDLE) 14) MENOS, (INT, 9), (VAR, j), (VAR, ##7) 15) IND, (VAR, ##7), (IDLE), (IDLE) 16) INDEX, (VAR, A), (INT, 2), (VAR, ##8) 17) MULT, (VAR, j), (VAR, k), (VAR, ##9) 18) MAIS, (VAR, i), (VAR, ##9), (VAR, ##10) 19) ATRIBPONT, (VAR, ##10), (IDLE), (VAR, ##8)

ler (i, j, A[2,3], k); 20) PARAM, (VAR, i), (IDLE), (IDLE) 21) PARAM, (VAR, j), (IDLE), (IDLE) 22) READ, (INT, 2), (IDLE), (IDLE) 23) IND, (INT, 2), (IDLE), (IDLE) 24) IND, (INT, 3), (IDLE), (IDLE) 25) INDEX, (VAR, A), (INT, 2), (VAR, ##11) 26) PARAM, (VAR, ##12), (IDLE), (IDLE) 27) READ, (INT, 1), (IDLE), (IDLE) 28) ATRIBPONT, (VAR, ##12), (IDLE), (VAR, ##11) 29) PARAM, (VAR, k), (IDLE), (IDLE) 30) READ, (INT, 1), (IDLE), (IDLE)

ler (A[1,2]); } 31) IND, (INT, 1), (IDLE), (IDLE) 32) IND, (INT, 2), (IDLE), (IDLE) 33) INDEX, (VAR, A), (INT, 2), (VAR, ##13) 34) PARAM, (VAR, ##14), (IDLE), (IDLE) 35) READ, (INT, 1), (IDLE), (IDLE) 36) ATRIBPONT, (VAR, ##14), (IDLE), (VAR, ##13)