diff --git a/.DS_Store b/.DS_Store index b17109b..260e73f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Assignment-3 Reformated.zip b/Assignment-3 Reformated.zip new file mode 100644 index 0000000..108d778 Binary files /dev/null and b/Assignment-3 Reformated.zip differ diff --git a/Assignment-3 Reformated/CFGGraph/CFGEdge.class b/Assignment-3 Reformated/CFGGraph/CFGEdge.class new file mode 100644 index 0000000..c0f50d4 Binary files /dev/null and b/Assignment-3 Reformated/CFGGraph/CFGEdge.class differ diff --git a/Assignment-3 Reformated/CFGGraph/CFGEdge.java b/Assignment-3 Reformated/CFGGraph/CFGEdge.java new file mode 100644 index 0000000..9454e80 --- /dev/null +++ b/Assignment-3 Reformated/CFGGraph/CFGEdge.java @@ -0,0 +1,42 @@ +package CFGGraph; +import org.jgrapht.graph.DefaultEdge; + +public class CFGEdge extends DefaultEdge { + //path defines if its a True or False or Null (when either T or F resulkt on the same node) + private boolean path; + private CFGNode from; + private CFGNode to; + private String label; + + public CFGEdge() { + this(null, null); + } + public CFGEdge(CFGNode from, CFGNode to) { + this.from = from; + this.to = to; + this.label = ""; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getLabel() { + return this.label; + } + + public CFGNode getFrom() { + return this.from; + } + + public CFGNode getTo() { + return this.to; + } + + @Override + public String toString() { + return label; + } + + public void setPath(boolean path) { this.path = path; } +} \ No newline at end of file diff --git a/Assignment-3 Reformated/CFGGraph/CFGNode.class b/Assignment-3 Reformated/CFGGraph/CFGNode.class new file mode 100644 index 0000000..bcb40a8 Binary files /dev/null and b/Assignment-3 Reformated/CFGGraph/CFGNode.class differ diff --git a/Assignment-3 Reformated/CFGGraph/CFGNode.java b/Assignment-3 Reformated/CFGGraph/CFGNode.java new file mode 100644 index 0000000..250b8ce --- /dev/null +++ b/Assignment-3 Reformated/CFGGraph/CFGNode.java @@ -0,0 +1,41 @@ +package CFGGraph; +import java.util.ArrayList; + +import japa.parser.ast.stmt.Statement; + +public class CFGNode { + + static int id_counter = 1; + private final int ID; + private String label; + private ArrayList statements; + + + public CFGNode(String label) { + this.label = label; + this.ID = id_counter++; + this.statements = new ArrayList<>(); + } + + public int getID() { + return this.ID; + } + + public String getLabel() { + return this.label; + } + + public ArrayList getStatements() { + return this.statements; + } + + public void addStatement(Statement s) { + statements.add(s); + } + + @Override + public String toString() { + return label; + } + +} \ No newline at end of file diff --git a/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor$1.class b/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor$1.class new file mode 100644 index 0000000..253ba70 Binary files /dev/null and b/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor$1.class differ diff --git a/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor.class b/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor.class new file mode 100644 index 0000000..3239c86 Binary files /dev/null and b/Assignment-3 Reformated/LCA_JP1_0_0$CFGVisitor.class differ diff --git a/Assignment-3 Reformated/LCA_JP1_0_0.class b/Assignment-3 Reformated/LCA_JP1_0_0.class new file mode 100644 index 0000000..2e1551c Binary files /dev/null and b/Assignment-3 Reformated/LCA_JP1_0_0.class differ diff --git a/Assignment-3 Reformated/LCA_JP1_0_0.java b/Assignment-3 Reformated/LCA_JP1_0_0.java new file mode 100644 index 0000000..421f11e --- /dev/null +++ b/Assignment-3 Reformated/LCA_JP1_0_0.java @@ -0,0 +1,431 @@ +import japa.parser.JavaParser; +import japa.parser.ast.CompilationUnit; +import japa.parser.ast.body.*; +import japa.parser.ast.visitor.VoidVisitorAdapter; +import japa.parser.ast.stmt.*; +import japa.parser.ast.expr.*; + +import java.io.FileInputStream; +import java.io.File; + +//graph imports +import org.jgrapht.*; +import org.jgrapht.graph.*; + +import java.io.*; +import java.util.*; + +import CFGGraph.CFGNode; +import CFGGraph.CFGEdge; + +public class LCA_JP1_0_0 { + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + System.out.println("Usage: java LCA_JP1_0_0 "); + return; + } + System.out.println("WELCOME TO THE JUNGLE"); + FileInputStream in = new FileInputStream(new File(args[0])); + CompilationUnit cu = JavaParser.parse(in); + in.close(); + + CFGVisitor visitor = new CFGVisitor(); + visitor.visit(cu, null); + } + + static class CFGVisitor extends VoidVisitorAdapter { + private Graph currCFG; + private CFGNode currentBlock; + private CFGNode entryNode; + private CFGNode exitNode; + private Map constantValues; + public void visit(MethodDeclaration n, Void arg) { + // Initialize new CFG for this method + currCFG = new DefaultDirectedGraph<>(CFGEdge.class); + constantValues = new HashMap(); + + // Create entry and exit nodes + entryNode = new CFGNode("ENTRY_" + n.getName()); + exitNode = new CFGNode("EXIT_" + n.getName()); + + currCFG.addVertex(entryNode); + currCFG.addVertex(exitNode); + + System.out.println("CFG Building Root: " + n.getName()); + + currentBlock = entryNode; + + // Visit method body + BlockStmt body = n.getBody(); + if (body != null) { + visitBlockStmt(body); + } + + // Connect the last block to exit if not already connected + if (currentBlock != null && currentBlock != exitNode) { + addEdge(currentBlock, exitNode, ""); + } + + //new function Print CFG + printCFG(n.getName()); + } + + private void visitBlockStmt(BlockStmt block) { + List stmts = block.getStmts(); + if (stmts == null) return; + + for (Statement stmt : stmts) { + visitStatement(stmt); + } + } + + private void visitStatement(Statement stmt) { + if (stmt instanceof ExpressionStmt) { + visitExpressionStmt((ExpressionStmt) stmt); + } else if (stmt instanceof IfStmt) { + visitIfStmt((IfStmt) stmt); + } else if (stmt instanceof ForStmt) { + visitForStmt((ForStmt) stmt); + } else if (stmt instanceof WhileStmt) { + visitWhileStmt((WhileStmt) stmt); + } else if (stmt instanceof ReturnStmt) { + visitReturnStmt((ReturnStmt) stmt); + } else if (stmt instanceof BlockStmt) { + visitBlockStmt((BlockStmt) stmt); + } else { + // Handle other statement types generically + CFGNode stmtNode = new CFGNode(stmt.toString().trim()); + currCFG.addVertex(stmtNode); + addEdge(currentBlock, stmtNode, ""); + currentBlock = stmtNode; + } + } + + private void visitExpressionStmt(ExpressionStmt stmt) { + CFGNode exprNode = new CFGNode(stmt.toString().trim()); + currCFG.addVertex(exprNode); + addEdge(currentBlock, exprNode, ""); + currentBlock = exprNode; + + String stmtStr = stmt.toString().trim(); + if (stmtStr.contains("=") && !stmtStr.contains("==")) { + try { + // Simple pattern: extract variable and value + String[] parts = stmtStr.split("="); + if (parts.length == 2) { + String varPart = parts[0].trim(); + String valuePart = parts[1].trim().replace(";", "").trim(); + + // Get variable name (handle "int v" or just "v") + String[] varTokens = varPart.split("\\s+"); + String varName = varTokens[varTokens.length - 1]; + + // Try to parse the value as integer + try { + int value = Integer.parseInt(valuePart); + constantValues.put(varName, value); + } catch (NumberFormatException e) { + // Not a constant, remove from tracking + constantValues.remove(varName); + } + } + } catch (Exception e) { + // Parsing failed, ignore + } + } + } + + private void visitIfStmt(IfStmt stmt) { + // Evaluate condition if possible + String condStr = stmt.getCondition().toString(); + String evaluatedCond = evaluateCondition(condStr); + + // Determine if condition is always true or false + boolean alwaysTrue = evaluatedCond.contains("TRUE"); + boolean alwaysFalse = evaluatedCond.contains("FALSE"); + + // Create condition node with evaluation result + CFGNode condNode = new CFGNode("if (" + condStr + ")" + evaluatedCond); + currCFG.addVertex(condNode); + addEdge(currentBlock, condNode, ""); + + CFGNode mergeNode = new CFGNode("MERGE_IF"); + currCFG.addVertex(mergeNode); + + // Save the condition node to connect branches + CFGNode savedCond = condNode; + + // Then branch + currentBlock = condNode; + Statement thenStmt = stmt.getThenStmt(); + if (thenStmt != null) { + visitStatement(thenStmt); + } + + // Connect then branch to merge + CFGNode thenEnd = currentBlock; + if (thenEnd != null && thenEnd != savedCond) { + addEdge(thenEnd, mergeNode, ""); + } + + // Add labeled edge from condition to then branch + // Show "T" when condition is ALWAYS TRUE + if (alwaysTrue) { + // Find the edge to the then branch and label it + Set edges = new HashSet(currCFG.outgoingEdgesOf(savedCond)); + for (CFGEdge e : edges) { + CFGNode target = currCFG.getEdgeTarget(e); + if (target != mergeNode) { + currCFG.removeEdge(e); + addEdge(savedCond, target, "T"); + break; + } + } + } + + // Else branch + currentBlock = savedCond; + Statement elseStmt = stmt.getElseStmt(); + if (elseStmt != null) { + visitStatement(elseStmt); + CFGNode elseEnd = currentBlock; + if (elseEnd != null && elseEnd != savedCond) { + addEdge(elseEnd, mergeNode, ""); + } + + // Add labeled edge from condition to else branch + // Show "F" when condition is ALWAYS FALSE + if (alwaysFalse) { + Set edges = new HashSet(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 { + // No else branch - always label this F + addEdge(savedCond, mergeNode, "F"); + } + + currentBlock = mergeNode; + } + + // *** CHANGE 4: NEW METHOD - Evaluate condition based on tracked constant values *** + private String evaluateCondition(String condition) { + try { + // Handle simple comparisons like "v == 5", "v > 5", "v < 5" + String[] operators = {"==", "!=", ">=", "<=", ">", "<"}; + + for (String op : operators) { + if (condition.contains(op)) { + String[] parts = condition.split(op); + if (parts.length == 2) { + String leftStr = parts[0].trim(); + String rightStr = parts[1].trim(); + + Integer leftVal = null; + Integer rightVal = null; + + // Try to get value from constants map or parse directly + if (constantValues.containsKey(leftStr)) { + leftVal = constantValues.get(leftStr); + } else { + try { + leftVal = Integer.parseInt(leftStr); + } catch (NumberFormatException e) {} + } + + if (constantValues.containsKey(rightStr)) { + rightVal = constantValues.get(rightStr); + } else { + try { + rightVal = Integer.parseInt(rightStr); + } catch (NumberFormatException e) {} + } + + // If we have both values, evaluate + if (leftVal != null && rightVal != null) { + boolean result = false; + if (op.equals("==")) result = leftVal.equals(rightVal); + else if (op.equals("!=")) result = !leftVal.equals(rightVal); + 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") + "]"; + } + } + break; // Found operator, don't check others + } + } + } catch (Exception e) { + // Evaluation failed + } + return ""; // Cannot determine + } + + private void visitForStmt(ForStmt stmt) { + // Initialization + List inits = stmt.getInit(); + if (inits != null && !inits.isEmpty()) { + for (Expression init : inits) { + CFGNode initNode = new CFGNode(init.toString()); + currCFG.addVertex(initNode); + addEdge(currentBlock, initNode, ""); + currentBlock = initNode; + } + } + + // Condition node + Expression compare = stmt.getCompare(); + String condStr = compare != null ? compare.toString() : "true"; + CFGNode condNode = new CFGNode("for (" + condStr + ")"); + currCFG.addVertex(condNode); + addEdge(currentBlock, condNode, ""); + + CFGNode exitLoopNode = new CFGNode("EXIT_FOR"); + currCFG.addVertex(exitLoopNode); + + // Save condition node + CFGNode savedCond = condNode; + + // Loop body + CFGNode bodyEntry = null; + Statement body = stmt.getBody(); + if (body != null) { + currentBlock = condNode; + visitStatement(body); + bodyEntry = currentBlock; + } + + // Update expressions + List updates = stmt.getUpdate(); + if (updates != null && !updates.isEmpty()) { + for (Expression update : updates) { + CFGNode updateNode = new CFGNode(update.toString()); + currCFG.addVertex(updateNode); + addEdge(currentBlock, updateNode, ""); + currentBlock = updateNode; + } + } + + // Back edge to condition + addEdge(currentBlock, savedCond, ""); + + // True edge from condition to body (will be added via body visit) + // False edge from condition to exit + addEdge(savedCond, exitLoopNode, "F"); + + currentBlock = exitLoopNode; + } + + private void visitWhileStmt(WhileStmt stmt) { + // Condition node + CFGNode condNode = new CFGNode("while (" + stmt.getCondition() + ")"); + currCFG.addVertex(condNode); + addEdge(currentBlock, condNode, ""); + + CFGNode exitLoopNode = new CFGNode("EXIT_WHILE"); + currCFG.addVertex(exitLoopNode); + + CFGNode savedCond = condNode; + + // Loop body + currentBlock = condNode; + Statement body = stmt.getBody(); + if (body != null) { + visitStatement(body); + } + + // Back edge to condition + addEdge(currentBlock, savedCond, ""); + + // True edge through body (added via visit) + // False edge to exit + addEdge(savedCond, exitLoopNode, "F"); + + currentBlock = exitLoopNode; + } + + private void visitReturnStmt(ReturnStmt stmt) { + Expression expr = stmt.getExpr(); + String returnStr = "return" + (expr != null ? " " + expr.toString() : ""); + CFGNode returnNode = new CFGNode(returnStr); + currCFG.addVertex(returnNode); + addEdge(currentBlock, returnNode, ""); + addEdge(returnNode, exitNode, ""); + currentBlock = null; // No more statements should follow + } + + private void addEdge(CFGNode from, CFGNode to, String label) { + if (from == null || to == null) return; + + CFGEdge edge = new CFGEdge(from, to); + if (label != null && label.length() > 0) { + edge.setLabel(label); + } + + try { + currCFG.addEdge(from, to, edge); + } catch (IllegalArgumentException e) { + // Edge already exists, ignore + } + } + + private void printCFG(String methodName) { + // Grammar: "CFG" SPACE GraphName ":" NEWLINE + System.out.print("CFG "); + System.out.print(methodName); + System.out.print(":"); + System.out.println(); + + // Get all vertices and sort by ID + Set vertexSet = currCFG.vertexSet(); + List nodes = new ArrayList(vertexSet); + + // Sort nodes by ID + Collections.sort(nodes, new Comparator() { + public int compare(CFGNode n1, CFGNode n2) { + return n1.getID() - n2.getID(); + } + }); + + // Grammar: (SPACE SPACE SPACE SPACE Node NEWLINE)* + for (CFGNode node : nodes) { + // Four spaces + System.out.print(" "); + // "node" SPACE IDENTIFIER ":" LABEL SPACE + System.out.print("node "); + System.out.print(node.getID()); + System.out.print(": "); + System.out.print(node.getLabel()); + System.out.print(" "); + + // ("edge" SPACE LABEL SPACE IDENTIFIER ";" SPACE)* + Set outEdges = currCFG.outgoingEdgesOf(node); + for (CFGEdge edge : outEdges) { + CFGNode target = currCFG.getEdgeTarget(edge); + String edgeLabel = edge.getLabel(); + if (edgeLabel == null) { + edgeLabel = ""; + } + System.out.print("edge "); + System.out.print(edgeLabel); + System.out.print(" "); + System.out.print(target.getID()); + System.out.print("; "); + } + System.out.println(); + } + } + } +} \ No newline at end of file diff --git a/Assignment-3 Reformated/Readme.md b/Assignment-3 Reformated/Readme.md new file mode 100644 index 0000000..f00c35a --- /dev/null +++ b/Assignment-3 Reformated/Readme.md @@ -0,0 +1,5 @@ +# How shalt thou compile, with patience and practice +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` +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` diff --git a/Assignment-3 Reformated/T b/Assignment-3 Reformated/T new file mode 100644 index 0000000..e69de29 diff --git a/Assignment-3 Reformated/Test.java b/Assignment-3 Reformated/Test.java new file mode 100644 index 0000000..6cfb155 --- /dev/null +++ b/Assignment-3 Reformated/Test.java @@ -0,0 +1,24 @@ +public class Test { + public int methodForLoop() { + int val = 1; + + for (int i = 0; i < 10; i++) { + val += 1; + if (val == 5) { + val = 5; + val = 6; + } else if(val < 5) { + val = 3; + } + if(1 == 1 && 2 == 2) {return 0;} else {return 1;} + + + } + return val; + } + + int result = this.methodForLoop(); + + + +} \ No newline at end of file diff --git a/Assignment-3 Reformated/javaparser-1.0.0.jar b/Assignment-3 Reformated/javaparser-1.0.0.jar new file mode 100644 index 0000000..4c6006a Binary files /dev/null and b/Assignment-3 Reformated/javaparser-1.0.0.jar differ diff --git a/Assignment-3 Reformated/lib/apfloat-1.10.1-javadoc.jar b/Assignment-3 Reformated/lib/apfloat-1.10.1-javadoc.jar new file mode 100644 index 0000000..6e86282 Binary files /dev/null and b/Assignment-3 Reformated/lib/apfloat-1.10.1-javadoc.jar differ diff --git a/Assignment-3 Reformated/lib/apfloat-1.10.1.jar b/Assignment-3 Reformated/lib/apfloat-1.10.1.jar new file mode 100644 index 0000000..9958619 Binary files /dev/null and b/Assignment-3 Reformated/lib/apfloat-1.10.1.jar differ diff --git a/Assignment-3 Reformated/lib/jgrapht-core-1.5.2-javadoc.jar b/Assignment-3 Reformated/lib/jgrapht-core-1.5.2-javadoc.jar new file mode 100644 index 0000000..3f9dc5b Binary files /dev/null and b/Assignment-3 Reformated/lib/jgrapht-core-1.5.2-javadoc.jar differ diff --git a/Assignment-3 Reformated/lib/jgrapht-core-1.5.2.jar b/Assignment-3 Reformated/lib/jgrapht-core-1.5.2.jar new file mode 100644 index 0000000..8283b35 Binary files /dev/null and b/Assignment-3 Reformated/lib/jgrapht-core-1.5.2.jar differ diff --git a/Assignment-3 Reformated/lib/jgrapht-io-1.5.2.jar b/Assignment-3 Reformated/lib/jgrapht-io-1.5.2.jar new file mode 100644 index 0000000..c444182 Binary files /dev/null and b/Assignment-3 Reformated/lib/jgrapht-io-1.5.2.jar differ diff --git a/Assignment-3 Reformated/lib/jheaps-0.14-javadoc.jar b/Assignment-3 Reformated/lib/jheaps-0.14-javadoc.jar new file mode 100644 index 0000000..863c71d Binary files /dev/null and b/Assignment-3 Reformated/lib/jheaps-0.14-javadoc.jar differ diff --git a/Assignment-3 Reformated/lib/jheaps-0.14.jar b/Assignment-3 Reformated/lib/jheaps-0.14.jar new file mode 100644 index 0000000..a0f0c23 Binary files /dev/null and b/Assignment-3 Reformated/lib/jheaps-0.14.jar differ diff --git a/Assignment-3/javaparser-1.0.0/LCA_JP1_0_0.java b/Assignment-3/javaparser-1.0.0/LCA_JP1_0_0.java index 9e5319d..0ea3766 100644 --- a/Assignment-3/javaparser-1.0.0/LCA_JP1_0_0.java +++ b/Assignment-3/javaparser-1.0.0/LCA_JP1_0_0.java @@ -1,24 +1,19 @@ -import java.io.FileInputStream; -import java.io.File; -import java.beans.Expression; -import java.io.*; -import java.net.*; -import java.util.*; - import japa.parser.JavaParser; import japa.parser.ast.CompilationUnit; import japa.parser.ast.body.*; import japa.parser.ast.visitor.VoidVisitorAdapter; -import japa.parser.ast.stmt.ExpressionStmt; -import japa.parser.ast.body.*; import japa.parser.ast.stmt.*; import japa.parser.ast.expr.*; +import java.io.FileInputStream; +import java.io.File; + +//graph imports import org.jgrapht.*; import org.jgrapht.graph.*; -import org.jgrapht.nio.*; -import org.jgrapht.nio.dot.*; -import org.jgrapht.traverse.*; + +import java.io.*; +import java.util.*; import CFGGraph.CFGNode; import CFGGraph.CFGEdge; @@ -294,4 +289,4 @@ public class LCA_JP1_0_0 { System.out.println(); } } -}} \ No newline at end of file +} \ No newline at end of file