diff --git a/src/main/java/grafos/CFG.java b/src/main/java/grafos/CFG.java index 16ac2cb..8a77bcc 100644 --- a/src/main/java/grafos/CFG.java +++ b/src/main/java/grafos/CFG.java @@ -2,6 +2,7 @@ package grafos; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.expr.BooleanLiteralExpr; +import com.github.javaparser.ast.expr.SimpleName; import com.github.javaparser.ast.stmt.*; import java.util.*; @@ -14,6 +15,8 @@ public class CFG { private final Node beginNode = new EmptyStmt(), endNode = new EmptyStmt(); private final LinkedList nodeList = new LinkedList<>(); private final Map labelMap = new HashMap<>(); + private final Map> breakMap = new HashMap<>(); + private final Stack> breakStack = new Stack<>(); private void registerNode(Node stmt) { nodes.add(stmt); @@ -111,6 +114,32 @@ public class CFG { return endNode; } + public void beginBreakSection(SimpleName name) { + breakMap.put(name, new LinkedList<>()); + } + + public void beginBreakSection() { + breakStack.push(new LinkedList<>()); + } + + public void registerBreak(BreakStmt stmt) { + List list; + if (stmt.getLabel().isPresent()) { + list = breakMap.get(stmt.getLabel().get()); + } else { + list = breakStack.peek(); + } + list.add(stmt); + } + + public void endBreakSection(SimpleName name) { + nodeList.addAll(breakMap.remove(name)); + } + + public void endBreakSection() { + nodeList.addAll(breakStack.pop()); + } + public List toStringList(GraphViz gv) { List res = new LinkedList<>(); res.add(gv.start_graph()); diff --git a/src/main/java/grafos/Visitador.java b/src/main/java/grafos/Visitador.java index e633c75..9fbd8cf 100755 --- a/src/main/java/grafos/Visitador.java +++ b/src/main/java/grafos/Visitador.java @@ -9,13 +9,8 @@ import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import java.util.LinkedList; import java.util.List; -import java.util.Stack; public class Visitador extends VoidVisitorAdapter { - - private Stack switchStack = new Stack<>(); - private List brokenStmts = new LinkedList<>(); - @Override public void visit(MethodDeclaration methodDeclaration, CFG graph) { graph.beginMethod(); @@ -55,15 +50,24 @@ public class Visitador extends VoidVisitorAdapter { graph.endBlock(); } + @Override + public void visit(LabeledStmt n, CFG graph) { + graph.beginBreakSection(n.getLabel()); + super.visit(n, graph); + graph.endBreakSection(n.getLabel()); + } + @Override public void visit(WhileStmt n, CFG graph) { Node whileStart = n.getCondition(); graph.beginBlock(n, whileStart); + graph.beginBreakSection(); graph.connectTo(whileStart); graph.setNextLabel(true); n.getBody().accept(this, graph); graph.connectTo(whileStart); graph.setNextLabel(false); + graph.endBreakSection(); graph.endBlock(); } @@ -71,16 +75,19 @@ public class Visitador extends VoidVisitorAdapter { public void visit(DoStmt n, CFG graph) { Node condition = n.getCondition(); graph.beginBlock(n, condition); + graph.beginBreakSection(); graph.appendNode(condition); n.getBody().accept(this, graph); graph.connectTo(condition); graph.setNextLabel(false); + graph.endBreakSection(); graph.endBlock(); } @Override public void visit(ForStmt n, CFG graph) { graph.beginBlock(n, n.getCompare().orElse(null)); + graph.beginBreakSection(); // Initialization expressions if (n.getInitialization() != null) { for (Expression e : n.getInitialization()) { @@ -109,6 +116,7 @@ public class Visitador extends VoidVisitorAdapter { // There is no comparison, can't exit the loop TODO implement break and continue as way to exit graph.clearNode(); } + graph.endBreakSection(); graph.endBlock(); } @@ -116,11 +124,13 @@ public class Visitador extends VoidVisitorAdapter { public void visit(ForeachStmt n, CFG graph) { ForeachStmt copy = new ForeachStmt(n.getTokenRange().orElse(null), n.getVariable(), n.getIterable(), new EmptyStmt()); graph.beginBlock(n, copy); + graph.beginBreakSection(); graph.connectTo(copy); graph.setNextLabel(true); n.getBody().accept(this, graph); graph.connectTo(copy); graph.setNextLabel(false); + graph.endBreakSection(); graph.endBlock(); } @@ -138,35 +148,29 @@ public class Visitador extends VoidVisitorAdapter { // Link previous statement to the switch's selector Node selectorNode = n.getSelector(); graph.beginBlock(n, selectorNode); + graph.beginBreakSection(); graph.connectTo(selectorNode); // Analyze switch's cases - switchStack.push(n); for (SwitchEntryStmt entry : n.getEntries()) { entry.accept(this, graph); graph.appendNode(selectorNode); } - 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 graph.removeNode(selectorNode); - graph.appendNodes(brokenStmts); // 1 - brokenStmts.clear(); if (n.getEntries().get(n.getEntries().size() - 1).getLabel().isPresent()) - graph.appendNode(selectorNode); // 2 + graph.appendNode(selectorNode); + graph.endBreakSection(); graph.endBlock(); } @Override public void visit(BreakStmt n, CFG graph) { - if (!switchStack.isEmpty() && !n.getLabel().isPresent()) { - graph.connectTo(n, false); - brokenStmts.add(n); - graph.clearNode(); - return; - } - super.visit(n, graph); + graph.connectTo(n, false); + graph.clearNode(); + graph.registerBreak(n); } @Override diff --git a/src/test/res/mytest/BasicBreak.java b/src/test/res/mytest/BasicBreak.java new file mode 100644 index 0000000..17204ab --- /dev/null +++ b/src/test/res/mytest/BasicBreak.java @@ -0,0 +1,17 @@ +package mytest; + +public class BasicBreak { + public static void main(String[] args) { + int x = 0; + bucle: + while (true) { + x++; + for (int y = 0; y < 10; y++) { + if (y == x) break; + if (y * 2 == x) break bucle; + } + if (x > 10) break; + x++; + } + } +}