• Nenhum resultado encontrado

Como construir um compilador utilizando ferramentas Java

N/A
N/A
Protected

Academic year: 2021

Share "Como construir um compilador utilizando ferramentas Java"

Copied!
153
0
0

Texto

(1)

Como construir um compilador utilizando

ferramentas Java

Aula 12 – Análise Semântica

Prof. M ´arcio Delamaro

[email protected]

(2)

O que é

Preocupa com o significado de cada construção.

(3)

O que é

Preocupa com o significado de cada construção.

Depende da linguagem.

(4)

O que é

Preocupa com o significado de cada construção.

Depende da linguagem.

Passeio(s) na árvore sintática

(5)

O que é

Preocupa com o significado de cada construção.

Depende da linguagem.

Passeio(s) na árvore sintática

Realizada em diversas fases, cada um relativa a

diferentes aspectos.

(6)

Por que em fases?

class A {

B varB;

}

class B {

}

(1)ListNode (2)ClassDeclNode (8)ListNode Token: A (3)ClassBodyNode (9)ClassDeclNode

(4)ListNode Token: B (10)ClassBodyNode

(5)VarDeclNode Token: B (6)ListNode

(7)VarNode Token: varB

(7)

Por que em fases?

a. visita ao nó 1

b. visita ao nó 2, insere a

classe

A

c. visita ao nó 3

d. visita ao nó 4

e. visita ao nó 5 e

veri-fica declaração

f. visita ao nó 8

g. visita ao nó 9 e insere

classe

B

h. visita ao nó 10

(1)ListNode (2)ClassDeclNode (8)ListNode Token: A (3)ClassBodyNode (9)ClassDeclNode

(4)ListNode Token: B (10)ClassBodyNode (5)VarDeclNode

Token: B (6)ListNode (7)VarNode Token: varB

(8)

Por que em fases?

Fase 1:

a. visita ao nó 1

b. visita ao nó 2, insere a

classe

A

c. visita ao nó 3

d. visita ao nó 4

e. visita ao nó 5

f. visita ao nó 8

g. visita ao nó 9 e inserre

classe

B

h. visita ao nó 10.

(1)ListNode (2)ClassDeclNode (8)ListNode Token: A (3)ClassBodyNode (9)ClassDeclNode

(4)ListNode Token: B (10)ClassBodyNode (5)VarDeclNode

Token: B (6)ListNode (7)VarNode Token: varB

(9)

Por que em fases?

Fase 2:

a. visita ao nó 1

b. visita ao nó 2

c. visita ao nó 3

d. visita ao nó 4

e. visita ao nó 5 e

veri-fica declaração

f. visita ao nó 8

g. visita ao nó 9

h. visita ao nó 10

(1)ListNode (2)ClassDeclNode (8)ListNode Token: A (3)ClassBodyNode (9)ClassDeclNode

(4)ListNode Token: B (10)ClassBodyNode (5)VarDeclNode

Token: B (6)ListNode (7)VarNode Token: varB

(10)

analisador semântico: parte 1

Analisa a declaração de classes.

(11)

analisador semântico: parte 1

Analisa a declaração de classes.

Constrói tabela de símbolos.

(12)

analisador semântico: parte 1

Analisa a declaração de classes.

Constrói tabela de símbolos.

Ao encontrar um nó

ClassDeclNode

, o analisador

semântico deve incluir a classe correspondente na

tabela de símbolos.

(13)

analisador semântico: parte 1

Analisa a declaração de classes.

Constrói tabela de símbolos.

Ao encontrar um nó

ClassDeclNode

, o analisador

semântico deve incluir a classe correspondente na

tabela de símbolos.

A árvore sintática não precisa ser completamente

percorrida, somente os seus níveis mais altos.

(14)

analisador semântico: parte 1

Analisa a declaração de classes.

Constrói tabela de símbolos.

Ao encontrar um nó

ClassDeclNode

, o analisador

semântico deve incluir a classe correspondente na

tabela de símbolos.

A árvore sintática não precisa ser completamente

percorrida, somente os seus níveis mais altos.

Tratamento de classes aninhadas.

(15)

Tratamento das classes

ListNode ClassDeclNode class1 ListNode ClassDeclNode ClassBodyNode ClassBodyNode class2 Symtable class1 class2 class class1 { } class class2 { }

(16)

Tratamento das classes aninhadas

ListNode ClassDeclNode class1 ListNode ClassDeclNode ListNode ClassDeclNode aninhada ListNode ClassDeclNode ClassBodyNode ClassBodyNode class2 ClassBodyNode ClassBodyNode Symtable class1 class2 aninhada aninhada aninhada Symtable Symtable class class1 { class aninhada{ } } class class2 { class aninhada { } }

(17)

Erros semânticos...

Nessa fase da análise semântica, somente um tipo de erro

semântico pode ser detectado: quando uma classe que já

foi definida num determinado escopo é redefinida.

class class1

{

class class1 {

}

}

(18)

Implementação:

main

if ( parser.token_source.foundLexError() + parser.contParseError == 0) {

if (print_tree) // exibir a ´arvore {

PrintTree prt = new PrintTree(); prt.printRoot(root);

}

ClassCheck tc = new ClassCheck(); try {

tc.ClassCheckRoot(root);

System.out.println("0 Semantic error found"); } catch (SemanticException e) { System.out.println(e.getMessage()); } }

(19)

ClassCheck

package semanalysis; import symtable.*;

import syntacticTree.*; public class ClassCheck {

Symtable Maintable; // tabela de mais alto n´ıvel

protected Symtable Curtable; // apontador para a tb corrente int foundSemanticError;

public ClassCheck() {

EntrySimple k;

foundSemanticError = 0;

Maintable = new Symtable(); // cria tabela principal k = new EntrySimple("int"); // insere tipos b´asicos Maintable.add(k);

k = new EntrySimple("string"); Maintable.add(k);

}

(20)

Tratando da raiz

public void ClassCheckRoot(ListNode x) throws SemanticException {

Curtable = Maintable; // tabela corrente = principal // chama an´alise para raiz da ´arvore

ClassCheckClassDeclListNode(x); // se houve erro, lanc¸a excec¸˜ao if (foundSemanticError != 0)

throw new SemanticException(foundSemanticError +

" Semantic Errors found (phase 1)"); }

(21)

Tratando lista de classes

public void ClassCheckClassDeclListNode(ListNode x) {

if (x == null) return; try {

ClassCheckClassDeclNode( (ClassDeclNode) x.node); }

catch (SemanticException e)

{ // se um erro ocorreu na an´alise da classe,

// d´a a mensagem, mas faz a an´alise para pr´oxima classe System.out.println(e.getMessage());

foundSemanticError++; }

ClassCheckClassDeclListNode(x.next); }

(22)

Tratando declaração de uma classe

public void ClassCheckClassDeclNode(ClassDeclNode x) throws SemanticException {

// salva apontador p/ tabela corrente Symtable temphold = Curtable;

EntryClass nc;

if (x == null) return;

// procura classe na tabela

nc = (EntryClass) Curtable.classFindUp(x.name.image); if (nc != null) // j´a declarada, ERRO

{

throw new SemanticException(x.name,

"Class "+ x.name.image + " already declared"); }

// inclui classe na tabela corrente

Curtable.add(nc = new EntryClass(x.name.image, Curtable)); Curtable = nc.nested; // tabela corrente = tabela da classe ClassCheckClassBodyNode(x.body);

Curtable = temphold; // recupera apontador p/ tabela corrente }

(23)

Errata

O erro reportado no slide anterior deveria ser verificado

também na fase 2 apenas. No exemplo abaixo, B ainda não

estaria na tabela de símbolos, mas o erro deveria ser

apontado. Na fase i verifica-se a partir da tabela corrente.

Na fase 2 a partir da tabela do nível anterior.

class A {

class B{}

}

class B {}

(24)

Como fica a tabela de símbolos

int 1 0 string int 1 0 string int 1 0 string Maintable Curtable A Próx. livre Maintable Curtable Próx. livre A Maintable Próx. livre Curtable (a) (b) (c) 2 2 2 3

(25)

Regras de escopo

Verifica-se se no escopo corrente já existe uma classe

com o mesmo nome da classe sendo declarada.

(26)

Regras de escopo

Verifica-se se no escopo corrente já existe uma classe

com o mesmo nome da classe sendo declarada.

Essa procura é feita por meio do método

Symtable.classFindUp

(27)

Regras de escopo

Verifica-se se no escopo corrente já existe uma classe

com o mesmo nome da classe sendo declarada.

Essa procura é feita por meio do método

Symtable.classFindUp

Procura a classe na tabela corrente.

(28)

Regras de escopo

Verifica-se se no escopo corrente já existe uma classe

com o mesmo nome da classe sendo declarada.

Essa procura é feita por meio do método

Symtable.classFindUp

Procura a classe na tabela corrente.

Caso não tenha encontrado, chama recursivamente a

pesquisa utilizando a tabela de nível superior.

(29)

classFindUp

public EntryTable classFindUp(String x) {

EntryTable p = top;

// para cada elemento da tabela corrente while (p != null)

{

// verifica se ´e uma entrada de classe ou tipo simples // e ent˜ao compara o nome

if ( ((p instanceof EntryClass) || (p instanceof EntrySimple)) && p.name.equals(x))

return p;

p = p.next; // pr´oxima entrada }

if (levelup == null) // se n˜ao achou e ´e o n´ıvel mais externo return null; // retorna null

// procura no n´ıvel mais externo

return levelup.mytable.classFindUp(x); }

(30)

Tratando o corpo da classe

Só interessa o corpo da classe se dentro dele houver

declaração de classe aninhada.

(31)

Tratando o corpo da classe

Só interessa o corpo da classe se dentro dele houver

declaração de classe aninhada.

Então somente a lista de classes é que interessa.

(32)

Tratando o corpo da classe

Só interessa o corpo da classe se dentro dele houver

declaração de classe aninhada.

Então somente a lista de classes é que interessa.

Dentro da declaração de variáveis, métodos ou

construtores, não existem declarações de classes.

(33)

Tratando o corpo da classe

public void ClassCheckClassBodyNode(

ClassBodyNode x)

{

if (x == null) return;

ClassCheckClassDeclListNode(x.clist);

}

(34)

Exercícios

Diga como ficaria a tabela de símbolos após a primeira fase da

analisador semântico ser concluída. Mostre também qual o

programa fonte que gerou cada árvore.

(35)

Exercícios

(36)

Exercícios

(37)

Exercícios

(38)

Exercícios

(39)

Exercícios

(40)

Análise semântica: parte 2

Nova classe

VarCheck

(41)

Análise semântica: parte 2

Nova classe

VarCheck

Usa a estrutura montada na parte 1

(42)

Análise semântica: parte 2

Nova classe

VarCheck

Usa a estrutura montada na parte 1

Faz outras verificações em relação a classes e

declaraçoes de variáveis.

(43)

Análise semântica: parte 2

Nova classe

VarCheck

Usa a estrutura montada na parte 1

Faz outras verificações em relação a classes e

declaraçoes de variáveis.

Não requer a análise de toda a árvore sintática.

(44)

Método

main

if ( parser.token_source.foundLexError() + parser.contParseError == 0) {

if (print_tree) // exibir a ´arvore {

PrintTree prt = new PrintTree();

prt.printRoot(root); // chama m´etodo para imprimir ´arvore }

VarCheck tc = new VarCheck(); try {

tc.VarCheckRoot(root);

System.out.println("0 Semantic Errors found"); } catch (SemanticException e) { System.out.println(e.getMessage()); } }

(45)

VarCheck

package semanalysis; import symtable.*;

import syntacticTree.*;

public class VarCheck extends ClassCheck { public VarCheck()

{

super(); }

public void VarCheckRoot(ListNode x) throws SemanticException {

ClassCheckRoot(x); // faz an´alise das classes VarCheckClassDeclListNode(x);

if (foundSemanticError != 0) // se houve erro, lanc¸a excec¸˜ao throw new SemanticException(foundSemanticError +

" Semantic Errors found (phase 2)"); }

(46)

VarCheck

: observações

É subclasse de

ClassCheck

(47)

VarCheck

: observações

É subclasse de

ClassCheck

Ou seja, ao criar um objeto dessa classe, são herdados

os métodos vistos na parte 1 da analisador semântico.

(48)

VarCheck

: observações

É subclasse de

ClassCheck

Ou seja, ao criar um objeto dessa classe, são herdados

os métodos vistos na parte 1 da analisador semântico.

Antes de iniciar a análise, é chamado o método

ClassCheckRoot(x)

que realiza a primeira parte da

análise.

(49)

Análise de uma lista de classes

public void VarCheckClassDeclListNode(ListNode x) {

if (x == null) return; try {

VarCheckClassDeclNode( (ClassDeclNode) x.node); }

catch (SemanticException e)

{ // se um erro ocorreu na an´alise da classe,

// d´a a mensagem, mas faz a an´alise para pr´oxima classe System.out.println(e.getMessage());

foundSemanticError++; }

VarCheckClassDeclListNode(x.next); }

(50)

Análise de uma declaração de classe

Se uma superclasse foi definida, verifica se a

superclasse existe.

(51)

Análise de uma declaração de classe

Se uma superclasse foi definida, verifica se a

superclasse existe.

Se existe, atualiza a tabela de símbolos.

(52)

Análise de uma declaração de classe

Se uma superclasse foi definida, verifica se a

superclasse existe.

Se existe, atualiza a tabela de símbolos.

Não verifica (ainda) circularidade

(53)

Análise de uma declaração de classe

Se uma superclasse foi definida, verifica se a

superclasse existe.

Se existe, atualiza a tabela de símbolos.

Não verifica (ainda) circularidade

class A extends B

class B extends C

class C extends A

(54)

Análise de uma declaração de classe

public void VarCheckClassDeclNode(ClassDeclNode x) throws SemanticException {

Symtable temphold = Curtable; // salva tabela corrente EntryClass c = null;

EntryClass nc;

if (x == null) return;

if (x.supername != null) { // verifica se superclasse foi definida c = (EntryClass) Curtable.classFindUp(x.supername.image);

if (c == null) { // Se n˜ao achou superclasse, ERRO

throw new SemanticException(x.position, "Superclass "+ x.supername.image + " not found");

} }

nc = (EntryClass) Curtable.classFindUp(x.name.image);

nc.parent = c; // coloca na tabela o apontador p/ superclasse Curtable = nc.nested; // tabela corrente = tabela da classe

VarCheckClassBodyNode(x.body);

Curtable = temphold; // recupera tabela corrente }

(55)

Análise de uma declaração de classe

// procura classe na tabela

nc = (EntryClass) Curtable.classFindUp(x.name.image); // procura nos niveis mais externos

if ( Curtable.levelup != null ) {

Symtable oneUp = Curtable.levelup.mytable;

EntryClass nc1 = (EntryClass) oneUp.classFindUp(x.name.image); if (nc1 != null) { // j´a declarada, ERRO

throw new SemanticException(x.name,

"Class " + x.name.image + " already declared"); }

}

nc.parent = c; // coloca na tabela o apontador p/ superclasse Curtable = nc.nested; // tabela corrente = tabela da classe VarCheckClassBodyNode(x.body);

Curtable = temphold; // recupera tabela corrente }

(56)

Outras declarações

Dentro de uma classe, existem declarações

Classes aninhadas

Variáveis

Construtores

Métodos

(57)

Trata o corpo de uma classe

public void VarCheckClassBodyNode(ClassBodyNode x) {

if (x == null) return;

VarCheckClassDeclListNode(x.clist); VarCheckVarDeclListNode(x.vlist);

VarCheckConstructDeclListNode(x.ctlist);

// se n˜ao existe constructor(), insere um falso

if ( Curtable.methodFindInclass("constructor", null) == null) { Curtable.add(new EntryMethod("constructor", Curtable.levelup, true)); } VarCheckMethodDeclListNode(x.mlist); }

Obs: construtor falso.

(58)

Declaração de variáveis

MyClass x, y;

(59)

Declaração de variáveis

MyClass x, y;

Verificar se

MyClass

existe na T.S.

(60)

Declaração de variáveis

MyClass x, y;

Verificar se

MyClass

existe na T.S.

Funciona para

int

ou

string

?

(61)

Declaração de variáveis

MyClass x, y;

Verificar se

MyClass

existe na T.S.

Funciona para

int

ou

string

?

Cada variável na declaração é inserida na T.S. corrente.

(62)

Declaração de variáveis

MyClass x, y;

Verificar se

MyClass

existe na T.S.

Funciona para

int

ou

string

?

Cada variável na declaração é inserida na T.S. corrente.

Declarações repetidas?

(63)

Declaração de variáveis

MyClass x, y;

Verificar se

MyClass

existe na T.S.

Funciona para

int

ou

string

?

Cada variável na declaração é inserida na T.S. corrente.

Declarações repetidas?

Não são verificadas pois não é possível ainda verificar

se na superclasse existe uma variável com o mesmo

nome.

(64)

Declaração de variáveis

public void VarCheckVarDeclNode(VarDeclNode x) throws SemanticException { EntryTable c;

ListNode p;

if (x == null) return;

// acha entrada do tipo da vari´avel

c = Curtable.classFindUp(x.position.image); // se n˜ao achou, ERRO

if (c == null)

throw new SemanticException(x.position, "Class "+ x.position.image + " not found");

// para cada vari´avel da declarac˜ao, cria uma entrada na tabela for (p = x.vars; p != null; p = p.next) {

VarNode q = (VarNode) p.node;

Curtable.add(new EntryVar(q.position.image, c, q.dim)); }

}

(65)

Declaração de construtor

Verifica o tipo de cada parâmetro.

(66)

Declaração de construtor

Verifica o tipo de cada parâmetro.

Cria uma

Entryrec

com os tipos dos parâmetros.

(67)

Declaração de construtor

Verifica o tipo de cada parâmetro.

Cria uma

Entryrec

com os tipos dos parâmetros.

Procura um construtor igual apenas na classe

corrente.

(68)

Declaração de construtor

Verifica o tipo de cada parâmetro.

Cria uma

Entryrec

com os tipos dos parâmetros.

Procura um construtor igual apenas na classe

corrente.

Insere um método com nome “constructor” na tabela de

símboloscorrente.

(69)

Declaração de construtor

public void VarCheckConstructDeclNode(ConstructDeclNode x) throws SemanticException { EntryMethod c; EntryRec r = null; EntryTable e; ListNode p; VarDeclNode q; VarNode u; int n; if (x == null) return; p = x.body.param; n = 0;

(70)

Declaração de construtor

while (p != null) // para cada parˆametro do construtor {

q = (VarDeclNode) p.node; // q = no com a declarac˜ao do parˆametro u = (VarNode) q.vars.node; // u = no com o nome e dimens˜ao

n++;

// acha a entrada do tipo na tabela

e = Curtable.classFindUp(q.position.image); // se n˜ao achou: ERRO

if (e == null)

throw new SemanticException(q.position, "Class " + q.position.image + " not found");

// constr´oi a lista com os parˆametros r = new EntryRec(e, u.dim, n, r);

p = p.next; }

if (r != null)

r = r.inverte(); // inverte a lista

(71)

Declaração de construtor

// procura construtor com essa assinatura dentro da mesma classe c = Curtable.methodFindInclass("constructor", r);

if (c == null)

{ // se n˜ao achou, insere

c = new EntryMethod("constructor", Curtable.levelup,0 ,r); Curtable.add(c);

}

else // construtor j´a definido na mesma classe: ERRO

throw new SemanticException(x.position, "Constructor " + Curtable.levelup.name +

"(" + (r == null? "" : r.toStr()) + ")" + " already declared");

}

(72)

Declaração de método

Como declaração de construtor

(73)

Declaração de método

Como declaração de construtor

Usa o nome do método em vez da palavra “constructor”

(74)

Declaração de método

Como declaração de construtor

Usa o nome do método em vez da palavra “constructor”

Procura o tipo de retorno para ver se foi declarado

(75)

Declaração de método

Como declaração de construtor

Usa o nome do método em vez da palavra “constructor”

Procura o tipo de retorno para ver se foi declarado

Insere na tabela normalmente

(76)

Análise semântica: parte 3

É a mais complexa das três.

(77)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

(78)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

Declaração de classes e variáveis.

(79)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

Declaração de classes e variáveis.

Comandos.

(80)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

Declaração de classes e variáveis.

Comandos.

Expressões.

(81)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

Declaração de classes e variáveis.

Comandos.

Expressões.

Particularmente importante é a chacagem de tipos.

(82)

Análise semântica: parte 3

É a mais complexa das três.

Diversos aspectos são tratados.

Declaração de classes e variáveis.

Comandos.

Expressões.

Particularmente importante é a chacagem de tipos.

Ou seja: abrange toda a árvore sintática.

(83)

Checagem de tipo

if ( expr )

comando 1;

else

comando 2;

if ( b )

return 0;

(84)

Checagem de tipo

IfNode

VarNode

ReturnNode

Token: b

IntConstNode

Token: 0

procurar a variável b na tabela de símbolos

pegar o tipo com que a variável foi declarada

lançar uma exceção caso o tipo não seja int

(85)

Outros tipos de expressão

Nem sempre expressão é apenas uma variável.

Existem 13 tipos de

ExpreNode

como:

IntConstNode

,

VarNode

,

AddNode

,

MultNode

,

RelationalNode

Expressões podem ser compostas de subexpressões.

Cada método que analisa um desses nós deve ser

capaz de computar o tipo correspondente.

Exemplo:

if ( a + b > 10 )

return 0;

(86)

Exemplo

IfNode

RelationalNode

ReturnNode

AddNode

Token:

>

IntConstNode IntConstNode

VarNode Token: +

VarNode

Token: 10

Token: 0

Token: a

Token: b

(87)

Tipo de uma expressão

Antes de saber qual o tipo da expressão de controle

RelationalNode

, é necessário calcular o tipo de cada

subexpressão.

(88)

Tipo de uma expressão

Antes de saber qual o tipo da expressão de controle

RelationalNode

, é necessário calcular o tipo de cada

subexpressão.

É preciso saber se “a + b” e “10” são expressões do tipo

inteiro para poderem ser comparadas por meio do

operador

>

.

(89)

Tipo de uma expressão

Antes de saber qual o tipo da expressão de controle

RelationalNode

, é necessário calcular o tipo de cada

subexpressão.

É preciso saber se “a + b” e “10” são expressões do tipo

inteiro para poderem ser comparadas por meio do

operador

>

.

É preciso saber se as variáveis “a” e “b” são do tipo

inteiro para poderem ser somadas e produzir um

resultado inteiro.

(90)

Tipo de uma expressão

Antes de saber qual o tipo da expressão de controle

RelationalNode

, é necessário calcular o tipo de cada

subexpressão.

É preciso saber se “a + b” e “10” são expressões do tipo

inteiro para poderem ser comparadas por meio do

operador

>

.

É preciso saber se as variáveis “a” e “b” são do tipo

inteiro para poderem ser somadas e produzir um

resultado inteiro.

O tipo é calculado “de baixo para cima”, a partir das

subesxpressões mais simples.

(91)

Tipo de uma expressão

Antes de saber qual o tipo da expressão de controle

RelationalNode

, é necessário calcular o tipo de cada

subexpressão.

É preciso saber se “a + b” e “10” são expressões do tipo

inteiro para poderem ser comparadas por meio do

operador

>

.

É preciso saber se as variáveis “a” e “b” são do tipo

inteiro para poderem ser somadas e produzir um

resultado inteiro.

O tipo é calculado “de baixo para cima”, a partir das

subesxpressões mais simples.

O método que analisa uma expressão retorna o seu tipo.

(92)

Regras do

RelationalNode

se os dois operandos forem inteiros, a expressão está

OK e o seu tipo é int;

(93)

Regras do

RelationalNode

se os dois operandos forem inteiros, a expressão está

OK e o seu tipo é int;

se os dois operandos forem string, a expressão é válida

somente se o operador for de igualdade ou

desigualdade;

(94)

Regras do

RelationalNode

se os dois operandos forem inteiros, a expressão está

OK e o seu tipo é int;

se os dois operandos forem string, a expressão é válida

somente se o operador for de igualdade ou

desigualdade;

idem para dois objetos de tipos comparáveis (tipos

iguais ou um é subclasse do outro);

(95)

Regras do

RelationalNode

se os dois operandos forem inteiros, a expressão está

OK e o seu tipo é int;

se os dois operandos forem string, a expressão é válida

somente se o operador for de igualdade ou

desigualdade;

idem para dois objetos de tipos comparáveis (tipos

iguais ou um é subclasse do outro);

strings e objetos podem ser comparados quanto à

igualdade e à desigualdade com um outro operando que

seja null.

(96)

Geração de código

MyClass x;

a = x.myMethod( b + c);

criar as instruções para somar esses valores e produzir

um resultado inteiro;

chamar o método MyClass.myMethod(int).

(97)

Geração de código

MyClass x;

a = x.myMethod( b + c);

transformar o valor inteiro de b em um string;

concatenar o valor de a com esse valor transformado,

produzindo como resultado um string;

chamar o método MyClass.myMethod(string).

(98)

Método principal

// verifica se pode operar sobre a ´arvore sint´atica if ( parser.token_source.foundLexError()

+ parser.contParseError == 0) {

if (print_tree) // exibir a ´arvore {

PrintTree prt = new PrintTree();

prt.printRoot(root); // chama m´etodo para imprimir ´arvore }

TypeCheck tc = new TypeCheck(); try {

tc.TypeCheckRoot(root);

System.out.println("0 Semantic Errors found"); }

catch (SemanticException e) {

System.out.println(e.getMessage()); }

(99)

Análise da raiz

public void TypeCheckRoot(ListNode x)

throws SemanticException

{

// faz an´

alise das vari´

aveis e m´

etodos

VarCheckRoot(x);

// faz an´

alise do corpo dos m´

etodos

TypeCheckClassDeclListNode(x);

if (foundSemanticError != 0) // se houve erro,

throw new SemanticException(foundSemanticError

" Semantic Errors found

}

(100)

Declaração de classe

public void TypeCheckClassDeclNode(ClassDeclNode x) throws SemanticException {

Symtable temphold = Curtable; // salva tabela corrente EntryClass nc;

if (x == null) return;

nc = (EntryClass) Curtable.classFindUp(x.name.image); if ( circularSuperclass(nc, nc.parent) )

{ // se existe declarac¸˜ao circular, ERRO nc.parent = null;

throw new SemanticException(x.position, "Circular inheritance"); }

Curtable = nc.nested; // tabela corrente = tabela da classe TypeCheckClassBodyNode(x.body);

Curtable = temphold; // recupera tabela corrente }

(101)

Herança circular

// verifica se existe referˆencia circular de superclasses

private boolean circularSuperclass(EntryClass orig, EntryClass e) {

if ( e == null) return false; if (orig == e )

return true;

return circularSuperclass(orig, e.parent); }

(102)

Análise de construtor

// acha a entrada do construtor na tabela t = Curtable.methodFind("constructor", r); CurMethod = t; // guarda m´etodo corrente // inicia um novo escopo na tabela corrente Curtable.beginScope();

// pega a entrada da classe corrente na tabela thisclass = (EntryClass) Curtable.levelup;

thisvar = new EntryVar("this", thisclass, 0);

Curtable.add(thisvar); // inclui vari´avel local "this" com no. 0 Returntype = null; // tipo de retorno do m´etodo = nenhum

nesting = 0; // n´ıvel de aninhamento de comandos for Nlocals = 1; // inicializa n´umero de vari´aveis locais TypeCheckMethodBodyNode(x.body);

t.totallocals = Nlocals; // n´umero de vari´aveis locais do m´etodo Curtable.endScope(); // retira vari´aveis locais da tabela

}

(103)

Tratamento dos comandos

A partir desse ponto “para baixo” é feito o tratamento

dos comandos que aparecem na árvore sintática.

(104)

Tratamento dos comandos

A partir desse ponto “para baixo” é feito o tratamento

dos comandos que aparecem na árvore sintática.

Cada tipo de nó (cada comando) diferente é tratado de

modo diferente.

(105)

Tratamento dos comandos

A partir desse ponto “para baixo” é feito o tratamento

dos comandos que aparecem na árvore sintática.

Cada tipo de nó (cada comando) diferente é tratado de

modo diferente.

Pode ser um tratamento muito simples (

BlockNode

,

PrintNode

) ou complexo (

VarDeclNode

).

(106)

BlockNode

public void TypeCheckBlockNode(BlockNode x) {

Curtable.beginScope(); // in´ıcio de um escopo TypeCheckStatementListNode(x.stats);

Curtable.endScope(); // final do escopo, libera vars. locais }

public void TypeCheckStatementListNode(ListNode x) { if (x == null) return;

try {

TypeCheckStatementNode( (StatementNode) x.node); } catch (SemanticException e) { System.out.println(e.getMessage()); foundSemanticError++; } TypeCheckStatementListNode(x.next); }

(107)

PrintNode

public void TypeCheckPrintNode(PrintNode x)

throws SemanticException {

type t;

if (x == null) return;

// t = tipo e dimens˜ao do resultado da express˜ao t = TypeCheckExpreNode(x.expr);

// tipo tem que ser string e dimens˜ao tem que ser 0 if ( t.ty != STRING_TYPE || t.dim != 0 )

throw new SemanticException(x.position,

"string expression required"); }

Notar os erros que podem ocorrer.

(108)

Declaração de variável local

public void TypeCheckLocalVarDeclNode(VarDeclNode x) throws SemanticException { ListNode p; VarNode q; EntryVar l, u; EntryTable c; if (x == null) return;

// procura tipo da declarac¸˜ao na tabela de s´ımbolos c = Curtable.classFindUp(x.position.image);

// se n˜ao achou, ERRO if (c == null)

throw new SemanticException(x.position, "Class "+ x.position.image + " not found.");

Verifica se tipo existe.

(109)

Declaração de variável local

for (p = x.vars; p != null; p = p.next) {

q = (VarNode) p.node;

l = Curtable.varFind(q.position.image);

// se vari´avel j´a existe ´e preciso saber que tipo de vari´avel ´e if ( l != null)

{

// verifica se ´e local, definida no escopo corrente if (l.scope == Curtable.scptr) // se for, ERRO

throw new SemanticException(q.position, "Variable "+ p.position.image + " already declared");

(110)

Declaração de variáveis locais

Procura a variável na tabela de símbolos.

(111)

Declaração de variáveis locais

Procura a variável na tabela de símbolos.

Se achou, pode ser um erro (ou não).

(112)

Declaração de variáveis locais

Procura a variável na tabela de símbolos.

Se achou, pode ser um erro (ou não).

l.scope

indica em qual scopo foi inserida a variável.

(113)

Declaração de variáveis locais

Procura a variável na tabela de símbolos.

Se achou, pode ser um erro (ou não).

l.scope

indica em qual scopo foi inserida a variável.

Curtable.scptr

indica qual o scopo corrente.

(114)

Declaração de variáveis locais

Procura a variável na tabela de símbolos.

Se achou, pode ser um erro (ou não).

l.scope

indica em qual scopo foi inserida a variável.

Curtable.scptr

indica qual o scopo corrente.

Se forem iguais, significa que variável já existe no

escopo corrente.

(115)

Declaração de variáveis locais

// c.c. verifica se ´e uma vari´avel de classe

if (l.localcount < 0) // se for, d´a uma advertˆencia

System.out.println("Line " + q.position.beginLine + " Column " + q.position.beginColumn +

" Warning: Variable " + q.position.image + " hides a class variable");

else // sen˜ao, ´e uma vari´avel local em outro escopo

System.out.println("Line " + q.position.beginLine + " Column " + q.position.beginColumn +

" Warning: Variable " + q.position.image + " hides a parameter or a local variable");

Advertência: esconde variável já definida.

(116)

Declaração de variáveis locais

Curtable.add(

new EntryVar(q.position.image, c, q.dim, Nlocals++)

);

Insere na tabela.

(117)

Comando de atribuição

public void TypeCheckAtribNode(AtribNode x)

throws SemanticException {

type t1, t2; EntryVar v;

if (x == null) return;

// verifica se o n´o filho tem um tipo v´alido if ( ! (x.expr1 instanceof DotNode ||

x.expr1 instanceof IndexNode || x.expr1 instanceof VarNode) )

throw new SemanticException(x.position,

"Invalid left side of assignment");

(118)

Comando de atribuição

// verifica se ´e uma atribuic¸˜ao para "this" if ( x.expr instanceof VarNode )

{

EntryVar v = Curtable.varFind(x.expr.position.image);

if ( v != null && v.localcount == 0) // ´e a vari´avel local 0? {

throw new SemanticException(x.position,

"Assigning to variable \"this\" is not legal"); }

}

(119)

Comando de atribuição

t1 = TypeCheckExpreNode(x.expr1); t2 = TypeCheckExpreNode(x.expr2); // verifica tipos das express˜oes // verifica dimens˜oes

if ( t1.dim != t2.dim )

throw new SemanticException(x.position,

"Invalid dimensions in assignment");

Compatibilidade de tipos.

int[][] x, y;

x = new int[10][10];

y = x[0];

(120)

Comando de atribuição

// verifica se lado esquerdo ´e uma classe e direito ´e null, OK if (t1.ty instanceof EntryClass && t2.ty == NULL_TYPE )

return;

// verifica se t2 ´e subclasse de t1

if ( ! ( isSubClass(t2.ty,t1.ty) || isSubClass(t1.ty,t2.ty) ) ) throw new SemanticException(x.position,

"Incompatible types for assignment ");

(121)

Atribuição de subclasses

Nesse último caso, vale uma explicação sobre a semântica

que queremos dar a este comando. Primeiro, se o tipo do

lado direito for uma subclasse do tipo do lado esquerdo,

então a atribuição é feita naturalmente, sem problemas. No

caso inverso, antes de fazer a atribuição, o sistema de

execução faz por conta própria a coerção dos tipos.

Obviamente, se a coerção não puder ser feita, um erro de

execução ocorre.

(122)

Atribuição de subclasse

class A extends C {

int methA() {

C var1;

A var2;

B var3;

var1 = new A(); // OK

var2 = var1;

// OK c/ coerção

var3 = var1;

// ERRO

}

}

class B extends C ...

class C ...

(123)

Análise das expressões

Uma expressão em

X

++

pode ser uma simples

constante ou variável, ou uma expressão composta de

diversas expressões mais simples.

(124)

Análise das expressões

Uma expressão em

X

++

pode ser uma simples

constante ou variável, ou uma expressão composta de

diversas expressões mais simples.

O tipo de uma expressão é calculado com base nos

tipos das suas subexpressões.

(125)

Análise das expressões

Uma expressão em

X

++

pode ser uma simples

constante ou variável, ou uma expressão composta de

diversas expressões mais simples.

O tipo de uma expressão é calculado com base nos

tipos das suas subexpressões.

O método que trata uma expressão deve computar e

retornar um objeto do tipo “type”.

(126)

Classe

type

public class type {

public EntryTable ty;

// entrada na tabela

public int dim;

// dimens˜

ao

public type(EntryTable t, int d)

{

ty = t;

dim = d;

}

(127)

Tipo de uma constante

Para as constantes, obter o seu tipo é trivial.

(128)

Tipo de uma constante

Para as constantes, obter o seu tipo é trivial.

O próprio tipo do nó da árvore sintática determina qual o

tipo da constante.

(129)

Tipo de uma constante

Para as constantes, obter o seu tipo é trivial.

O próprio tipo do nó da árvore sintática determina qual o

tipo da constante.

Somente no caso de uma constante inteira é necessária

uma verificação extra.

(130)

Tipo de uma constante

Para as constantes, obter o seu tipo é trivial.

O próprio tipo do nó da árvore sintática determina qual o

tipo da constante.

Somente no caso de uma constante inteira é necessária

uma verificação extra.

Para verificar se é uma constante válida, utilizamos uma

chamada ao método

Integer.parseInt

da API Java.

(131)

Constante inteira

public type TypeCheckIntConstNode(IntConstNode x) throws SemanticException {

int k;

if (x == null) return null;

// tenta transformar imagem em n´umero inteiro try

{

k = Integer.parseInt(x.position.image); }

catch(NumberFormatException e)

{ // se deu erro, formato ´e inv´alido // (possivelmente fora dos limites)

throw new SemanticException(x.position, "Invalid int constant"); }

return new type(INT_TYPE, 0); }

(132)

Constante string ou null

public type TypeCheckStringConstNode(StringConstNode x) {

if (x == null) return null;

return new type( STRING_TYPE, 0); }

public type TypeCheckNullConstNode(NullConstNode x) {

if (x == null) return null;

return new type( NULL_TYPE, 0); }

(133)

Tipo de uma variável

Para uma variável também não é difícil calcular seu tipo.

(134)

Tipo de uma variável

Para uma variável também não é difícil calcular seu tipo.

Basta consultar a tabela de símbolos.

(135)

Tipo de uma variável

Para uma variável também não é difícil calcular seu tipo.

Basta consultar a tabela de símbolos.

Isto é feito utilizando o conhecido método

Symtable.varFind

(136)

Tipo de uma variável

Para uma variável também não é difícil calcular seu tipo.

Basta consultar a tabela de símbolos.

Isto é feito utilizando o conhecido método

Symtable.varFind

O nome está no nó

VarNode

sendo analisado.

(137)

Tipo de um

VarNode

public type TypeCheckVarNode(VarNode x) throws SemanticException {

EntryVar p;

if (x == null) return null; // procura vari´avel na tabela

p = Curtable.varFind(x.position.image); // se n˜ao achou, ERRO

if (p == null)

throw new SemanticException(x.position, "Variable " +

x.position.image + " not found"); return new type(p.type, p.dim);

}

(138)

Chamada de método

calcula o tipo da expressão que está no seu primeiro

filho e que representa a expressão à esquerda do “.” na

chamada do método

(139)

Chamada de método

calcula o tipo da expressão que está no seu primeiro

filho e que representa a expressão à esquerda do “.” na

chamada do método

se a dimensão é maior que zero. Caso seja, um erro foi

encontrado, pois um array não pode ter um método

associado a ele;

(140)

Chamada de método

calcula o tipo da expressão que está no seu primeiro

filho e que representa a expressão à esquerda do “.” na

chamada do método

se a dimensão é maior que zero. Caso seja, um erro foi

encontrado, pois um array não pode ter um método

associado a ele;

se o tipo calculado corresponde a uma classe. Caso

não seja, um erro foi encontrado, pois tipos simples não

podem ter métodos.

(141)

Tipo de um

CallNode

public type TypeCheckCallNode(CallNode x) throws SemanticException { EntryClass c;

EntryMethod m; type t1, t2;

if (x == null) return null;

// calcula tipo do primeiro filho t1 = TypeCheckExpreNode(x.expr); // se for array, ERRO

if ( t1.dim > 0 )

throw new SemanticException(x.position,

"Arrays do not have methods"); // se n˜ao for uma classe, ERRO

if (! (t1.ty instanceof EntryClass))

throw new SemanticException(x.position, "Type " + t1.ty.name + " does not have methods");

(142)

Chamada de método

Em seguida são calculados os tipos para cada um dos

argumentos.

(143)

Chamada de método

Em seguida são calculados os tipos para cada um dos

argumentos.

Utilizando o nome do método, que é um dos filhos do nó

corrente, e a lista de tipos dos argumentos, realiza-se

uma busca na tabela de símbolos para achar o método

adequado.

(144)

Chamada de método

Em seguida são calculados os tipos para cada um dos

argumentos.

Utilizando o nome do método, que é um dos filhos do nó

corrente, e a lista de tipos dos argumentos, realiza-se

uma busca na tabela de símbolos para achar o método

adequado.

A busca deve ser feita na classe adequada, ou seja, na

classe que foi calculada no início.

(145)

Chamada de método

Em seguida são calculados os tipos para cada um dos

argumentos.

Utilizando o nome do método, que é um dos filhos do nó

corrente, e a lista de tipos dos argumentos, realiza-se

uma busca na tabela de símbolos para achar o método

adequado.

A busca deve ser feita na classe adequada, ou seja, na

classe que foi calculada no início.

A entrada do método na tabela de símbolos diz-nos qual

é o tipo retornado pela chamada.

(146)

Tipo de um

CallNode

// pega tipos dos argumentos

t2 = TypeCheckExpreListNode(x.args);

// procura o m´etodo desejado na classe t1.ty c = (EntryClass) t1.ty;

m = c.nested.methodFind(x.meth.image, (EntryRec) t2.ty); // se n˜ao achou, ERRO

if (m == null)

throw new SemanticException(x.position, "Method " + x.meth.image

+ "(" + (t2.ty == null ? "" : ((EntryRec) t2.ty).toStr()) + ") not found in class " + c.name);

return new type(m.type, m.dim); }

(147)

Expressão de adição/subtração

AddNode

possui dois filhos

ExpreNode

e o tipo de

operação a ser executada.

(148)

Expressão de adição/subtração

AddNode

possui dois filhos

ExpreNode

e o tipo de

operação a ser executada.

São calculados os tipos das subexpressões.

(149)

Expressão de adição/subtração

AddNode

possui dois filhos

ExpreNode

e o tipo de

operação a ser executada.

São calculados os tipos das subexpressões.

Expressões devem ter tipo sem dimensão.

(150)

Expressão de adição/subtração

AddNode

possui dois filhos

ExpreNode

e o tipo de

operação a ser executada.

São calculados os tipos das subexpressões.

Expressões devem ter tipo sem dimensão.

Dois inteiros podem ser somados ou subtraídos.

(151)

Expressão de adição/subtração

AddNode

possui dois filhos

ExpreNode

e o tipo de

operação a ser executada.

São calculados os tipos das subexpressões.

Expressões devem ter tipo sem dimensão.

Dois inteiros podem ser somados ou subtraídos.

Soma pode ser realizada entre strings e inteiros.

(152)

Tipo de um

AddNode

public type TypeCheckAddNode(AddNode x)

throws SemanticException { type t1, t2;

int op; // operac¸˜ao int i, j;

if (x == null) return null; op = x.position.kind;

t1 = TypeCheckExpreNode(x.expr1); t2 = TypeCheckExpreNode(x.expr2); // se dimens˜ao > 0, ERRO

if ( t1.dim > 0 || t2.dim > 0 )

throw new SemanticException(x.position, "Can not use " + x.position.image + " for arrays");

(153)

Tipo de um

AddNode

i = j = 0;

if (t1.ty == INT_TYPE) i++;

else if (t1.ty == STRING_TYPE) j++;

if (t2.ty == INT_TYPE) i++;

else if (t2.ty == STRING_TYPE) j++;

// dois operadores inteiro, OK if (i == 2)

return new type(INT_TYPE, 0);

// um inteiro e um string. S´o pode somar if ( op == langXConstants.PLUS && i+j == 2)

return new type(STRING_TYPE, 0);

throw new SemanticException(x.position, "Invalid types for " + x.position.image);

}

Referências

Documentos relacionados

As abraçadeiras tipo TUCHO SIMPLES INOX , foram desenvolvidas para aplicações que necessitam alto torque de aperto e condições severas de temperatura, permitin- do assim,

Para o cálculo acordado em contrato os clientes deverão necessariamente informar em cada consulta o código administrativo, a senha e o código de um ou mais

Foi apresentada, pelo Ademar, a documentação encaminhada pelo APL ao INMETRO, o qual argumentar sobre a PORTARIA Nº 398, DE 31 DE JULHO DE 2012 E SEU REGULAMENTO TÉCNICO

Neste trabalho avaliamos as respostas de duas espécies de aranhas errantes do gênero Ctenus às pistas químicas de presas e predadores e ao tipo de solo (arenoso ou

Entre as atividades, parte dos alunos é também conduzida a concertos entoados pela Orquestra Sinfônica de Santo André e OSESP (Orquestra Sinfônica do Estado de São

The results of those assays evidenced the importance of a larger diameter of the pilot hole compared to the inner diameter of the screw for reducing insertion torque and

 Considerando a ampla distribuição dos microrganismos, é importante que os alimentos sejam manipulados sob criteriosas condições de higiene, evitando que os

Como irá trabalhar com JavaServer Faces voltado para um container compatível com a tecnologia Java EE 5, você deverá baixar a versão JSF 1.2, a utilizada nesse tutorial.. Ao baixar