160 lines
4.7 KiB
Java
Executable file
160 lines
4.7 KiB
Java
Executable file
package grafos;
|
|
|
|
import com.github.javaparser.ast.Node;
|
|
import com.github.javaparser.ast.body.MethodDeclaration;
|
|
import com.github.javaparser.ast.expr.Expression;
|
|
import com.github.javaparser.ast.stmt.*;
|
|
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
|
|
|
|
import java.util.Collections;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
|
|
public class Visitador extends VoidVisitorAdapter<CFG> {
|
|
//********************************************************/
|
|
//********************** Atributos ***********************/
|
|
//********************************************************/
|
|
|
|
private List<Node> prevNode;
|
|
|
|
//********************************************************/
|
|
//*********************** Metodos ************************/
|
|
//********************************************************/
|
|
|
|
// Visitador de métodos
|
|
// Este visitador añade el nodo final al CFG
|
|
@Override
|
|
public void visit(MethodDeclaration methodDeclaration, CFG graph) {
|
|
prevNode = Collections.singletonList(graph.beginNode());
|
|
|
|
// Visitamos el método
|
|
super.visit(methodDeclaration, graph);
|
|
|
|
// Añadimos el nodo final al CFG
|
|
Node end = graph.endNode();
|
|
for (Node n : prevNode)
|
|
if (n != end)
|
|
graph.connect(n, end);
|
|
}
|
|
|
|
@Override
|
|
public void visit(ReturnStmt n, CFG arg) {
|
|
arg.addNode(n);
|
|
arg.connect(prevNode, n);
|
|
super.visit(n, arg);
|
|
arg.connect(n, arg.endNode());
|
|
prevNode = Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public void visit(IfStmt n, CFG graph) {
|
|
Node ifStart = n.getCondition();
|
|
graph.addNode(ifStart);
|
|
graph.connect(prevNode, ifStart);
|
|
|
|
// TODO: shortcut conditions (||, &&)
|
|
|
|
prevNode = Collections.singletonList(ifStart);
|
|
List<Node> prevNodeBegin = prevNode;
|
|
n.getThenStmt().accept(this, graph);
|
|
List<Node> newPrev = new LinkedList<>();
|
|
if (prevNode == prevNodeBegin)
|
|
newPrev.add(ifStart);
|
|
else newPrev.addAll(prevNode);
|
|
prevNode = Collections.singletonList(ifStart);
|
|
if (n.getElseStmt().isPresent()) {
|
|
n.getElseStmt().get().accept(this, graph);
|
|
if (prevNode == prevNodeBegin)
|
|
newPrev.add(ifStart);
|
|
else newPrev.addAll(prevNode);
|
|
} else {
|
|
newPrev.add(ifStart);
|
|
}
|
|
prevNode = newPrev;
|
|
}
|
|
|
|
@Override
|
|
public void visit(WhileStmt n, CFG graph) {
|
|
Node whileStart = n.getCondition();
|
|
graph.addNode(whileStart);
|
|
graph.connect(prevNode, whileStart);
|
|
|
|
// TODO: shortcut conditions (||, &&)
|
|
|
|
prevNode = Collections.singletonList(whileStart);
|
|
n.getBody().accept(this, graph);
|
|
graph.connect(prevNode, whileStart);
|
|
prevNode = Collections.singletonList(whileStart);
|
|
}
|
|
|
|
@Override
|
|
public void visit(DoStmt n, CFG graph) {
|
|
prevNode = new LinkedList<>(prevNode);
|
|
prevNode.add(n.getCondition());
|
|
n.getBody().accept(this, graph);
|
|
graph.addNode(n.getCondition());
|
|
graph.connect(prevNode, n.getCondition());
|
|
prevNode = Collections.singletonList(n.getCondition());
|
|
}
|
|
|
|
@Override
|
|
public void visit(ForStmt n, CFG graph) {
|
|
// Initialization expressions
|
|
if (n.getInitialization() != null) {
|
|
for (Expression e : n.getInitialization()) {
|
|
graph.addNode(e);
|
|
graph.connect(prevNode, e);
|
|
prevNode = Collections.singletonList(e);
|
|
}
|
|
}
|
|
// Comparison expression
|
|
// TODO: shortcut conditions (||, &&)
|
|
if (n.getCompare().isPresent()) {
|
|
graph.addNode(n.getCompare().get());
|
|
graph.connect(prevNode, n.getCompare().get());
|
|
prevNode = Collections.singletonList(n.getCompare().get());
|
|
}
|
|
// Loop body
|
|
n.getBody().accept(this, graph);
|
|
// Update expressions
|
|
if (n.getUpdate() != null) {
|
|
for (Expression e : n.getUpdate()) {
|
|
graph.addNode(e);
|
|
graph.connect(prevNode, e);
|
|
prevNode = Collections.singletonList(e);
|
|
}
|
|
}
|
|
// Connect to comparison expression
|
|
if (n.getCompare().isPresent())
|
|
graph.connect(prevNode, n.getCompare().get());
|
|
else {
|
|
// TODO: connect last update / end of loop with first element of loop body
|
|
}
|
|
// Set comparison as last possible statement
|
|
if (n.getCompare().isPresent())
|
|
prevNode = Collections.singletonList(n.getCompare().get());
|
|
else // There is no comparison, can't exit the loop TODO implement break and continue as way to exit
|
|
prevNode = Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public void visit(ForeachStmt n, CFG graph) {
|
|
ForeachStmt copy = new ForeachStmt(n.getTokenRange().isPresent() ? n.getTokenRange().get() : null, n.getVariable(), n.getIterable(), new EmptyStmt());
|
|
graph.addNode(copy);
|
|
graph.connect(prevNode, copy);
|
|
prevNode = Collections.singletonList(copy);
|
|
n.getBody().accept(this, graph);
|
|
graph.connect(prevNode, copy);
|
|
prevNode = Collections.singletonList(copy);
|
|
}
|
|
|
|
@Override
|
|
public void visit(ExpressionStmt es, CFG graph) {
|
|
graph.addNode(es);
|
|
graph.connect(prevNode, es);
|
|
prevNode = Collections.singletonList(es);
|
|
|
|
// Seguimos visitando...
|
|
super.visit(es, graph);
|
|
}
|
|
}
|