ces 41 compiladores aulas pr ticas 2013 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
CES-41 COMPILADORES Aulas Práticas - 2013 PowerPoint Presentation
Download Presentation
CES-41 COMPILADORES Aulas Práticas - 2013

Loading in 2 Seconds...

play fullscreen
1 / 79

CES-41 COMPILADORES Aulas Práticas - 2013 - PowerPoint PPT Presentation


  • 91 Views
  • Uploaded on

CES-41 COMPILADORES Aulas Práticas - 2013. 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: Comandos de atribuição, compostos, entrada e saída, condicionais, enquanto, variáveis escalares e indexadas

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'CES-41 COMPILADORES Aulas Práticas - 2013' - irish


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
ces 41 compiladores aulas pr ticas 2013

CES-41 COMPILADORESAulas Práticas - 2013

Capítulo IV

Código Intermediário no Yacc

slide2
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
  • Seja essa linguagem chamada de Sub-Set2 2013
  • Seja o programa a seguir, escrito em Sub-Set2 2013, para encontrar números primos
slide3
programa primos;

var logic achou; int n, div, resto, cont, num;

{

ler (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");

}

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

slide5

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)

slide6

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)

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

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

slide9
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

slide10

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

slide11

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

slide13

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

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

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

slide16

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
slide17

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

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

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

#define IDPROG 1

#define IDVAR 2

#define IDFUNC 3

#define IDPROC 4

  • 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

slide21
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

slide22
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

slide23
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);

slide24

codintermed

modname

modtip

  • Função InicCodIntermed:

void InicCodIntermed () {

codintermed = malloc (sizeof (celmodhead));

modcorrente = codintermed;

modcorrente->listquad = NULL;

modcorrente->prox = NULL;

}

prox

listquad

modcorrente

slide25

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

slide26
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

slide27

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

slide28
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

slide29
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

slide30
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

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

}

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

slide33
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.
slide34
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;

} PROGRAMA ID PVIRG { printf ("programa %s ;\n", $3);

simb = InsereSimb ($3, IDPROG, NOTVAR);

InicCodIntermMod (simb);

} DeclsCmdComp {

VerificaInicRef (); ImprimeTabSimb ();

ImprimeQuadruplas ();

}

;

Acrescentar ao arquivo inter012013.y o código em destaque

Rodar com o arquivo inter012013.dat

slide35
Exercício 4.2: Inserir a quádrupla OPENMOD
  • Ainda na produção do não-terminalProg:

Prog: {- - - - -} PROGRAMA ID PVIRG {

- - - - -

InicCodIntermMod (simb);

opnd1.tipo = MODOPND;

opnd1.atr.modulo = modcorrente;

GeraQuadrupla (OPENMOD, opnd1, opndidle, opndidle);

} DeclsCmdComp {

- - - - -

}

;

Acrescentar ao arquivo inter012013. y o código em destaque

Rodar com o arquivo inter012013. dat

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

slide37
É 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
slide38
Na 1ª produção do não-terminalVariavel (sem subscritos), calcula-se seu operando:

Variavel: ID {- - - - -

$$.simb = simb;

if ($$.simb != NULL) {

if (- - - - -) Esperado ("Subscrito\(s)");

$$.opnd.tipo = VAROPND;

$$.opnd.atr.simb = $$.simb;

}

}

;

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

}

slide40
Fator: CTCARAC { - - - - - $$.tipo = CHAR;

$$.opnd.tipo = CHAROPND;

$$.opnd.atr.valchar = $1;

}

| VERDADE { - - - - - $$.tipo = LOGICAL;

$$.opnd.tipo = LOGICOPND;

$$.opnd.atr.vallogic = 1;

}

| FALSO { - - - - - $$.tipo = LOGICAL;

$$.opnd.tipo = LOGICOPND;

$$.opnd.atr.vallogic = 0;

}

| ABPAR {- - - - -} Expressao FPAR {

- - - - - $$.tipo = $3.tipo; $$.opnd = $3.opnd;

}

slide41
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 inter012013. dat

slide42

Rodar com o arquivo inter012013. dat

  • Produções do não-terminalTermo:

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

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

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

slide44
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 inter022013.y, inter022013.l e inter022013.dat

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

slide47
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 inter022013.dat, tirar o comentário do se sem senao e rodar

slide48
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

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

slide50
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);

}

}

;

slide51
CmdSenao :

| SENAO {

- - - - -

opndaux.tipo = ROTOPND;

$<quad>$ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux);

} Comando {

$<quad>2->result.atr.rotulo =

GeraQuadrupla (NOP, opndidle, opndidle, opndidle);

}

;

No arquivo inter022013.dat, tirar o comentário do se com senao e rodar

slide52
CmdSe : SE ABPAR {- - - - -} Expressao { - - - - -

opndaux.tipo = ROTOPND;

$<quad>$ = GeraQuadrupla (OPJF, $4.opnd, opndidle, opndaux);

} FPAR {- - - - -} Comando {

$<quad>$ = quadcorrente;

$<quad>5->result.atr.rotulo =

GeraQuadrupla (NOP, opndidle, opndidle, opndidle);

} CmdSenao{- - - - -}

;

$5

Expressao

$9

JF

-----

NOP

-----

-----

##n

-----

-----

-----

##n

ROT

-----

Comando

slide53
CmdSenao : | SENAO { - - - - -

opndaux.tipo = ROTOPND;

$<quad>$ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux);

} Comando {

$<quad>2->result.atr.rotulo =

GeraQuadrupla (NOP, opndidle, opndidle, opndidle);

}

;

Expressao

?

$2

$5

NOP

JUMP

JF

-----

-----

##n

-----

-----

-----

-----

-----

-----

-----

ROT

##n

ROT

As quádruplas NOP e JUMP foram geradas em ordem trocada

Comando

$9

slide54
CmdSenao : | SENAO { - - - - -

opndaux.tipo = ROTOPND;

$<quad>$ = GeraQuadrupla (OPJUMP, opndidle, opndidle, opndaux);

} Comando {

$<quad>2->result.atr.rotulo =

GeraQuadrupla (NOP, opndidle, opndidle, opndidle);

}

;

Expressao

?

$2

Comando

$5

NOP

JUMP

NOP

JF

-----

-----

-----

##n

-----

-----

-----

-----

-----

-----

-----

-----

ROT

##n

ROT

-----

Comando

$9

É preciso inverter a ordem das quádruplas NOP e JUMP

slide55

Comando

$9

CmdSe : SE ABPAR {- - - - -} Expressao {- - - - -} FPAR {- - - - -} Comando

{ - - - - -} 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);

}

}

;

NOP

NOP

JUMP

-----

-----

-----

-----

-----

-----

ROT

-----

-----

quadaux

Comando

Se a quádrupla seguinte à $9 for a quádrupla corrente, o se não tem senao – não é preciso fazer troca

slide56
Exercício 4.6: Inserir quádruplas para o comando enquanto
  • Exemplo: as quádruplas para o comando

enquanto (i < j) i := j + h;

i := 0;

podem ser:

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)

9) ATRIB, (INT, 0), (IDLE), (VAR, i)

slide57
CmdEnquanto : ENQUANTO ABPAR Expressao FPAR Comando

;

Expressao

?

Comando

NOP

JUMP

JF

NOP

-----

##n

-----

-----

-----

-----

-----

-----

-----

-----

-----

-----

ROT

-----

##n

ROT

slide58
Exercício 4.7: Inserir quádruplas para comandos ler e escrever
  • 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 inter022013.y

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

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

Elementos de escrita também podem ser operandos de quádruplas

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

%union {

- - - - -

intnsubscr, nargs;

- - - - -

}

  • Declaração do atributo dos não terminais ListVar e ListEscr:

%type <nargs> ListVarListEscr

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

%type <infoexpr> Expressao ExprAux1 ExprAux2

ExprAux3 ExprAux4 Termo Fator ElemEscr

slide62
Programação para o não-terminalListVar que é usado na produção do não-terminalCmdLer:

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

slide63
Programação para o não-terminalCmdLer:

CmdLer : LER ABPAR { - - - - -}

ListVar

{

opnd1.tipo = INTOPND;

opnd1.atr.valint = $4;

GeraQuadrupla (OPREAD, opnd1, opndidle, opndidle);

}

FPAR PVIRG {printf (") ;\n");}

;

slide64
Programação para o não-terminalElemEscr:

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-terminalElemEscr não é usado

Portanto não é calculado

slide65
Programação para o não-terminalListEscr:

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

slide66
Programação para o não-terminalCmdEscrever:

CmdEscrever : ESCREVER ABPAR {- - - - -} ListEscr

{

opnd1.tipo = INTOPND;

opnd1.atr.valint = $4;

GeraQuadrupla (OPWRITE, opnd1, opndidle, opndidle);

}

FPAR PVIRG {printf (") ;\n");}

;

No arquivo inter022013.dat, tirar o comentário dos comandos ler e escrever e rodar

slide67
Exercício 4.8: Inserir quádruplas para indexação
  • 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]:
    • 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:
slide68
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:

Ender (A) + i * n + j

  • Para m := 6, n := 5, o endereço de A[4,3] é

Ender (A) + 23

slide69
No programa, cada índice pode ser uma expressão inteira
  • 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:

IND, i , ---- , ----

IND, j , ---- , ----

slide70
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:
    • Pegar as dimensões e o endereço de A na tabela de símbolos
    • Desempilhar dois índices
    • Calcular o endereço, colocando-o na variável temp1
  • A variável temp1 é portanto um ponteiro
slide71
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:

CONTAPONT , temp1 , ---- , temp2

temp2 recebe o conteúdo do local apontado por 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]);

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

ATRIBPONT , tempexpr , ---- , temp1

O local apontado por temp1 recebe o conteúdo de tempexpr

  • 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]);

slide73
Quando o elemento A[i,j] vai receber um valor lido:
      • O valor lido é guardado numa temporária
      • O local apontado por temp1 recebe o valor dessa temporária

PARAM , tempread , ---- , ----

OPREAD , 1 , ---- , ----

ATRIBPONT , tempread , ---- , temp1

É 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]);

slide74
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

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

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

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

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

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