Como construir um compilador utilizando ferramentas Java

Propaganda
Como construir um compilador utilizando
ferramentas Java
Aula 10 – Exibição da árvore sintática
Prof. Márcio Delamaro
[email protected]
Como construir um compilador utilizando ferramentas Java – p. 1/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Introdução às demais fases do nosso compilador.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Introdução às demais fases do nosso compilador.
Não utilizaremos mais o arquivo .jj para fazermos
nossas implementações.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Introdução às demais fases do nosso compilador.
Não utilizaremos mais o arquivo .jj para fazermos
nossas implementações.
A exibição da árvore sintática é efetuada por um
conjunto de métodos que analisam os nós da árvore e
adotam as ações necessárias para exibi-los.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Introdução às demais fases do nosso compilador.
Não utilizaremos mais o arquivo .jj para fazermos
nossas implementações.
A exibição da árvore sintática é efetuada por um
conjunto de métodos que analisam os nós da árvore e
adotam as ações necessárias para exibi-los.
Para cada tipo de nó, existe um método correspondente.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Por que visualisar
Verificar se nossa implementação da árvore sintática
está correta.
Introdução às demais fases do nosso compilador.
Não utilizaremos mais o arquivo .jj para fazermos
nossas implementações.
A exibição da árvore sintática é efetuada por um
conjunto de métodos que analisam os nós da árvore e
adotam as ações necessárias para exibi-los.
Para cada tipo de nó, existe um método correspondente.
A análise semântica e a geração de código se
processam exatamente da mesma forma.
Como construir um compilador utilizando ferramentas Java – p. 2/2
Como vamos exibir
Forma textual.
Como construir um compilador utilizando ferramentas Java – p. 3/2
Como vamos exibir
Forma textual.
Cada nó é numerado.
Como construir um compilador utilizando ferramentas Java – p. 3/2
Como vamos exibir
Forma textual.
Cada nó é numerado.
Filhos são numerados (visita em profundidade)
Como construir um compilador utilizando ferramentas Java – p. 3/2
Como vamos exibir
Forma textual.
Cada nó é numerado.
Filhos são numerados (visita em profundidade)
Exibe-se para cada nó: seu número, tipo, número dos
nós filhos
Como construir um compilador utilizando ferramentas Java – p. 3/2
Exemplo
class a {
string b;
constructor(int c)
{
b = c + "";
}
int m()
{
print "b: " + b;
}
}
Como construir um compilador utilizando ferramentas Java – p. 4/2
Exemplo
(1)ListNode
(2)ClassDeclNode
Token: a
Token: string
(3)ClassBodyNode
(4)ListNode
(8)ListNode
(22)ListNode
(5)VarDeclNode
(9)ConstructDeclNode
(23)MethodDeclNode
(6)ListNode
(10)MethodBodyNode
Token: int
Token: m
(7)VarNode
(11)ListNode
(15)BlockNode
(25)BlockNode
Token: b
(12)VarDeclNode
(16)ListNode
(26)ListNode
Token: int
(13)ListNode
(17)AtribNode
(27)PrintNode
(14)VarNode
(18)VarNode
Token: c
Token: b
(19)AddNode
(20)VarNode
Token: +
Token: c
(24)MethodBodyNode
(28)AddNode
(29)StringConstNode
(21)StringConstNode
Token: ”b: ”
Token: +
(30)VarNode
Token: b
Token: ” ”
Como construir um compilador utilizando ferramentas Java – p. 5/2
Exemplo
1: ListNode (ClassDeclNode) ===> 2 null
2: ClassDeclNode ===> a null 3
3: ClassBodyNode ===> null 4 8 22
4: ListNode (VarDeclNode) ===> 5 null
5: VarDeclNode ===> string 6
6: ListNode (VarNode) ===> 7 null
7: VarNode ===> b
8: ListNode (ConstructDeclNode) ===> 9 null
9: ConstructDeclNode ===> 10
10: MethodBodyNode ===> 11 15
11: ListNode (VarDeclNode) ===> 12 null
12: VarDeclNode ===> int 13
13: ListNode (VarNode) ===> 14 null
14: VarNode ===> c
15: BlockNode ===> 16
16: ListNode (StatementNode) ===> 17 null
17: AtribNode ===> 18 19
18: VarNode ===> b
19: AddNode ===> 20 + 21
20: VarNode ===> c
Como construir um compilador utilizando ferramentas Java – p. 6/2
Observações
Token não é numerado.
Como construir um compilador utilizando ferramentas Java – p. 7/2
Observações
Token não é numerado.
Junto com um ListNode é exibido o tipo do nó contido
na lista.
Como construir um compilador utilizando ferramentas Java – p. 7/2
Observações
Token não é numerado.
Junto com um ListNode é exibido o tipo do nó contido
na lista.
Quando algum dos filhos não existe, utiliza-se “null” na
exibição.
Como construir um compilador utilizando ferramentas Java – p. 7/2
Observações
Token não é numerado.
Junto com um ListNode é exibido o tipo do nó contido
na lista.
Quando algum dos filhos não existe, utiliza-se “null” na
exibição.
Pequenas modificações devem ser feitas no método
main no arquivo .jj
Como construir um compilador utilizando ferramentas Java – p. 7/2
Argumento na chamada
for (i = 0; i < args.length - 1; i++)
{
. . .
if (args[i].equals("-print_tree") )
print_tree = true;
. . .
}
Como construir um compilador utilizando ferramentas Java – p. 8/2
Exibição
if ( parser.token_source.foundLexError()
+ parser.contParseError == 0 &&
print_tree)
{
PrintTree prt = new PrintTree();
prt.printRoot(root);
}
Como construir um compilador utilizando ferramentas Java – p. 9/2
Classe PrintTree
Dentro do pacote syntacticTree
Nessa única classe estão os métodos para numerar e
exibir cada tipo de nó.
Um método para numerar ClassDeclNode, um para
numerar ClassbodyNode, um para cada tipo de
ListNode, etc.
O mesmo para exibir.
O ponto de entrada na classe é o método printRoot
que recebe um ListNode que é a raiz da árvore
sintática.
Como construir um compilador utilizando ferramentas Java – p. 10/2
Básicos da classe
public class PrintTree {
int kk;
public PrintTree() {
kk = 1;
// inicializa contador de nós
}
public void printRoot(ListNode x) {
if ( x == null )
System.out.println("Empty syntatic tree.");
else {
numberClassDeclListNode(x);
printClassDeclListNode(x);
}
System.out.println();
}
Como construir um compilador utilizando ferramentas Java – p. 11/2
Métodos que numeram
atribuir ao nó que lhe foi passado como argumento o
valor da variável kk;
Como construir um compilador utilizando ferramentas Java – p. 12/2
Métodos que numeram
atribuir ao nó que lhe foi passado como argumento o
valor da variável kk;
incrementar kk;
Como construir um compilador utilizando ferramentas Java – p. 12/2
Métodos que numeram
atribuir ao nó que lhe foi passado como argumento o
valor da variável kk;
incrementar kk;
chamar os métodos para numeração, passando como
argumento os filhos do nó que lhe foi passado como
argumento.
Como construir um compilador utilizando ferramentas Java – p. 12/2
Métodos que numeram
atribuir ao nó que lhe foi passado como argumento o
valor da variável kk;
incrementar kk;
chamar os métodos para numeração, passando como
argumento os filhos do nó que lhe foi passado como
argumento.
Como armazenar o número do nó?
Como construir um compilador utilizando ferramentas Java – p. 12/2
GeneralNode
package syntacticTree;
import Token;
abstract public class GeneralNode {
public Token position;
public int number;
public GeneralNode(Token x) {
position = x;
number = 0;
}
}
Como construir um compilador utilizando ferramentas Java – p. 13/2
ClassBodyNode
public void numberClassBodyNode(ClassBodyNode
{
if ( x == null ) return;
x.number = kk++;
numberClassDeclListNode(x.clist);
numberVarDeclListNode(x.vlist);
numberConstructDeclListNode(x.ctlist);
numberMethodDeclListNode(x.mlist);
}
Como construir um compilador utilizando ferramentas Java – p. 14/2
Especial: ListNode
public void numberListNode(ListNode x)
{
if ( x == null ) return;
// numera x.node
numberListNode(x.next);
}
Como construir um compilador utilizando ferramentas Java – p. 15/2
Especial: ListNode
Ao visitarmos um nó desse tipo, queremos visitar cada
elemento que compõe a lista.
Precisamos saber qual é o tipo do nó filho.
Sáo assim saberemos qual método chamar.
Solução: um método para cada tipo possível de lista.
Por exemplo: numberClassDeclListNode
Como construir um compilador utilizando ferramentas Java – p. 16/2
numberClassDeclListNode
public void numberClassDeclListNode(ListNode x)
{
if(x == null) return;
x.number = kk++;
numberClassDeclNode((ClassDeclNode)x.node);
numberClassDeclListNode(x.next);
}
Como construir um compilador utilizando ferramentas Java – p. 17/2
Sete listas
numberClassDeclListNode (lista de
ClassDeclNode)
numberVarDeclListNode (lista de VarDeclNode)
numberVarListNode (lista de VarNode)
numberConstructDeclListNode (lista de
ConstructDeclNode)
numberMethodDeclListNode (lista de
MethodDeclNode)
numberStatementListNode (lista de
statementNode)
numberExpreListNode (lista de ExpreNode).
Como construir um compilador utilizando ferramentas Java – p. 18/2
Especial II: StatementNode
public void numberMethodBodyNode(
MethodBodyNode x)
{
if (x == null) return;
x.number = kk++;
numberVarDeclListNode(x.param);
numberStatementNode(x.stat);
}
Como construir um compilador utilizando ferramentas Java – p. 19/2
Especial II: StatementNode
O que deve fazer numberStatementNode?
Descobrir qual é o tipo real do nó.
Redirecionar para o método correto como:
numberBlockNode, numberIfNode, numberForNode,
numberPrintNode, etc
Como construir um compilador utilizando ferramentas Java – p. 20/2
Especial II: StatementNode
public void
numberStatementNode(StatementNode x) {
if (x instanceof BlockNode)
numberBlockNode( (BlockNode) x);
else
if (x instanceof VarDeclNode)
numberVarDeclNode( (VarDeclNode) x);
else
if (x instanceof AtribNode)
numberAtribNode( (AtribNode) x);
else
if (x instanceof IfNode)
numberIfNode( (IfNode) x);
else
Como construir um compilador utilizando ferramentas Java – p. 21/2
Especial III: ExpreNode
O mesmo problema acontece quando um ExpreNode
aparece como filho de um nó como, por exemplo, o IfNode.
Existe um numberExpreNode que redireciona a chamada
para o método correto, de acordo com o tipo real do nó.
Como construir um compilador utilizando ferramentas Java – p. 22/2
Especial III: ExpreNode
public void numberExpreNode(ExpreNode x) {
if (x instanceof NewObjectNode)
numberNewObjectNode( (NewObjectNode) x);
else
if (x instanceof NewArrayNode)
numberNewArrayNode( (NewArrayNode) x);
else
if (x instanceof RelationalNode)
numberRelationalNode( (RelationalNode) x);
else
if (x instanceof AddNode)
numberAddNode( (AddNode) x);
else
Como construir um compilador utilizando ferramentas Java – p. 23/2
Exibição dos nós
Aplica-se quase tudo que comentamos em relação a
sua numeração.
Para cada tipo de nó, temos um, ou em alguns casos,
alguns métodos que tratam desse tipo de nó.
A diferença reside nas ações que são tomadas.
Queremos mostrar qual é o tipo de nó e quais são os
seus filhos.
Como construir um compilador utilizando ferramentas Java – p. 24/2
Exemplo: ClassBodyNode
public void printClassBodyNode(ClassBodyNode x)
{
if ( x == null ) return;
System.out.println();
System.out.print(x.number + ": ClassBodyNode ===> " +
(x.clist == null ? "null" : String.valueOf(x.clist.number))
+ " " +
(x.vlist == null ? "null" : String.valueOf(x.vlist.number))
+ " " +
(x.ctlist == null ? "null" : String.valueOf(x.ctlist.number))
+ " " +
(x.mlist == null ? "null" : String.valueOf(x.mlist.number)) );
printClassDeclListNode(x.clist);
printVarDeclListNode(x.vlist);
printConstructDeclListNode(x.ctlist);
printMethodDeclListNode(x.mlist);
}
Como construir um compilador utilizando ferramentas Java – p. 25/2
Exibição: Token
Como esses nós não possuem numeração, quando
aparecem na árvore sintática, exibimos diretamente seu
conteúdo junto com o seu pai, ou seja, o conteúdo da sua
variável image que mostra qual foi o símbolo consumido na
entrada e que originou o token.
Como construir um compilador utilizando ferramentas Java – p. 26/2
Exemplo: printClassDeclNode
public void printClassDeclNode(ClassDeclNode x)
{
if ( x == null ) return;
System.out.println();
System.out.print(x.number + ": ClassDeclNode ===> " +
x.name.image + " " +
(x.supername == null ? "null": x.supername.image) + " " +
(x.body == null ? "null": String.valueOf(x.body.number)) );
printClassBodyNode(x.body);
}
Como construir um compilador utilizando ferramentas Java – p. 27/2
Outras operações
Programa de “pretty-print” que produz como saída o
programa-fonte formatado de acordo com algumas
regras de indentação.
Construção do grafo de fluxo de controle do programa.
Esse tipo de grafo é muito útil para a atividade de teste,
principalmente quando a este se associa informação
sobre a utilização das variáveis.
Cálculo da complexidade do programa, como número de
linhas de código, complexidade ciclomática,
complexidade de Halstead etc.
Como construir um compilador utilizando ferramentas Java – p. 28/2
Exercício
Faça o download dos arquivos do capítulo 7 do livro.
Procure na Internet e faça o download do programa
GraphViz.
Determine como o GraphViz pode ser usado para
gerar uma saída gráfica da árvore sintática.
Crie uma nova classe PrintGraphTree que gera um
arquivo no formato que possa ser processado pela
GraphViz
Adicione no seu compilador uma opção -graph_tree que
habilita a geração desse arquivo.
Como construir um compilador utilizando ferramentas Java – p. 29/2
Download