diff --git a/tools/fxtran-parser/.gitignore b/tools/fxtran-parser/.gitignore deleted file mode 100644 index b2516d8c6138ca12aa517664f6e71d827b6fe6da..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.gradle/ -build diff --git a/tools/fxtran-parser/build.gradle b/tools/fxtran-parser/build.gradle deleted file mode 100644 index 864c8f446221a958983ad4654fcf0ceb2df23b33..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/build.gradle +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * This generated file contains a sample Java application project to get you started. - * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle - * User Manual available at https://docs.gradle.org/7.2/userguide/building_java_projects.html - */ - -plugins { - id 'com.github.johnrengelman.shadow' version '7.1.1' - id 'java' - id 'application' -} - -// from https://discuss.gradle.org/t/dependency-local-project-or-external-jar/6722/2 -// extended so that we can configure "force use" of the library by creating a -// file with a corresponding name. This can be used for testing, but mainly is -// to be required in docker since the "detect local copy of datastructure-utils" -// seems to produce a "false positive" (probably since the root folder is the -// root -project.ext.localRemote = { aProjectName -> - if(rootProject.file('./force-use-library-' + aProjectName).exists()) { - project.logger.lifecycle('ignoring local copies of ' + aProjectName) - dependencies.create files('libs/'+aProjectName+'.jar') - } - else { - if(rootProject.file('../' + aProjectName).exists()) { - project.logger.lifecycle('found ' + aProjectName + ' locally.') - dependencies.create project(':'+aProjectName) - dependencies.create files('libs/'+aProjectName+'.jar') - } else { - project.logger.lifecycle('did not find ' + aProjectName + ' locally, using library.') - dependencies.create files('libs/'+aProjectName+'.jar') - } - } - } - - -sourceCompatibility = '1.17' - - -repositories { - mavenCentral() - mavenLocal() - maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } - maven { url "https://oss.sonatype.org/content/repositories/releases/" } -} - -dependencies { - testImplementation 'junit:junit:4.13.2' - - implementation 'junit:junit:4.13.2' - - implementation 'com.google.guava:guava:30.1.1-jre' - - compileOnly 'org.projectlombok:lombok:1.18.20' - annotationProcessor 'org.projectlombok:lombok:1.18.20' - - testCompileOnly 'org.projectlombok:lombok:1.18.20' - testAnnotationProcessor 'org.projectlombok:lombok:1.18.20' - - //implementation project(':datastructure-utils') - implementation localRemote('datastructure-utils') - implementation files('libs/common-1.3.0-SNAPSHOT.jar') // implementation 'org.oceandsl:common:1.3.0-SNAPSHOT' - implementation files('libs/analysis-1.3.0-SNAPSHOT.jar')// implementation 'org.oceandsl:analysis:1.3.0-SNAPSHOT' - - implementation 'org.apache.commons:commons-csv:1.9.0' - implementation 'org.apache.commons:commons-collections4:4.4' - implementation 'org.apache.commons:commons-lang3:3.12.0' - implementation 'net.sourceforge.teetime:teetime:3.1-SNAPSHOT' - implementation 'net.kieker-monitoring:kieker:2.0.0-SNAPSHOT' - implementation 'org.eclipse.emf:org.eclipse.emf.ecore:2.23.0' - implementation 'org.eclipse.emf:org.eclipse.emf.ecore.xmi:2.16.0' - implementation group: 'org.apache.commons', name:'commons-lang3', version:'3.9' - implementation 'commons-io:commons-io:2.11.0' - implementation group: 'org.apache.ant', name:'ant', version: '1.8.2' -} - -shadowJar { - archiveBaseName.set('shadow') - archiveClassifier.set('') - archiveVersion.set('') -} - -jar { - manifest { - attributes "Main-Class": 'cau.agse.hs.staticfortran.main.ParseXML' - } -} - -mainClassName = 'cau/agse/hs/staticfortran/main/ParseXML' diff --git a/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.jar b/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..0000000000000000000000000000000000000000 Binary files a/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.properties b/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index aa991fceae6e464c320a107e4b337daf48c0d7ab..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/tools/fxtran-parser/libs/analysis-1.3.0-SNAPSHOT.jar b/tools/fxtran-parser/libs/analysis-1.3.0-SNAPSHOT.jar deleted file mode 100644 index 7d810991a0c4dda10904c7d0ac5c6d4442f34a14..0000000000000000000000000000000000000000 Binary files a/tools/fxtran-parser/libs/analysis-1.3.0-SNAPSHOT.jar and /dev/null differ diff --git a/tools/fxtran-parser/libs/common-1.3.0-SNAPSHOT.jar b/tools/fxtran-parser/libs/common-1.3.0-SNAPSHOT.jar deleted file mode 100644 index c361b8e212b70fdbed6807c2977b2c5701b284ff..0000000000000000000000000000000000000000 Binary files a/tools/fxtran-parser/libs/common-1.3.0-SNAPSHOT.jar and /dev/null differ diff --git a/tools/fxtran-parser/libs/datastructure-utils.jar b/tools/fxtran-parser/libs/datastructure-utils.jar deleted file mode 100644 index 99b1b7d9843a8ead0852e1b6375c4d7fd63e8d26..0000000000000000000000000000000000000000 Binary files a/tools/fxtran-parser/libs/datastructure-utils.jar and /dev/null differ diff --git a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/main/ParseXML.java b/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/main/ParseXML.java deleted file mode 100644 index 6868694dc823c26efa12885486443d1ee754e3de..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/main/ParseXML.java +++ /dev/null @@ -1,86 +0,0 @@ -package cau.agse.hs.staticfortran.main; - -import java.io.IOException; -import java.io.PrintStream; -import java.nio.file.Paths; -import java.util.List; - -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.tools.ant.types.Path; -import org.xml.sax.SAXException; - -import cau.agse.hs.staticfortran.model.ASTNode; -import cau.agse.hs.staticfortran.model.FortranModuleModel; -import cau.agse.hs.staticfortran.model.FortranProjectModel; -import cau.agse.hs.utils.files.Directories; -import cau.agse.hs.utils.files.FileUtils; -import cau.agse.hs.utils.staging.IOStaging; - -public class ParseXML { - - static String[] UVicVersions = { - "UVic-caucluster_2.6_fixed", - "UVic-caucluster_2.7.1_fixed", - "UVic-caucluster_2.7.2_fixed", - "UVic-caucluster_2.7.3-fixed", - "UVic-caucluster_2.7.4_fixed", - "UVic-caucluster_2.7.5_fixed", - "UVic-caucluster_2.7_fixed", - "UVic-caucluster_2.8", - "UVic-caucluster_2.9", - "UVic-caucluster_2.9.1", - "UVic-caucluster_2.9.2" }; - - public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException { - - if (args.length != 2) { - System.out.println("Tool requires two arguments:"); - System.out.println(" - path to fxtran-generated XML files"); - System.out.println(" - path to store output files"); - System.exit(0); - } - - Path rootPath = Paths.get(args[0]); - Path outputDir = Paths.get(args[1]); - boolean handleRoot = true; - - Predicate<Path> notRootPath = path -> !path.toAbsolutePath().equals(rootPath.toAbsolutePath()); - Predicate<Path> useDirectory = handleRoot? Directories.isDirectory : notRootPath; - - List<Path> directories = Directories.pathsInDirectory(rootPath, useDirectory, useDirectory, true); - System.out.println("done scanning."); - - for (Path directory : directories) { - FortranProjectModel projectModel = new FortranProjectModel(); - projectModel.addModulesFromXMLs(directory); - System.out.println("Added modules from " + directory.toAbsolutePath() + "."); - - for (FortranModuleModel fortranModule : projectModel) { - - // System.out.println("function declarations:"); - // xml.functionDeclarations().forEach(System.out::println); - - System.out.println("subroutine calls of " + fortranModule.getXmlFilePath() + ": "); - fortranModule.subroutineCalls().forEach(pair -> System.out.println("call: " + pair.first + " --> " + pair.second)); - - System.out.println("function calls of " + fortranModule.getXmlFilePath() + ": "); - fortranModule.functionCalls().forEach(pair -> System.out.println("call: " + pair.first + " --> " + pair.second)); - - System.out.println("node types:"); - IOStaging.printWithCommas(fortranModule.computeAllNodeAttributes(node -> ASTNode.nodeType(node.getNodeType()))); - - System.out.println("node names:"); - IOStaging.printWithCommas(fortranModule.computeAllNodeAttributes(node -> node.getNodeName())); - } - - FileUtils.createDirectory(outputDir); - - PrintStream tableOutput = FileUtils.printToFileAnd(System.out, outputDir.resolve("calltable.csv")); - PrintStream errorOutput = FileUtils.printToFileAnd(System.out, outputDir.resolve("notfound.csv")); - - projectModel.exportCallTable(tableOutput, errorOutput); - } - } - -} diff --git a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/ASTNode.java b/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/ASTNode.java deleted file mode 100644 index 8709756994d659f1ce20bce4becd3f4742db224d..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/ASTNode.java +++ /dev/null @@ -1,392 +0,0 @@ -package cau.agse.hs.staticfortran.model; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.List; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import cau.agse.hs.tools.DataStructureTools; -import cau.agse.hs.utils.lists.iterators.IndexIterator; -import cau.agse.hs.utils.misc.Pair; -import lombok.experimental.Delegate; - -// No own attributes, only accessor functions for nodes. Implemented as class in order to allow -// chaining. - -public class ASTNode implements Node { - - @Delegate(types=Node.class) - Node node; - - public String getNodeName() { - return (node == null)? null : node.getNodeName(); - } - - public static Predicate<Node> isSubroutineStatement = hasName("subroutine-stmt"); - public static Predicate<Node> isEndSubroutineStatement = hasName("end-subroutine-stmt"); - public static Predicate<Node> isFunctionStatement = hasName("function-stmt"); - public static Predicate<Node> isEndFunctionStatement = hasName("end-function-stmt"); - public static Predicate<Node> isModuleStatement = hasName("module-stmt"); - public static Predicate<Node> isUseStatement = hasName("use-stmt"); - public static Predicate<Node> isCallStatement = hasName("call-stmt"); - public static Predicate<Node> isSubroutineName = hasName("subroutine-N"); - public static Predicate<Node> isFunctionName = hasName("function-N"); - public static Predicate<Node> isNamedExpression = hasName("named-E"); - public static Predicate<Node> isBigN = hasName("N"); - public static Predicate<Node> isSmallN = hasName("n"); - public static Predicate<Node> isElementLT = hasName("element-LT"); - public static Predicate<Node> isRLT = hasName("R-LT"); - public static Predicate<Node> isElement = hasName("element"); - public static Predicate<Node> isParensR = hasName("parens-R"); - public static Predicate<Node> isRegularLeftParanthesis = isParensR.and(node -> node.getTextContent().startsWith("(")); - public static Predicate<Node> isOperationStatement = isSubroutineStatement.or(isFunctionStatement); - - public static Predicate<Node> namedExpressionFunctionCall = - isNamedExpression - .and(childSatisfies("0", isBigN)) - .and(childSatisfies("0,0", isSmallN)) - .and(childSatisfies("1", isRLT)) - .and(childSatisfies("1,0", isRegularLeftParanthesis)) - ; - - public static String nameOfCalledFunction(Node functionCallNode) { - return getSuccessorNode(functionCallNode, "0,0").getTextContent(); - } - - public static String nameOfCalledOperation(Node operationCallNode) { - return getSuccessorNode(operationCallNode, "1").getTextContent(); - } - - public static Predicate<Node> hasName(String name) { - return node -> name.equals(node.getNodeName()); - } - - public static Predicate<Node> hasTextContent(String content) { - return node -> content.equals(node.getTextContent()); - } - - public static Predicate<Node> childSatisfies(String path, Predicate<Node> predicate) { - return node -> predicate.test(getSuccessorNode(node, path)); - } - - public ASTNode(Node node) { - this.node = node; - if (!satisfiesAssumptions(node)) { - throw new IllegalArgumentException("unexpected node"); - } - } - - public String getNodeTypeName() { - return nodeType(this.getNodeType()); - } - - public static String nodeType(short nodeType) { - return switch(nodeType) { - case Node.ELEMENT_NODE -> "Element Node"; - case Node.ATTRIBUTE_NODE -> "Attribute Node"; - case Node.TEXT_NODE -> "Text Node"; - case Node.CDATA_SECTION_NODE -> "CDATA Section Node"; - case Node.ENTITY_REFERENCE_NODE -> "Entity Reference Node"; - case Node.ENTITY_NODE -> "Entity Node"; - case Node.PROCESSING_INSTRUCTION_NODE -> "Processing Instruction Node"; - case Node.COMMENT_NODE -> "Comment Node"; - case Node.DOCUMENT_NODE -> "Document Node"; - case Node.DOCUMENT_TYPE_NODE -> "Document Type Node"; - case Node.DOCUMENT_FRAGMENT_NODE -> "Document Fragment Node"; - case Node.NOTATION_NODE -> "Notation Node"; - default -> "Unknown Node Type"; - }; - } - - // Convenience functions - - private Iterable<ASTNode> getChildren() { - return getChildren(this); - } - - private static Iterable<ASTNode> getChildren(Node node) { - return new Iterable<ASTNode>() { - @Override - public Iterator<ASTNode> iterator() { - return new IndexIterator<>(() -> node.getChildNodes().getLength(), index -> new ASTNode(node.getChildNodes().item(index))); - }}; - } - - public ASTNode getChild(int index) { - return new ASTNode(getChildNodes().item(index)); - } - - public static int printNode(Node node, int depth) { - String spaces = ""; - for (int i = 0; i < depth; i++) { - spaces = spaces + " "; - } - int numberOfPrintedNodes = 1; - System.out.println(spaces + "[node type] " + ASTNode.nodeType(node.getNodeType())); - System.out.println(spaces + "[node name] " + node.getNodeName()); - System.out.println(spaces + "[node value] " + node.getNodeValue()); - System.out.println(spaces + "[node text content] " + node.getTextContent()); - System.out.println(spaces + "[node #kids] " + node.getChildNodes().getLength()); - - for (ASTNode child : ASTNode.getChildren(node)) { - numberOfPrintedNodes += printNode(child, depth + 1); - } - return numberOfPrintedNodes; - } - - - // Node Search - - private static boolean testNodeAndFirstChildPredicateChain(Node t, List<Predicate<Node>> predicates) { - if (predicates.isEmpty()) return true; - if (!predicates.get(0).test(t)) return false; - if (predicates.size() == 1) return true; - if (t.getChildNodes().getLength() == 0) return false; - return testNodeAndFirstChildPredicateChain(t.getFirstChild(), predicates.subList(1, predicates.size())); - } - - - static private Predicate<Node> nodeAndfirstChildPredicateChain(List<Predicate<Node>> predicates) { - return node -> testNodeAndFirstChildPredicateChain(node, predicates); - } - - static private ASTNode getSuccessorNode(Node node, String path) { - - if (path.isEmpty()) return new ASTNode(node); - - String firstNumber = StringUtils.substringBefore(path, ","); - String nextPath = StringUtils.substringAfter(path, ","); - int childIndex = Integer.parseInt(firstNumber); - NodeList children = node.getChildNodes(); - if (children.getLength() < childIndex) { - return null; - } - return getSuccessorNode(node.getChildNodes().item(childIndex), nextPath); - } - - static ASTNode getFirstChildChain(Node node, int depth) { - - Node result = node; - - for (int i = 0; i < depth; i++) { - result = result.getFirstChild(); - } - - return new ASTNode(result); - } - - // NOTE: Only terminates if nextNode eventually returns null or a matching element. - private ASTNode findFirst(Function <Node, Node> nextNode, Predicate<Node> condition, boolean includeSelf) { - return findFirst(nextNode, condition, includeSelf, null); - } - - // paranthesistypes: contains pairs of "opening paranthesis" and "closed paranthesis" conditions, - // where stuff between the paranthesis is ignored. - // - // Be careful with the search direction here, if you are searching "backwards", then ")" might - // be your opening, and "(" your closing paranthesis. - // - // use case: when finding the containing operation statement, we need to skip functions that - // are defined "along the way," i.e., where both the "function declaration" and the - // "end function declaration" elements appear. - - // NOTE: Only terminates if nextNode eventually returns null or a matching element. - private ASTNode findFirst(Function <Node, Node> nextNode, Predicate<Node> condition, boolean includeSelf, List<Pair<Predicate<Node>, Predicate<Node>>> paranthesesTypes) { - - int numberparanthesesTypes = (paranthesesTypes == null)? 0 : paranthesesTypes.size(); - int[] openParanthesis = new int[numberparanthesesTypes]; - - Node current = this; // nextNode.apply(this); - - boolean inParanthesisInterval = false; - while (current != null) { - - if (!inParanthesisInterval && condition.test(current) && ((current != this) || includeSelf)) { - return new ASTNode(current); - } - - inParanthesisInterval = false; - for (int i = 0; i < numberparanthesesTypes; i++) { - Predicate<Node> openingParanthesis = paranthesesTypes.get(i).first; - Predicate<Node> closingParanthesis = paranthesesTypes.get(i).second; - - if (openingParanthesis.test(current)) { - openParanthesis[i]++; - } - - if (closingParanthesis.test(current)) { - openParanthesis[i]--; - } - - if (openParanthesis[i] > 0) { - inParanthesisInterval = true; - } - } - - current = nextNode.apply(current); - } - - return null; - } - - private boolean hasConnectedWith(Function<Node, Node> nextNode, Predicate<Node> condition, boolean includeSelf) { - return findFirst(nextNode, condition, includeSelf) != null; - } - - private boolean hasLeftSibling(Predicate<Node> condition, boolean includeSelf) { - return hasConnectedWith(node -> node.getPreviousSibling(), condition, includeSelf); - } - - private ASTNode firstLeftSibling(Predicate<Node> condition, boolean includeSelf) { - return firstLeftSibling(condition, includeSelf, null); - } - - private ASTNode firstLeftSibling(Predicate<Node> condition, boolean includeSelf, List<Pair<Predicate<Node>, Predicate<Node>>> paranthesisTypes) { - return findFirst(node -> node.getPreviousSibling(), condition, includeSelf, paranthesisTypes); - } - - private ASTNode firstAncestor(Predicate<Node> condition, boolean includeSelf) { - return findFirst(node -> node.getParentNode(), condition, includeSelf); - } - - public Set<ASTNode> allDescendents(Predicate<Node> condition, boolean includeSelf) { - return addAllDescendentsTo(condition, includeSelf, new HashSet<>()); - } - - private <T extends Collection<ASTNode>> T addAllDescendentsTo(Predicate<Node> condition, boolean includeSelf, T addToThese) { - - if (condition.test(this) && includeSelf) { - addToThese.add(this); - } - - for (ASTNode child : this.getChildren()) { - child.addAllDescendentsTo(condition, true, addToThese); - } - - return addToThese; - } - - public static String getNameOfOperation(ASTNode operationStatement) { - - if (isSubroutineStatement.test(operationStatement)) { - return getNameOfOperation(operationStatement, isSubroutineName); - } - else if (isFunctionStatement.test(operationStatement)) { - return getNameOfOperation(operationStatement, isFunctionName); - } - - throw new IllegalArgumentException("Node is neither a function nor a subroutine statement."); - } - - public static String getNameOfOperation(ASTNode operationStatement, Predicate<Node> namePredicate) { - Set<ASTNode> nameNodes = operationStatement.allDescendents(namePredicate, true); - return DataStructureTools.getUniqueElement(nameNodes).getTextContent(); - } - - public ASTNode findContainingStatement(Predicate<Node> condition) { - return findContainingStatement(condition, null); - } - - public ASTNode findContainingStatement(Predicate<Node> condition, List<Pair<Predicate<Node>, Predicate<Node>>> paranthesisTypes) { - - Predicate<Node> hasSuchANodeAsLeftSibling = node -> (new ASTNode(node).hasLeftSibling(condition, false)); - - ASTNode siblingOfSuchNode = this.firstAncestor(hasSuchANodeAsLeftSibling, - !condition.test(this)); - - if (siblingOfSuchNode == null) { - return null; - } - - ASTNode suchStatement = siblingOfSuchNode.firstLeftSibling(condition, true, paranthesisTypes); - return suchStatement; - } - - public String getNameOfContainingOperation() { - return getNameOfContainingOperation(false); - } - - public String getNameOfContainingOperation(boolean verbose) { - Pair<Predicate<Node>, Predicate<Node>> - endFunctionToBeginFunction = new Pair<>(isEndFunctionStatement, isFunctionStatement); - - Pair<Predicate<Node>, Predicate<Node>> - endSubroutineToBeginSubroutine = new Pair<>(isEndSubroutineStatement, isSubroutineStatement); - - var paranthesisTypes = List.of(endFunctionToBeginFunction, endSubroutineToBeginSubroutine); - - ASTNode containingOperationStatement = findContainingStatement(isOperationStatement, paranthesisTypes); - if (verbose) { - System.out.println("looking for containing operation of " + this.getTextContent()); - System.out.println("Containing Operation Statement: " + containingOperationStatement.getTextContent()); - } - return (containingOperationStatement == null)? "<root>" : getNameOfOperation(containingOperationStatement); - } - - // We make some assumptions about the structure of the Fortran files (and the generated XML representations). - // If we hit a node that does not satisfy these assumptions, throw an exception so that we know we need to - // handle that case as well. - public static boolean satisfiesAssumptions(Node node) { - - if (node == null) { - return true; - } - - short type = node.getNodeType(); - - if ((type == Node.TEXT_NODE) && node.getChildNodes().getLength() > 0) throw new IllegalArgumentException("text node with children"); - - if ((node.getNodeName().equals("call-stmt")) && node.getChildNodes().getLength() < 2) { - printNode(node, 0); - throw new IllegalArgumentException("call statement with < 2 children"); - } - - if (isNamedExpression.test(node)) { - // NodeList children = node.getChildNodes(); - Node firstChild = node.getFirstChild(); - Node firstGrandChild = firstChild.getFirstChild(); - if (!isBigN.test(firstChild)) { - throw new IllegalArgumentException("that's not a nice named expression, dude."); - } - - if(!isSmallN.test(firstGrandChild)) { - throw new IllegalArgumentException("that's not a nice named expression, dude."); - } - - if (firstGrandChild.getChildNodes().getLength() > 1) { - printNode(firstGrandChild, 0); - throw new IllegalArgumentException("that's not a nice named expression, dude."); - } - } - - return true; - } - - public boolean satisfiesAssumptions() { - return satisfiesAssumptions(this); - } - - public int getNumberOfDescendants(boolean countSelf) { - return allDescendents(node -> true, countSelf).size(); - } - - public <T> Set<T> getDescendentAttributes(Predicate<Node> predicate, Function<ASTNode, T> extractAttribute) throws ParserConfigurationException, SAXException, IOException { - return allDescendents(predicate, true) - .stream() - .map(extractAttribute) - .collect(Collectors.toSet()); - } -} diff --git a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranModuleModel.java b/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranModuleModel.java deleted file mode 100644 index a53dd271733401697332ad7593a5e0c5710e253d..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranModuleModel.java +++ /dev/null @@ -1,163 +0,0 @@ -package cau.agse.hs.staticfortran.model; - -import java.io.IOException; -import java.io.PrintStream; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -import cau.agse.hs.tools.DataStructureTools; -import cau.agse.hs.utils.lists.misc.ListTools; -import cau.agse.hs.utils.misc.Pair; -import lombok.Getter; - -public class FortranModuleModel { - - @Getter Path xmlFilePath; - @Getter Set<String> usedModules; - @Getter Set<String> specifiedSubroutines; - @Getter Set<String> specifiedFunctions; - @Getter Set<String> specifiedOperations; - @Getter String moduleName; - ASTNode documentElement; - - public FortranModuleModel(Path xmlFilePath) throws ParserConfigurationException, SAXException, IOException { - this.xmlFilePath = xmlFilePath; - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document doc = builder.parse(xmlFilePath.toFile()); - doc.getDocumentElement().normalize(); - documentElement = new ASTNode(doc.getDocumentElement()); - ASTNode moduleStatement = DataStructureTools.getUniqueElementIfNonEmpty(documentElement.allDescendents(ASTNode.isModuleStatement, true), null); - this.moduleName = (moduleStatement == null)? "<no module>" : moduleStatement.getChild(1).getTextContent(); - - this.usedModules = computeUsedModels(); - this.specifiedSubroutines = computeSubroutineDeclarations(); - this.specifiedFunctions = computeFunctionDeclarations(); - this.specifiedOperations = new HashSet<>(); - this.specifiedOperations.addAll(specifiedFunctions); - this.specifiedOperations.addAll(specifiedSubroutines); - - printSummary(System.out); - } - - public void printSummary(PrintStream out) { - out.println("# Summary"); - out.println(" [xmlFilePath] " + xmlFilePath); - out.println(" [moduleName] " + moduleName); - out.println(" [used modules] "); - usedModules.forEach(name -> System.out.println(" * " + name)); - - out.println(" [subroutine definitions] "); - specifiedSubroutines.forEach(name -> System.out.println(" * " + name)); - - out.println(" [function definitions] "); - specifiedFunctions.forEach(name -> System.out.println(" * " + name)); - } - - public void printXML() throws ParserConfigurationException, SAXException, IOException { - Set<String> nodeTypes = new HashSet<>(); - ASTNode.printNode(documentElement, 0); - - nodeTypes.forEach(System.out::println); - System.out.println("# nodes: " + documentElement.allDescendents(node -> true, true).size()); - } - - public Set<String> computeSubroutineDeclarations() throws ParserConfigurationException, SAXException, IOException { - return documentElement.getDescendentAttributes(ASTNode.isSubroutineStatement, subroutineNode -> ASTNode.getNameOfOperation(subroutineNode)); - } - - public Set<String> computeFunctionDeclarations() throws ParserConfigurationException, SAXException, IOException { - return documentElement.getDescendentAttributes(ASTNode.isFunctionStatement, functionNode -> ASTNode.getNameOfOperation(functionNode)); - } - - /* public Set<String> getAllNamesInNamedEChains() throws ParserConfigurationException, SAXException, IOException { - return documentElement.getDescendentAttributes(ASTNode.namedExpressionFunctionCall, ASTNode.nameOfCalledFunction); - } // node -> ASTNode.getFirstChildChain(node, 4).getTextContent() */ - - public List<Pair<String, String>> operationCalls() throws ParserConfigurationException, SAXException, IOException { - return ListTools.ofM(subroutineCalls(), functionCalls(), Pair.getComparatorFirstSecond()); - } - - public List<Pair<String, String>> operationCalls(Predicate<Node> callPredicate, Function<Node, String> calledOperation) { - Set<Pair<String, String>> result = new HashSet<>(); // Check for double entries - Set<ASTNode> callStatements = documentElement.allDescendents(callPredicate, true); - for (ASTNode callStatement : callStatements) { - String callee = calledOperation.apply(callStatement); - String caller = callStatement.getNameOfContainingOperation(); - result.add(new Pair<>(caller, callee)); - } - - return ListTools.ofM(result, Pair.getComparatorFirstSecond()); - } - - public List<Pair<String, String>> subroutineCalls() throws ParserConfigurationException, SAXException, IOException { - return operationCalls(ASTNode.isCallStatement, subroutineCall -> ASTNode.nameOfCalledOperation(subroutineCall)); - /* - Set<Pair<String, String>> result = new HashSet<>(); // Check for double entries - Set<ASTNode> callStatements = documentElement.allDescendents(ASTNode.isCallStatement, true); - for (ASTNode callStatement : callStatements) { - // Issue: Here we do not know which function is called, if there are several xms files - // (Fortran files) containing the same function. This needs to be resolved on a higher - // level (i.e., the calling class that has access to the set of operation declarations - // by all the modules). Therefore, we here only return a simple list of pairs of strings. - String callee = ASTNode.nameOfCalledOperation(callStatement); - String caller = callStatement.getNameOfContainingOperation(); - result.add(new Pair<>(caller, callee)); - } - - return ListTools.ofM(result, Pair.getComparatorFirstSecond());*/ - } - - public List<Pair<String, String>> functionCalls() throws ParserConfigurationException, SAXException, IOException { - return operationCalls(ASTNode.namedExpressionFunctionCall, functionCall -> ASTNode.nameOfCalledFunction(functionCall)); - - /* - Set<Pair<String, String>> result = new HashSet<>(); // Check for double entries - Set<ASTNode> functionCalls = documentElement.allDescendents(ASTNode.namedExpressionFunctionCall, true); - for (ASTNode functionCall : functionCalls) { - String callee = ASTNode.nameOfCalledFunction(functionCall); - String caller = functionCall.getNameOfContainingOperation(); - result.add(new Pair<>(caller, callee)); - } - - return ListTools.ofM(result, Pair.getComparatorFirstSecond()); */ - } - - - - public <T extends Comparable<T>> List<T> computeAllNodeAttributes(Function<ASTNode, T> extractAttribute) throws ParserConfigurationException, SAXException, IOException { - List<T> resultList = ListTools.ofM(documentElement.getDescendentAttributes(node -> true, extractAttribute)); - Collections.sort(resultList); - return resultList; - } - - public int getNumberOfNodes() throws ParserConfigurationException, SAXException, IOException { - return documentElement.getNumberOfDescendants(true); - } - - public Set<String> computeUsedModels() { - Set<String> result = new HashSet<>(); - ASTNode rootNode = documentElement; - Set<ASTNode> useStatements = rootNode.allDescendents(ASTNode.isUseStatement, false); - for (ASTNode useStatement : useStatements) { - String usedModuleName = useStatement.getChild(1).getTextContent(); - System.out.println("found use statement: " + useStatement.getTextContent() + ", module name: " + usedModuleName); - result.add(usedModuleName); - } - return result; - } - -} diff --git a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranProjectModel.java b/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranProjectModel.java deleted file mode 100644 index bf441d73249b61460809d7904922132283c5a114..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/main/java/cau/agse/hs/staticfortran/model/FortranProjectModel.java +++ /dev/null @@ -1,96 +0,0 @@ -package cau.agse.hs.staticfortran.model; - -import java.io.IOException; -import java.io.PrintStream; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.xml.parsers.ParserConfigurationException; - -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -import cau.agse.hs.tools.DataStructureTools; -import cau.agse.hs.utils.files.Directories; -import cau.agse.hs.utils.lists.misc.ListTools; -import cau.agse.hs.utils.misc.Pair; -import cau.agse.hs.utils.staging.IOStaging; -import lombok.experimental.Delegate; - -public class FortranProjectModel implements List<FortranModuleModel> { - - @Delegate List<FortranModuleModel> fortranModules; - - Map<String, FortranModuleModel> moduleNamesToXMLs; - - public FortranProjectModel() { - fortranModules = new ArrayList<>(); - moduleNamesToXMLs = new HashMap<>(); - } - - public void addModule(Path xmlFile) throws ParserConfigurationException, SAXException, IOException { - FortranModuleModel module = new FortranModuleModel(xmlFile); - fortranModules.add(module); - moduleNamesToXMLs.put(module.moduleName, module); - } - - public void addModulesFromXMLs(Path directory) throws IOException, ParserConfigurationException, SAXException { - List<Path> xmlFiles = Directories.pathsInDirectory(directory, Directories.endsWith(".xml")); - Collections.sort(xmlFiles); - for (Path xml : xmlFiles) { - this.addModule(xml); - } - } - - public void exportCallTable(PrintStream tableOut, PrintStream notFoundOut) throws ParserConfigurationException, SAXException, IOException { - tableOut.println("callerfilename,callermodule,callerfunction,calleefilename,calleemodule,calleefunction"); - notFoundOut.println("Calls to operations that could not be found:"); - for (FortranModuleModel module : this) { - for (Pair<String, String> call : module.operationCalls()) { - String callerFunctionName = call.first; - String callerFileName = module.getXmlFilePath().toAbsolutePath().getFileName().toString(); - String calleeFunctionName = call.second; - FortranModuleModel calleeXML = resolveCallee(module, calleeFunctionName); - String calleeFileName = (calleeXML == null)? "<unknown>" : calleeXML.getXmlFilePath().toAbsolutePath().getFileName().toString(); - String calleeModuleName = (calleeXML == null)? "<unknown>" : calleeXML.moduleName; - tableOut.println(callerFileName + ", " + module.moduleName + ", " + callerFunctionName + ", " + calleeFileName + ", " + calleeModuleName + ", " + calleeFunctionName); - if (calleeXML == null) { - notFoundOut.println(callerFileName + ":" + callerFunctionName + " --> " + calleeFunctionName); - } - } - } - } - - private FortranModuleModel resolveCallee(FortranModuleModel xml, String calleeFunctionName) { - return DataStructureTools.getUniqueElementIfNonEmpty(resolveCalleeModuleCandidates(xml, calleeFunctionName), null); - } - - private List<FortranModuleModel> resolveCalleeModuleCandidates(FortranModuleModel callerModule, String calleeOperationName) { - - List<FortranModuleModel> result = ListTools.ofM(); - List<FortranModuleModel> usedModules = ListTools.ofM(callerModule); // local definitions are always the first ones. - - for (String usedModuleName : callerModule.getUsedModules()) { - FortranModuleModel moduleXML = moduleNamesToXMLs.get(usedModuleName); - if (moduleXML == null) { - System.out.println("MODULE NOT FOUND: [" + usedModuleName + "]"); - } - else { - usedModules.add(moduleXML); - } - } - - for (FortranModuleModel usedModule : usedModules) { - if (usedModule.getSpecifiedOperations().contains(calleeOperationName)) { - result.add(usedModule); - } - } - return result; - } -} diff --git a/tools/fxtran-parser/src/main/java/cau/agse/hs/tools/DataStructureTools.java b/tools/fxtran-parser/src/main/java/cau/agse/hs/tools/DataStructureTools.java deleted file mode 100644 index 8171e614dd9c304c471e47693c987762f529c28e..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/main/java/cau/agse/hs/tools/DataStructureTools.java +++ /dev/null @@ -1,20 +0,0 @@ -package cau.agse.hs.tools; - -import java.util.Collection; - -public class DataStructureTools { - - public static <T> T getUniqueElement (Collection<T> collection) { - - if (collection.size() != 1) { - throw new IllegalArgumentException("Unique element exists only for singletons."); - } - - return collection.iterator().next(); - - } - - public static <T> T getUniqueElementIfNonEmpty (Collection<T> collection, T alternative) { - return collection.isEmpty()? alternative : getUniqueElement(collection); - } -} diff --git a/tools/fxtran-parser/src/test/java/regression/CompareWithPythonAnalysis.java b/tools/fxtran-parser/src/test/java/regression/CompareWithPythonAnalysis.java deleted file mode 100644 index 74cd0bf3f68b43398af71b7814795290390be6d9..0000000000000000000000000000000000000000 --- a/tools/fxtran-parser/src/test/java/regression/CompareWithPythonAnalysis.java +++ /dev/null @@ -1,130 +0,0 @@ -package regression; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import javax.xml.parsers.ParserConfigurationException; - -import org.junit.Test; -import org.xml.sax.SAXException; - -import cau.agse.hs.staticfortran.model.FortranModuleModel; -import cau.agse.hs.utils.lists.misc.ListTools; -import cau.agse.hs.utils.misc.Pair; - -public class CompareWithPythonAnalysis { - - public static List<String> functionDeclarationsInSediment = List.of( - "bury", - "calc_buff", - "calc_cal_c", - "calc_db", - "calc_dc", - "calc_do2", - "calc_k", - "calss", - "co3", - "co3ss", - "estimate_rc", - "get_resp", - "get_sed_ml_mass", - "my_saxpy", - "my_sgbfa", - "my_sgbsl", - "my_sscal", - "o2org", - "o2ss", - "orgc", - "pore_2_form", - "reset_pw", - "sed_const_cal", - "sed_diag", - "sed_ss", - "set_est_pore", - "set_pore", - "setup_pw", - "sldcon", - "sldfrc", - "tridiag"); - - public List<String> functionCallsInSediment = List.of( - "bury", "set_est_pore", - "bury", "get_sed_ml_mass", - "sed_ss", "o2org", - "sed_ss", "calss", - "sed_ss", "set_pore", - "sed_ss", "pore_2_form", - "sed_ss", "calc_do2", - "sed_ss", "calc_dc", - "sed_ss", "calc_db", - "sed_const_cal", "set_pore", - "sed_const_cal", "pore_2_form", - "sed_const_cal", "calc_do2", - "sed_const_cal", "calc_dc", - "sed_const_cal", "calc_db", - "sed_const_cal", "o2org", - "sed_const_cal", "co3ss", - "o2org", "orgc", - "o2org", "o2ss", - "o2org", "get_resp", - "orgc", "tridiag", - "orgc", "sldcon", - "o2ss", "tridiag", - "calss", "co3ss", - "calss", "sldcon", - "co3ss", "co3", - "co3ss", "sed_diag", - "co3ss", "reset_pw", - "co3ss", "reset_pw", - "co3ss", "reset_pw", - "co3", "my_sgbfa", - "co3", "my_sgbsl", - "my_sgbfa", "my_sscal", - "my_sgbfa", "my_saxpy", - "my_sgbsl", "my_saxpy", - "my_sgbsl", "my_saxpy"); - - - - public void checkXMLFileHasExpectedListOfFunctionDeclarations(Path xmlFile, List<String> expectedDeclarations) throws ParserConfigurationException, SAXException, IOException { - FortranModuleModel xml = new FortranModuleModel(xmlFile); - List<String> declarations = new ArrayList<String>(xml.computeSubroutineDeclarations()); - // Collections.sort(expectedDeclarations); - Collections.sort(declarations); - assertEquals(expectedDeclarations, declarations); - System.out.println("verified " + declarations.size() + " declarations."); - } - - public void checkXMLFileHasExpectedListOfFunctionCalls(Path xmlFile, List<String> expectedCalls) throws ParserConfigurationException, SAXException, IOException { - if ((expectedCalls.size() % 2) != 0) { - throw new IllegalArgumentException("Requires sequence <caller>, <callee>, must be of even length."); - } - FortranModuleModel xml = new FortranModuleModel(xmlFile); - List<Pair<String, String>> expectedCallPairs = ListTools.ofM(); - Iterator<String> units = expectedCalls.iterator(); - - while(units.hasNext()) { - expectedCallPairs.add(new Pair<>(units.next(), units.next())); - } - List<Pair<String, String>> actualCallPairs = xml.subroutineCalls(); - Collections.sort(actualCallPairs, Pair.getComparatorFirstSecond()); - Collections.sort(expectedCallPairs, Pair.getComparatorFirstSecond()); - assertEquals(expectedCallPairs, actualCallPairs); - System.out.println("verified " + actualCallPairs.size() + " calls."); - } - - - // @Test TODO: Uses paths only used during development / debugging. - public void test() throws ParserConfigurationException, SAXException, IOException { - checkXMLFileHasExpectedListOfFunctionDeclarations(Paths.get("../../esm-preprocessed/UVic-caucluster_2.9.2/code/sediment.f.xml"), functionDeclarationsInSediment); - checkXMLFileHasExpectedListOfFunctionCalls(Paths.get("../../esm-preprocessed/UVic-caucluster_2.9.2/code/sediment.f.xml"), functionCallsInSediment); - } - -}