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.Node;
|
||||||
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
|
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
|
||||||
|
import com.github.javaparser.ast.expr.SimpleName;
|
||||||
import com.github.javaparser.ast.stmt.*;
|
import com.github.javaparser.ast.stmt.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -14,6 +15,8 @@ public class CFG {
|
||||||
private final Node beginNode = new EmptyStmt(), endNode = new EmptyStmt();
|
private final Node beginNode = new EmptyStmt(), endNode = new EmptyStmt();
|
||||||
private final LinkedList<Node> nodeList = new LinkedList<>();
|
private final LinkedList<Node> nodeList = new LinkedList<>();
|
||||||
private final Map<Node, String> labelMap = new HashMap<>();
|
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) {
|
private void registerNode(Node stmt) {
|
||||||
nodes.add(stmt);
|
nodes.add(stmt);
|
||||||
|
@ -111,6 +114,32 @@ public class CFG {
|
||||||
return endNode;
|
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) {
|
public List<String> toStringList(GraphViz gv) {
|
||||||
List<String> res = new LinkedList<>();
|
List<String> res = new LinkedList<>();
|
||||||
res.add(gv.start_graph());
|
res.add(gv.start_graph());
|
||||||
|
|
|
@ -9,13 +9,8 @@ import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class Visitador extends VoidVisitorAdapter<CFG> {
|
public class Visitador extends VoidVisitorAdapter<CFG> {
|
||||||
|
|
||||||
private Stack<SwitchStmt> switchStack = new Stack<>();
|
|
||||||
private List<BreakStmt> brokenStmts = new LinkedList<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MethodDeclaration methodDeclaration, CFG graph) {
|
public void visit(MethodDeclaration methodDeclaration, CFG graph) {
|
||||||
graph.beginMethod();
|
graph.beginMethod();
|
||||||
|
@ -55,15 +50,24 @@ public class Visitador extends VoidVisitorAdapter<CFG> {
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LabeledStmt n, CFG graph) {
|
||||||
|
graph.beginBreakSection(n.getLabel());
|
||||||
|
super.visit(n, graph);
|
||||||
|
graph.endBreakSection(n.getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WhileStmt n, CFG graph) {
|
public void visit(WhileStmt n, CFG graph) {
|
||||||
Node whileStart = n.getCondition();
|
Node whileStart = n.getCondition();
|
||||||
graph.beginBlock(n, whileStart);
|
graph.beginBlock(n, whileStart);
|
||||||
|
graph.beginBreakSection();
|
||||||
graph.connectTo(whileStart);
|
graph.connectTo(whileStart);
|
||||||
graph.setNextLabel(true);
|
graph.setNextLabel(true);
|
||||||
n.getBody().accept(this, graph);
|
n.getBody().accept(this, graph);
|
||||||
graph.connectTo(whileStart);
|
graph.connectTo(whileStart);
|
||||||
graph.setNextLabel(false);
|
graph.setNextLabel(false);
|
||||||
|
graph.endBreakSection();
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,16 +75,19 @@ public class Visitador extends VoidVisitorAdapter<CFG> {
|
||||||
public void visit(DoStmt n, CFG graph) {
|
public void visit(DoStmt n, CFG graph) {
|
||||||
Node condition = n.getCondition();
|
Node condition = n.getCondition();
|
||||||
graph.beginBlock(n, condition);
|
graph.beginBlock(n, condition);
|
||||||
|
graph.beginBreakSection();
|
||||||
graph.appendNode(condition);
|
graph.appendNode(condition);
|
||||||
n.getBody().accept(this, graph);
|
n.getBody().accept(this, graph);
|
||||||
graph.connectTo(condition);
|
graph.connectTo(condition);
|
||||||
graph.setNextLabel(false);
|
graph.setNextLabel(false);
|
||||||
|
graph.endBreakSection();
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ForStmt n, CFG graph) {
|
public void visit(ForStmt n, CFG graph) {
|
||||||
graph.beginBlock(n, n.getCompare().orElse(null));
|
graph.beginBlock(n, n.getCompare().orElse(null));
|
||||||
|
graph.beginBreakSection();
|
||||||
// Initialization expressions
|
// Initialization expressions
|
||||||
if (n.getInitialization() != null) {
|
if (n.getInitialization() != null) {
|
||||||
for (Expression e : n.getInitialization()) {
|
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
|
// There is no comparison, can't exit the loop TODO implement break and continue as way to exit
|
||||||
graph.clearNode();
|
graph.clearNode();
|
||||||
}
|
}
|
||||||
|
graph.endBreakSection();
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +124,13 @@ public class Visitador extends VoidVisitorAdapter<CFG> {
|
||||||
public void visit(ForeachStmt n, CFG graph) {
|
public void visit(ForeachStmt n, CFG graph) {
|
||||||
ForeachStmt copy = new ForeachStmt(n.getTokenRange().orElse(null), n.getVariable(), n.getIterable(), new EmptyStmt());
|
ForeachStmt copy = new ForeachStmt(n.getTokenRange().orElse(null), n.getVariable(), n.getIterable(), new EmptyStmt());
|
||||||
graph.beginBlock(n, copy);
|
graph.beginBlock(n, copy);
|
||||||
|
graph.beginBreakSection();
|
||||||
graph.connectTo(copy);
|
graph.connectTo(copy);
|
||||||
graph.setNextLabel(true);
|
graph.setNextLabel(true);
|
||||||
n.getBody().accept(this, graph);
|
n.getBody().accept(this, graph);
|
||||||
graph.connectTo(copy);
|
graph.connectTo(copy);
|
||||||
graph.setNextLabel(false);
|
graph.setNextLabel(false);
|
||||||
|
graph.endBreakSection();
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,35 +148,29 @@ public class Visitador extends VoidVisitorAdapter<CFG> {
|
||||||
// Link previous statement to the switch's selector
|
// Link previous statement to the switch's selector
|
||||||
Node selectorNode = n.getSelector();
|
Node selectorNode = n.getSelector();
|
||||||
graph.beginBlock(n, selectorNode);
|
graph.beginBlock(n, selectorNode);
|
||||||
|
graph.beginBreakSection();
|
||||||
graph.connectTo(selectorNode);
|
graph.connectTo(selectorNode);
|
||||||
// Analyze switch's cases
|
// Analyze switch's cases
|
||||||
switchStack.push(n);
|
|
||||||
for (SwitchEntryStmt entry : n.getEntries()) {
|
for (SwitchEntryStmt entry : n.getEntries()) {
|
||||||
entry.accept(this, graph);
|
entry.accept(this, graph);
|
||||||
graph.appendNode(selectorNode);
|
graph.appendNode(selectorNode);
|
||||||
}
|
}
|
||||||
switchStack.pop();
|
|
||||||
// The next statement will be linked to:
|
// The next statement will be linked to:
|
||||||
// 1. All break statements that broke from the switch
|
// 1. All break statements that broke from the switch
|
||||||
// 2. If the switch doesn't have a default statement, the switch's selector
|
// 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
|
// 3. If the last entry doesn't break, to the last statement
|
||||||
graph.removeNode(selectorNode);
|
graph.removeNode(selectorNode);
|
||||||
graph.appendNodes(brokenStmts); // 1
|
|
||||||
brokenStmts.clear();
|
|
||||||
if (n.getEntries().get(n.getEntries().size() - 1).getLabel().isPresent())
|
if (n.getEntries().get(n.getEntries().size() - 1).getLabel().isPresent())
|
||||||
graph.appendNode(selectorNode); // 2
|
graph.appendNode(selectorNode);
|
||||||
|
graph.endBreakSection();
|
||||||
graph.endBlock();
|
graph.endBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BreakStmt n, CFG graph) {
|
public void visit(BreakStmt n, CFG graph) {
|
||||||
if (!switchStack.isEmpty() && !n.getLabel().isPresent()) {
|
|
||||||
graph.connectTo(n, false);
|
graph.connectTo(n, false);
|
||||||
brokenStmts.add(n);
|
|
||||||
graph.clearNode();
|
graph.clearNode();
|
||||||
return;
|
graph.registerBreak(n);
|
||||||
}
|
|
||||||
super.visit(n, graph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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