diff --git a/src/main/java/grafos/CFG.java b/src/main/java/grafos/CFG.java new file mode 100644 index 0000000..b6c08d7 --- /dev/null +++ b/src/main/java/grafos/CFG.java @@ -0,0 +1,70 @@ +package grafos; + +import com.github.javaparser.ast.stmt.EmptyStmt; +import com.github.javaparser.ast.stmt.Statement; + +import java.util.*; + +public class CFG { + private final List nodes = new ArrayList(); + private final Map> edges = new HashMap>(); + private Statement beginNode, endNode; + + public void addNode(Statement stmt) { + nodes.add(stmt); + System.out.println("NODO: " + stmt2str(stmt)); + } + + public void connect(int begin, int end) { + connect(nodes.get(begin), nodes.get(end)); + } + + public void connect(Statement begin, Statement end) { + if (edges.containsKey(begin) && !edges.get(begin).contains(end)) { + edges.get(begin).add(end); + } else { + List dest = new ArrayList(); + dest.add(end); + edges.put(begin, dest); + } + } + + public Statement beginNode() { + if (beginNode == null) { + beginNode = new EmptyStmt(); + nodes.add(beginNode); + } + return beginNode; + } + + public Statement endNode() { + if (endNode == null) { + endNode = new EmptyStmt(); + nodes.add(endNode); + } + return endNode; + } + + public List toStringList() { + List res = new LinkedList(); + for (Map.Entry> e : edges.entrySet()) { + for (Statement dest : e.getValue()) { + res.add(edge2str(e.getKey(), dest)); + } + } + return res; + } + + private String edge2str(Statement a, Statement b) { + return stmt2str(a) + "->" + stmt2str(b); + } + + private String stmt2str(Statement s) { + if (s == beginNode) + return "Start"; + if (s == endNode) + return "Stop"; + int index = nodes.indexOf(s); + return "\"(" + index + ") " + s.toString().replace("\"", "\\\"") + "\""; + } +} diff --git a/src/main/java/grafos/Transformador.java b/src/main/java/grafos/Transformador.java index 4f03edf..e4937b6 100644 --- a/src/main/java/grafos/Transformador.java +++ b/src/main/java/grafos/Transformador.java @@ -7,8 +7,6 @@ import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.visitor.VoidVisitor; import java.io.File; -import java.util.ArrayList; -import java.util.List; public class Transformador { @@ -25,12 +23,18 @@ public class Transformador { quitarComentarios(cu); // Recorremos el AST - List arcos = new ArrayList(); - VoidVisitor> visitador = new Visitador(); - visitador.visit(cu, arcos); + CFG graph = new CFG(); + VoidVisitor visitador = new Visitador(); + visitador.visit(cu, graph); - // Imprimimos el CFG del programa - String dotInfo = imprimirGrafo(arcos); + // Imprimimos el CFG del program + StringBuilder builder = new StringBuilder(); + for (String s : graph.toStringList()) { + builder.append(s); + builder.append(";"); + System.out.println("ARCO: " + s); + } + String dotInfo = builder.toString(); // Generamos un PDF con el CFG del programa System.out.print("\nGenerando PDF..."); @@ -49,19 +53,6 @@ public class Transformador { System.out.println(" PDF generado!"); } - // Imprime el grafo en la pantalla - private static String imprimirGrafo(List arcos) { - StringBuilder dotInfo = new StringBuilder(); - for (String arco : arcos) { - dotInfo.append(arco); - System.out.println("ARCO: " + arco); - } - System.out.println("\nCFG:"); - System.out.println(dotInfo); - - return dotInfo.toString(); - } - // Elimina todos los comentarios de un nodo y sus hijos private static void quitarComentarios(Node node) { node.removeComment(); diff --git a/src/main/java/grafos/Visitador.java b/src/main/java/grafos/Visitador.java index 6ef9c77..fa0e995 100755 --- a/src/main/java/grafos/Visitador.java +++ b/src/main/java/grafos/Visitador.java @@ -1,24 +1,16 @@ package grafos; -import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.ast.stmt.Statement; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; -import java.util.List; - - -public class Visitador extends VoidVisitorAdapter> { +public class Visitador extends VoidVisitorAdapter { //********************************************************/ //********************** Atributos ***********************/ //********************************************************/ - // Usamos un contador para numerar las instrucciones - private int contador = 1; - private String nodoAnterior = "Start"; - private String nodoActual = ""; + private Statement prevNode; //********************************************************/ //*********************** Metodos ************************/ @@ -27,67 +19,27 @@ public class Visitador extends VoidVisitorAdapter> { // Visitador de métodos // Este visitador añade el nodo final al CFG @Override - public void visit(MethodDeclaration methodDeclaration, List collector) { + public void visit(MethodDeclaration methodDeclaration, CFG graph) { + prevNode = graph.beginNode(); + // Visitamos el método - super.visit(methodDeclaration, collector); + super.visit(methodDeclaration, graph); // Añadimos el nodo final al CFG - collector.add(nodoAnterior + "-> Stop;"); + Statement end = graph.endNode(); + if (prevNode != end) + graph.connect(prevNode, end); } // Visitador de expresiones // Cada expresión encontrada genera un nodo en el CFG @Override - public void visit(ExpressionStmt es, List collector) { - // Creamos el nodo actual - nodoActual = crearNodo(es); - - crearArcos(collector); - - nodoAnterior = nodoActual; + public void visit(ExpressionStmt es, CFG graph) { + graph.addNode(es); + graph.connect(prevNode, es); + prevNode = es; // Seguimos visitando... - super.visit(es, collector); + super.visit(es, graph); } - - // Añade un arco desde el último nodo hasta el nodo actual (se le pasa como parametro) - private void añadirArcoSecuencialCFG(List collector) { - System.out.println("NODO: " + nodoActual); - - String arco = nodoAnterior + "->" + nodoActual + ";"; - collector.add(arco); - } - - // Crear arcos - private void crearArcos(List collector) { - añadirArcoSecuencialCFG(collector); - } - - // Crear nodo - // Añade un arco desde el nodo actual hasta el último control - private String crearNodo(Object objeto) { - return "\"(" + contador++ + ") " + quitarComillas(objeto.toString()) + "\""; - } - - // Sustituye " por \" en un string: Sirve para eliminar comillas. - private static String quitarComillas(String texto) { - return texto.replace("\"", "\\\""); - } - - // Dada una sentencia, - // Si es una �nica instrucci�n, devuelve un bloque equivalente - // Si es un bloque, lo devuelve - private BlockStmt convertirEnBloque(Statement statement) { - if (statement instanceof BlockStmt) - return (BlockStmt) statement; - - BlockStmt block = new BlockStmt(); - NodeList blockStmts = new NodeList(); - blockStmts.add(statement); - - block.setStatements(blockStmts); - - return block; - } - }