2019-03-26 20:11:14 +01:00
|
|
|
package grafos;
|
|
|
|
|
2019-03-26 22:41:38 +01:00
|
|
|
import com.github.javaparser.ast.Node;
|
2019-04-03 15:34:25 +02:00
|
|
|
import com.github.javaparser.ast.NodeList;
|
2019-03-26 20:11:14 +01:00
|
|
|
import com.github.javaparser.ast.body.MethodDeclaration;
|
2019-03-27 01:57:03 +01:00
|
|
|
import com.github.javaparser.ast.expr.Expression;
|
|
|
|
import com.github.javaparser.ast.stmt.*;
|
2019-03-26 20:11:14 +01:00
|
|
|
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
|
|
|
|
|
2019-03-26 23:26:01 +01:00
|
|
|
import java.util.LinkedList;
|
2019-03-26 22:41:38 +01:00
|
|
|
import java.util.List;
|
2019-04-03 15:34:25 +02:00
|
|
|
import java.util.Stack;
|
2019-03-26 22:41:38 +01:00
|
|
|
|
2019-03-26 22:25:52 +01:00
|
|
|
public class Visitador extends VoidVisitorAdapter<CFG> {
|
2019-03-26 20:29:29 +01:00
|
|
|
|
2019-04-03 15:34:25 +02:00
|
|
|
private Stack<SwitchStmt> switchStack = new Stack<>();
|
|
|
|
private List<BreakStmt> brokenStmts = new LinkedList<>();
|
2019-03-26 20:29:29 +01:00
|
|
|
|
|
|
|
@Override
|
2019-03-26 22:25:52 +01:00
|
|
|
public void visit(MethodDeclaration methodDeclaration, CFG graph) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.beginMethod();
|
2019-03-26 22:25:52 +01:00
|
|
|
super.visit(methodDeclaration, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.finishMethod();
|
2019-03-26 20:11:14 +01:00
|
|
|
}
|
2019-03-26 20:29:29 +01:00
|
|
|
|
2019-03-27 11:55:19 +01:00
|
|
|
@Override
|
|
|
|
public void visit(ReturnStmt n, CFG arg) {
|
2019-04-04 00:03:12 +02:00
|
|
|
arg.connectTo(n);
|
|
|
|
arg.connectTo(arg.getEndNode());
|
|
|
|
arg.clearNode();
|
2019-03-27 11:55:19 +01:00
|
|
|
}
|
|
|
|
|
2019-03-26 23:26:01 +01:00
|
|
|
@Override
|
|
|
|
public void visit(IfStmt n, CFG graph) {
|
2019-04-04 00:03:12 +02:00
|
|
|
// Connect to the condition
|
2019-03-26 23:26:01 +01:00
|
|
|
Node ifStart = n.getCondition();
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.beginBlock(n, ifStart);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(ifStart);
|
|
|
|
// Connect condition to then block
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(true);
|
2019-03-26 23:26:01 +01:00
|
|
|
n.getThenStmt().accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
// Save end of then block
|
|
|
|
List<Node> newPrev = new LinkedList<>(graph.getNodeList());
|
|
|
|
// Connect condition to else block
|
|
|
|
graph.setNode(ifStart);
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(false);
|
2019-03-26 23:26:01 +01:00
|
|
|
if (n.getElseStmt().isPresent()) {
|
|
|
|
n.getElseStmt().get().accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
newPrev.addAll(graph.getNodeList());
|
2019-03-26 23:26:01 +01:00
|
|
|
} else {
|
|
|
|
newPrev.add(ifStart);
|
|
|
|
}
|
2019-04-04 00:03:12 +02:00
|
|
|
// Set ends of then/else as the new list
|
|
|
|
graph.setNodeList(newPrev);
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-03-26 23:26:01 +01:00
|
|
|
}
|
|
|
|
|
2019-03-27 00:16:44 +01:00
|
|
|
@Override
|
|
|
|
public void visit(WhileStmt n, CFG graph) {
|
|
|
|
Node whileStart = n.getCondition();
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.beginBlock(n, whileStart);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(whileStart);
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(true);
|
2019-03-27 00:16:44 +01:00
|
|
|
n.getBody().accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(whileStart);
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(false);
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-03-27 00:16:44 +01:00
|
|
|
}
|
|
|
|
|
2019-03-27 00:41:26 +01:00
|
|
|
@Override
|
|
|
|
public void visit(DoStmt n, CFG graph) {
|
2019-04-03 17:37:57 +02:00
|
|
|
Node condition = n.getCondition();
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.beginBlock(n, condition);
|
|
|
|
graph.appendNode(condition);
|
2019-03-27 00:41:26 +01:00
|
|
|
n.getBody().accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(condition);
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(false);
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-03-27 00:41:26 +01:00
|
|
|
}
|
|
|
|
|
2019-03-27 01:57:03 +01:00
|
|
|
@Override
|
|
|
|
public void visit(ForStmt n, CFG graph) {
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.beginBlock(n, n.getCompare().orElse(null));
|
2019-03-27 01:57:03 +01:00
|
|
|
// Initialization expressions
|
|
|
|
if (n.getInitialization() != null) {
|
|
|
|
for (Expression e : n.getInitialization()) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(e);
|
2019-03-27 01:57:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Comparison expression
|
|
|
|
// TODO: shortcut conditions (||, &&)
|
|
|
|
if (n.getCompare().isPresent()) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(n.getCompare().get());
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(true);
|
2019-03-27 01:57:03 +01:00
|
|
|
}
|
|
|
|
// Loop body
|
|
|
|
n.getBody().accept(this, graph);
|
|
|
|
// Update expressions
|
2019-04-04 00:03:12 +02:00
|
|
|
if (n.getUpdate() != null)
|
|
|
|
for (Expression e : n.getUpdate())
|
|
|
|
graph.connectTo(e);
|
2019-03-27 01:57:03 +01:00
|
|
|
// Connect to comparison expression
|
|
|
|
// Set comparison as last possible statement
|
2019-04-03 18:00:14 +02:00
|
|
|
if (n.getCompare().isPresent()) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(n.getCompare().get());
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.setNextLabel(false);
|
2019-04-04 00:03:12 +02:00
|
|
|
} else {
|
|
|
|
// TODO: connect last update / end of loop with first element of loop body
|
|
|
|
// There is no comparison, can't exit the loop TODO implement break and continue as way to exit
|
|
|
|
graph.clearNode();
|
|
|
|
}
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-03-27 01:57:03 +01:00
|
|
|
}
|
|
|
|
|
2019-03-27 12:11:08 +01:00
|
|
|
@Override
|
|
|
|
public void visit(ForeachStmt n, CFG graph) {
|
2019-04-03 15:34:25 +02:00
|
|
|
ForeachStmt copy = new ForeachStmt(n.getTokenRange().orElse(null), n.getVariable(), n.getIterable(), new EmptyStmt());
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.beginBlock(n, copy);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(copy);
|
|
|
|
graph.setNextLabel(true);
|
2019-03-27 12:11:08 +01:00
|
|
|
n.getBody().accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(copy);
|
|
|
|
graph.setNextLabel(false);
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-03-27 12:11:08 +01:00
|
|
|
}
|
|
|
|
|
2019-04-03 15:34:25 +02:00
|
|
|
@Override
|
|
|
|
public void visit(SwitchEntryStmt n, CFG graph) {
|
|
|
|
// Case header
|
|
|
|
Node caseNode = new SwitchEntryStmt(n.getTokenRange().orElse(null), n.getLabel().orElse(null), new NodeList<>());
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(caseNode);
|
2019-04-03 15:34:25 +02:00
|
|
|
// Case body
|
|
|
|
n.getStatements().accept(this, graph);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void visit(SwitchStmt n, CFG graph) {
|
|
|
|
// Link previous statement to the switch's selector
|
2019-04-03 17:37:57 +02:00
|
|
|
Node selectorNode = n.getSelector();
|
2019-04-03 18:00:14 +02:00
|
|
|
graph.beginBlock(n, selectorNode);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(selectorNode);
|
2019-04-03 15:34:25 +02:00
|
|
|
// Analyze switch's cases
|
|
|
|
switchStack.push(n);
|
|
|
|
for (SwitchEntryStmt entry : n.getEntries()) {
|
|
|
|
entry.accept(this, graph);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.appendNode(selectorNode);
|
2019-04-03 15:34:25 +02:00
|
|
|
}
|
|
|
|
switchStack.pop();
|
|
|
|
// The next statement will be linked to:
|
|
|
|
// 1. All break statements that broke from the switch
|
|
|
|
// 2. If the switch doesn't have a default statement, the switch's selector
|
|
|
|
// 3. If the last entry doesn't break, to the last statement
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.removeNode(selectorNode);
|
|
|
|
graph.appendNodes(brokenStmts); // 1
|
|
|
|
brokenStmts.clear();
|
2019-04-03 15:34:25 +02:00
|
|
|
if (n.getEntries().get(n.getEntries().size() - 1).getLabel().isPresent())
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.appendNode(selectorNode); // 2
|
2019-04-03 17:37:57 +02:00
|
|
|
graph.endBlock();
|
2019-04-03 15:34:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void visit(BreakStmt n, CFG graph) {
|
|
|
|
if (!switchStack.isEmpty() && !n.getLabel().isPresent()) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(n, false);
|
2019-04-03 15:34:25 +02:00
|
|
|
brokenStmts.add(n);
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.clearNode();
|
2019-04-03 15:34:25 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
super.visit(n, graph);
|
|
|
|
}
|
|
|
|
|
2019-03-26 20:11:14 +01:00
|
|
|
@Override
|
2019-03-26 22:25:52 +01:00
|
|
|
public void visit(ExpressionStmt es, CFG graph) {
|
2019-04-04 00:03:12 +02:00
|
|
|
graph.connectTo(es);
|
2019-03-26 20:11:14 +01:00
|
|
|
}
|
|
|
|
}
|