Code Should work now: P.S. Please god
This commit is contained in:
@@ -25,7 +25,6 @@ public class LCA_JP1_0_0 {
|
|||||||
System.out.println("Usage: java LCA_JP1_0_0 <JavaSourceFile>");
|
System.out.println("Usage: java LCA_JP1_0_0 <JavaSourceFile>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
System.out.println("WELCOME TO THE JUNGLE");
|
|
||||||
FileInputStream in = new FileInputStream(new File(args[0]));
|
FileInputStream in = new FileInputStream(new File(args[0]));
|
||||||
CompilationUnit cu = JavaParser.parse(in);
|
CompilationUnit cu = JavaParser.parse(in);
|
||||||
in.close();
|
in.close();
|
||||||
@@ -62,12 +61,12 @@ public class LCA_JP1_0_0 {
|
|||||||
visitBlockStmt(body);
|
visitBlockStmt(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect the last block to exit if not already connected
|
// Connect last block to exit if not already connected
|
||||||
if (currentBlock != null && currentBlock != exitNode) {
|
if (currentBlock != null && currentBlock != exitNode) {
|
||||||
addEdge(currentBlock, exitNode, "");
|
addEdge(currentBlock, exitNode, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
//new function Print CFG
|
// Print CFG
|
||||||
printCFG(n.getName());
|
printCFG(n.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +107,7 @@ public class LCA_JP1_0_0 {
|
|||||||
addEdge(currentBlock, exprNode, "");
|
addEdge(currentBlock, exprNode, "");
|
||||||
currentBlock = exprNode;
|
currentBlock = exprNode;
|
||||||
|
|
||||||
|
// Track constant like "int v = 5" or "v = 5"
|
||||||
String stmtStr = stmt.toString().trim();
|
String stmtStr = stmt.toString().trim();
|
||||||
if (stmtStr.contains("=") && !stmtStr.contains("==")) {
|
if (stmtStr.contains("=") && !stmtStr.contains("==")) {
|
||||||
try {
|
try {
|
||||||
@@ -126,8 +126,7 @@ public class LCA_JP1_0_0 {
|
|||||||
int value = Integer.parseInt(valuePart);
|
int value = Integer.parseInt(valuePart);
|
||||||
constantValues.put(varName, value);
|
constantValues.put(varName, value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// Not a constant, remove from tracking
|
constantValues.remove(varName); // Not a constant, remove from tracking
|
||||||
constantValues.remove(varName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -139,21 +138,16 @@ public class LCA_JP1_0_0 {
|
|||||||
private void visitIfStmt(IfStmt stmt) {
|
private void visitIfStmt(IfStmt stmt) {
|
||||||
// Evaluate condition if possible
|
// Evaluate condition if possible
|
||||||
String condStr = stmt.getCondition().toString();
|
String condStr = stmt.getCondition().toString();
|
||||||
String evaluatedCond = evaluateCondition(condStr);
|
String edgeLabel = evaluateConditionForEdge(condStr);
|
||||||
|
|
||||||
// Determine if condition is always true or false
|
// Create condition node
|
||||||
boolean alwaysTrue = evaluatedCond.contains("TRUE");
|
CFGNode condNode = new CFGNode("if (" + condStr + ")");
|
||||||
boolean alwaysFalse = evaluatedCond.contains("FALSE");
|
|
||||||
|
|
||||||
// Create condition node with evaluation result
|
|
||||||
CFGNode condNode = new CFGNode("if (" + condStr + ")" + evaluatedCond);
|
|
||||||
currCFG.addVertex(condNode);
|
currCFG.addVertex(condNode);
|
||||||
addEdge(currentBlock, condNode, "");
|
addEdge(currentBlock, condNode, "");
|
||||||
|
|
||||||
CFGNode mergeNode = new CFGNode("MERGE_IF");
|
CFGNode mergeNode = new CFGNode("MERGE_IF");
|
||||||
currCFG.addVertex(mergeNode);
|
currCFG.addVertex(mergeNode);
|
||||||
|
|
||||||
// Save the condition node to connect branches
|
|
||||||
CFGNode savedCond = condNode;
|
CFGNode savedCond = condNode;
|
||||||
|
|
||||||
// Then branch
|
// Then branch
|
||||||
@@ -163,22 +157,19 @@ public class LCA_JP1_0_0 {
|
|||||||
visitStatement(thenStmt);
|
visitStatement(thenStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect then branch to merge
|
|
||||||
CFGNode thenEnd = currentBlock;
|
CFGNode thenEnd = currentBlock;
|
||||||
if (thenEnd != null && thenEnd != savedCond) {
|
if (thenEnd != null && thenEnd != savedCond) {
|
||||||
addEdge(thenEnd, mergeNode, "");
|
addEdge(thenEnd, mergeNode, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add labeled edge from condition to then branch
|
// Label then branch edge if we evaluated it
|
||||||
// Show "T" when condition is ALWAYS TRUE
|
if (!edgeLabel.isEmpty()) {
|
||||||
if (alwaysTrue) {
|
|
||||||
// Find the edge to the then branch and label it
|
|
||||||
Set<CFGEdge> edges = new HashSet<CFGEdge>(currCFG.outgoingEdgesOf(savedCond));
|
Set<CFGEdge> edges = new HashSet<CFGEdge>(currCFG.outgoingEdgesOf(savedCond));
|
||||||
for (CFGEdge e : edges) {
|
for (CFGEdge e : edges) {
|
||||||
CFGNode target = currCFG.getEdgeTarget(e);
|
CFGNode target = currCFG.getEdgeTarget(e);
|
||||||
if (target != mergeNode) {
|
if (target != mergeNode) {
|
||||||
currCFG.removeEdge(e);
|
currCFG.removeEdge(e);
|
||||||
addEdge(savedCond, target, "T");
|
addEdge(savedCond, target, edgeLabel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,35 +184,15 @@ public class LCA_JP1_0_0 {
|
|||||||
if (elseEnd != null && elseEnd != savedCond) {
|
if (elseEnd != null && elseEnd != savedCond) {
|
||||||
addEdge(elseEnd, mergeNode, "");
|
addEdge(elseEnd, mergeNode, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add labeled edge from condition to else branch
|
|
||||||
// Show "F" when condition is ALWAYS FALSE
|
|
||||||
if (alwaysFalse) {
|
|
||||||
Set<CFGEdge> edges = new HashSet<CFGEdge>(currCFG.outgoingEdgesOf(savedCond));
|
|
||||||
for (CFGEdge e : edges) {
|
|
||||||
CFGNode target = currCFG.getEdgeTarget(e);
|
|
||||||
if (target != mergeNode && e.getLabel() == null) {
|
|
||||||
currCFG.removeEdge(e);
|
|
||||||
addEdge(savedCond, target, "F");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Normal case - else gets F label
|
|
||||||
addEdge(savedCond, mergeNode, "F");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// No else branch - always label this F
|
|
||||||
addEdge(savedCond, mergeNode, "F");
|
addEdge(savedCond, mergeNode, "F");
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBlock = mergeNode;
|
currentBlock = mergeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *** CHANGE 4: NEW METHOD - Evaluate condition based on tracked constant values ***
|
private String evaluateConditionForEdge(String condition) {
|
||||||
private String evaluateCondition(String condition) {
|
|
||||||
try {
|
try {
|
||||||
// Handle simple comparisons like "v == 5", "v > 5", "v < 5"
|
|
||||||
String[] operators = {"==", "!=", ">=", "<=", ">", "<"};
|
String[] operators = {"==", "!=", ">=", "<=", ">", "<"};
|
||||||
|
|
||||||
for (String op : operators) {
|
for (String op : operators) {
|
||||||
@@ -231,27 +202,19 @@ public class LCA_JP1_0_0 {
|
|||||||
String leftStr = parts[0].trim();
|
String leftStr = parts[0].trim();
|
||||||
String rightStr = parts[1].trim();
|
String rightStr = parts[1].trim();
|
||||||
|
|
||||||
Integer leftVal = null;
|
Integer leftVal = constantValues.get(leftStr);
|
||||||
Integer rightVal = null;
|
Integer rightVal = constantValues.get(rightStr);
|
||||||
|
|
||||||
// Try to get value from constants map or parse directly
|
if (leftVal == null) {
|
||||||
if (constantValues.containsKey(leftStr)) {
|
try { leftVal = Integer.parseInt(leftStr); }
|
||||||
leftVal = constantValues.get(leftStr);
|
catch (NumberFormatException e) {}
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
leftVal = Integer.parseInt(leftStr);
|
|
||||||
} catch (NumberFormatException e) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constantValues.containsKey(rightStr)) {
|
if (rightVal == null) {
|
||||||
rightVal = constantValues.get(rightStr);
|
try { rightVal = Integer.parseInt(rightStr); }
|
||||||
} else {
|
catch (NumberFormatException e) {}
|
||||||
try {
|
|
||||||
rightVal = Integer.parseInt(rightStr);
|
|
||||||
} catch (NumberFormatException e) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have both values, evaluate
|
|
||||||
if (leftVal != null && rightVal != null) {
|
if (leftVal != null && rightVal != null) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
if (op.equals("==")) result = leftVal.equals(rightVal);
|
if (op.equals("==")) result = leftVal.equals(rightVal);
|
||||||
@@ -261,16 +224,14 @@ public class LCA_JP1_0_0 {
|
|||||||
else if (op.equals(">=")) result = leftVal >= rightVal;
|
else if (op.equals(">=")) result = leftVal >= rightVal;
|
||||||
else if (op.equals("<=")) result = leftVal <= rightVal;
|
else if (op.equals("<=")) result = leftVal <= rightVal;
|
||||||
|
|
||||||
return " [ALWAYS " + (result ? "TRUE" : "FALSE") + "]";
|
return result ? "T" : "F";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break; // Found operator, don't check others
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {}
|
||||||
// Evaluation failed
|
return "";
|
||||||
}
|
|
||||||
return ""; // Cannot determine
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitForStmt(ForStmt stmt) {
|
private void visitForStmt(ForStmt stmt) {
|
||||||
@@ -382,35 +343,27 @@ public class LCA_JP1_0_0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void printCFG(String methodName) {
|
private void printCFG(String methodName) {
|
||||||
// Grammar: "CFG" SPACE GraphName ":" NEWLINE
|
|
||||||
System.out.print("CFG ");
|
System.out.print("CFG ");
|
||||||
System.out.print(methodName);
|
System.out.print(methodName);
|
||||||
System.out.print(":");
|
System.out.print(":");
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
// Get all vertices and sort by ID
|
|
||||||
Set<CFGNode> vertexSet = currCFG.vertexSet();
|
Set<CFGNode> vertexSet = currCFG.vertexSet();
|
||||||
List<CFGNode> nodes = new ArrayList<CFGNode>(vertexSet);
|
List<CFGNode> nodes = new ArrayList<CFGNode>(vertexSet);
|
||||||
|
|
||||||
// Sort nodes by ID
|
|
||||||
Collections.sort(nodes, new Comparator<CFGNode>() {
|
Collections.sort(nodes, new Comparator<CFGNode>() {
|
||||||
public int compare(CFGNode n1, CFGNode n2) {
|
public int compare(CFGNode n1, CFGNode n2) {
|
||||||
return n1.getID() - n2.getID();
|
return n1.getID() - n2.getID();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Grammar: (SPACE SPACE SPACE SPACE Node NEWLINE)*
|
|
||||||
for (CFGNode node : nodes) {
|
for (CFGNode node : nodes) {
|
||||||
// Four spaces
|
System.out.print("\t");
|
||||||
System.out.print(" ");
|
|
||||||
// "node" SPACE IDENTIFIER ":" LABEL SPACE
|
|
||||||
System.out.print("node ");
|
System.out.print("node ");
|
||||||
System.out.print(node.getID());
|
System.out.print(node.getID());
|
||||||
System.out.print(": ");
|
System.out.print(": ");
|
||||||
System.out.print(node.getLabel());
|
System.out.print(node.getLabel());
|
||||||
System.out.print(" ");
|
System.out.print(" ");
|
||||||
|
|
||||||
// ("edge" SPACE LABEL SPACE IDENTIFIER ";" SPACE)*
|
|
||||||
Set<CFGEdge> outEdges = currCFG.outgoingEdgesOf(node);
|
Set<CFGEdge> outEdges = currCFG.outgoingEdgesOf(node);
|
||||||
for (CFGEdge edge : outEdges) {
|
for (CFGEdge edge : outEdges) {
|
||||||
CFGNode target = currCFG.getEdgeTarget(edge);
|
CFGNode target = currCFG.getEdgeTarget(edge);
|
||||||
|
|||||||
@@ -1,5 +1,28 @@
|
|||||||
# How shalt thou compile, with patience and practice
|
# How shalt thou compile, with patience and practice
|
||||||
1. Compile thy code
|
1. Compile thy code
|
||||||
`javac -cp .:javaparser-1.0.0.jar:./lib/jgrapht-core-1.5.2.jar:./lib/jgrapht-io-1.5.2.jar:./lib/apfloat-1.10.1.jar:./lib/jheaps-0.14.jar CFGGraph/*.java LCA_JP1_0_0.java`
|
`javac -cp .:javaparser-1.0.0.jar:./lib/jgrapht-core-1.5.2.jar:./lib/jgrapht-io-1.5.2.jar:./lib/apfloat-1.10.1.jar:./lib/jheaps-0.14.jar CFGGraph/*.java LCA_JP1_0_0.java`
|
||||||
|
|
||||||
|
`javac -cp .:javaparser-1.0.0.jar:./lib/* CFGGraph/*.java LCA_JP1_0_0.java`
|
||||||
2. Now move forth to victory
|
2. Now move forth to victory
|
||||||
`java -cp .:javaparser-1.0.0.jar:./lib/jgrapht-core-1.5.2.jar:./lib/jgrapht-io-1.5.2.jar:./lib/apfloat-1.10.1.jar:./lib/jheaps-0.14.jar LCA_JP1_0_0 Test.java`
|
`java -cp .:javaparser-1.0.0.jar:./lib/jgrapht-core-1.5.2.jar:./lib/jgrapht-io-1.5.2.jar:./lib/ apfloat-1.10.1.jar:./lib/jheaps-0.14.jar LCA_JP1_0_0 Test.java`
|
||||||
|
|
||||||
|
`java -cp .:javaparser-1.0.0.jar:./lib/* LCA_JP1_0_0 Test.java`
|
||||||
|
3. PS: On Windows, replace `:` with `;` and `/` with `\` in paths
|
||||||
|
|
||||||
|
|
||||||
|
Node 1 (ENTRY): Created FIRST, so it gets ID = 1
|
||||||
|
Node 2 (EXIT): Created SECOND, so it gets ID = 2
|
||||||
|
Then we build the rest of the method body starting from node 3
|
||||||
|
|
||||||
|
Why we need them:
|
||||||
|
ENTRY marks where the method starts (before any code executes)
|
||||||
|
EXIT marks where the method ends (after return statements)
|
||||||
|
Helps with analysis - clear start/end points for control flow
|
||||||
|
```java
|
||||||
|
if (val == 5) { // node 8
|
||||||
|
val = 6; // node 10
|
||||||
|
} // node 9: MERGE_IF
|
||||||
|
```
|
||||||
|
**Node 9 (MERGE_IF) → edge 14**:
|
||||||
|
- Node 9 is where the FIRST if statement merges (after `val = 6;`)
|
||||||
|
- After the merge, control flow continues to the NEXT statement
|
||||||
|
|||||||
Reference in New Issue
Block a user