Visitor: implemented any possible breakStmt
This commit is contained in:
parent
47bff81942
commit
96847b7a8a
3 changed files with 67 additions and 17 deletions
|
@ -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<Node> nodeList = new LinkedList<>();
|
||||
private final Map<Node, String> labelMap = new HashMap<>();
|
||||
private final Map<SimpleName, List<BreakStmt>> breakMap = new HashMap<>();
|
||||
private final Stack<List<BreakStmt>> 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<BreakStmt> 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<String> toStringList(GraphViz gv) {
|
||||
List<String> res = new LinkedList<>();
|
||||
res.add(gv.start_graph());
|
||||
|
|
|
@ -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<CFG> {
|
||||
|
||||
private Stack<SwitchStmt> switchStack = new Stack<>();
|
||||
private List<BreakStmt> brokenStmts = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void visit(MethodDeclaration methodDeclaration, CFG graph) {
|
||||
graph.beginMethod();
|
||||
|
@ -55,15 +50,24 @@ public class Visitador extends VoidVisitorAdapter<CFG> {
|
|||
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<CFG> {
|
|||
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<CFG> {
|
|||
// 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<CFG> {
|
|||
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<CFG> {
|
|||
// 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
|
||||
|
|
17
src/test/res/mytest/BasicBreak.java
Normal file
17
src/test/res/mytest/BasicBreak.java
Normal file
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue