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

Loading in 2 Seconds...

play fullscreen
1 / 78

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


  • 67 Views
  • Uploaded on

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

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 - 2012' - yuma


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 2012

CES-41 COMPILADORESAulas Práticas - 2012

Capítulo IV

Código Intermediário no Yacc

slide2
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
slide3
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;}

}

}

}

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

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 ##global destinam-se a:

alocar as variáveis globais

chamar o módulo principal

e encerrar tudo no final

slide12

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

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

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

slide15

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
slide16

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

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

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

#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

slide20
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

slide21
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

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

slide23

codintermed

modname

modtip

  • Função InicCodIntermed:

void InicCodIntermed () {

codintermed = malloc (sizeof (celmodhead));

modcorrente = codintermed;

modcorrente->listquad = NULL;

modcorrente->prox = NULL;

}

prox

listquad

modcorrente

slide24

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

slide25
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

slide26

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

slide27
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

slide28
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

slide29
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

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

}

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

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

slide34
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

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

slide36
É 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
slide37
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;

}

}

;

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

}

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

}

slide40
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

slide41

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

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

slide43
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

slide44
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
slide45
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;

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

;

No arquivo inter022012.dat, tirar o comentário do se sem senaoe rodar

slide47
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

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

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

}

}

;

slide50
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

slide51
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

slide52
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

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

Comando

$5

NOP

JUMP

NOP

JF

-----

-----

-----

##n

-----

-----

-----

-----

-----

-----

-----

-----

ROT

##n

ROT

-----

Comando

$9

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

slide54

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

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

slide56
CmdEnquanto : ENQUANTO ABPAR Expressao FPAR Comando

;

Expressao

?

Comando

NOP

JUMP

JF

NOP

-----

##n

-----

-----

-----

-----

-----

-----

-----

-----

-----

-----

ROT

-----

##n

ROT

slide57
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 inter022012.y

slide58
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

slide59
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

slide60
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

slide61
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

slide62
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");}

;

slide63
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

slide64
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

slide65
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 inter022012.dat, tirar o comentário dos comandos ler e escrever e rodar

slide66
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:
slide67
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

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

slide69
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
slide70
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]);

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

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

slide73
Exemplo: seja o seguinte programa:

teste {

locais:

int i, j, k, A[10][10];

comandos:

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

slide74
teste {

locais:

int i, j, k, A[10][10];

1) OPENMOD, (IDLE), (IDLE), (IDLE)

comandos:

i <- 7; j <- 5;

2) ATRIB, (INT, 7), (IDLE), (VAR, i)

3) ATRIB, (INT, 5), (IDLE), (VAR, j)

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

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

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

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