Visitor: implemented any possible breakStmt

This commit is contained in:
Carlos Galindo 2019-04-04 17:14:14 +02:00
parent 47bff81942
commit 96847b7a8a
Signed by untrusted user who does not match committer: kauron
GPG Key ID: 83E68706DEE119A3
3 changed files with 67 additions and 17 deletions

View File

@ -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());

View File

@ -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

View 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++;
}
}
}