diff --git a/.idea/misc.xml b/.idea/misc.xml index 687193e..ac2c845 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/src/main/kotlin/core/CFunction.kt b/src/main/kotlin/core/CFunction.kt index 5d03b1b..5c3bf42 100644 --- a/src/main/kotlin/core/CFunction.kt +++ b/src/main/kotlin/core/CFunction.kt @@ -1,8 +1,7 @@ package core +import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.typenameToTypeEnum -import org.w3c.dom.Node -import java.io.File class CFunction( val name: String, source: String // 函数名 @@ -68,35 +67,95 @@ class CFunction( return "" } - fun getTraceTree(): List { + fun getTraceTree(invokeInfo: InvokeInfo? = null): List { // 初始化 Trace Tree val nodes = mutableListOf() cParser.defineList.forEach { - nodes.add(TraceTree(it, null, null)) + nodes.add(TraceTree(it, mutableListOf())) } // 然后根据句子来获得 TraceTree + var paramIndex = 0 // 标记是第几个参数 cParser.sentenceList.forEachIndexed { index, sentence -> - if (sentence.type == CLanguage.Companion.OPERATION.DEFINE_VALUE_PARAM || sentence.type == CLanguage.Companion.OPERATION.CHANGE_VALUE_PARAM) { + if (sentence.type == DEFINE_VALUE_PARAM || sentence.type == CHANGE_VALUE_PARAM) { // 例子: // x,A(z),CHANGE_VALUE // A,z,CHANGE_VALUE_PARAM // y,x,CHANGE_VALUE // -,x,CHANGE_VALUE_PARAM - if (index > 1) { // 按理来说肯定成立,加个检查防止意外 + if (index > 0) { // 按理来说肯定成立,加个检查防止意外 val left = cParser.sentenceList[index - 1].left val lNode = nodes.findNode(left) val rNode = nodes.findNode(sentence.right) - val funName = sentence.left if (lNode != null && rNode != null) { - lNode.changedBy = rNode - if (funName != "-") { - lNode.upperFuncName = funName - } + rNode.changes.add(lNode) } } + } else if (sentence.type == PARAM && invokeInfo != null){ + if (invokeInfo.param.lastIndex >= paramIndex){ // 在 InvokeTree 里面 + val rNode = nodes.findNode(sentence.right) + val lNode = TraceTree("${invokeInfo.caller}:${invokeInfo.param[paramIndex]}",mutableListOf()) + if (rNode!= null) { + lNode.changes.add(rNode) + } + nodes.add(lNode) + paramIndex ++ + } } } - return nodes.getDeepest() + + // 去掉没有改过别人的 + val result = mutableListOf() + for (tree in nodes) { + if (!tree.changes.isEmpty()) { + result.add(tree) + } + } + + return result } +} + +fun List.find(name: String): CFunction? { + this.forEach { if (it.name == name) return it } + return null +} + +/** + * List.getInvokeTree + * @param List: 要求包含所有函数以查找 + * @param name: 从哪个函数开始查找 + * @return 特制的 TraceTree + */ +fun List.getInvokeTree(name: String): List { + // 先找到开始的函数 + val func = this.find(name) + if (func == null) { + return emptyList() + } + + val invokeTrees = mutableListOf() + val args = mutableListOf() + var funcName = "" + + func.cParser.sentenceList.forEach { sentence -> + // 🌰: + // A,z,CHANGE_VALUE_PARAM + if (sentence.type == CHANGE_VALUE_PARAM || sentence.type == DEFINE_VALUE_PARAM) { + if (sentence.left != "-") { // 左边就是函数名 + args.add(sentence.right) + funcName = sentence.left + } + }else{ // 更新 + val function = this.find(funcName) + if (function!=null) { + val info = InvokeInfo(name,args) + val tt = function.getTraceTree(info) + invokeTrees.addAll(tt) + } + args.clear() + funcName = "" + } + } + return invokeTrees } \ No newline at end of file diff --git a/src/main/kotlin/core/CLanguage.kt b/src/main/kotlin/core/CLanguage.kt index 7e3f26c..5add865 100644 --- a/src/main/kotlin/core/CLanguage.kt +++ b/src/main/kotlin/core/CLanguage.kt @@ -9,6 +9,7 @@ class CLanguage { CHANGE_VALUE, // identifier = RHAND DEFINE_VALUE_PARAM, // int a=b, 一直接在上一个后面 CHANGE_VALUE_PARAM, // a = b + PARAM, // 函数的参数初始化 RETURN // 字面意思 } enum class CTYPES { diff --git a/src/main/kotlin/core/CParser.kt b/src/main/kotlin/core/CParser.kt index 435b4ce..e7e59fa 100644 --- a/src/main/kotlin/core/CParser.kt +++ b/src/main/kotlin/core/CParser.kt @@ -1,5 +1,7 @@ package core +import core.CLanguage.Companion.OPERATION.* + class Sentence(val left: String, val right: String, val type: CLanguage.Companion.OPERATION) class CParser(content: String, paramNameList: List) { @@ -14,7 +16,13 @@ class CParser(content: String, paramNameList: List) { init { // 把参数加进去 - defineList.addAll(paramNameList) + if (!paramNameList.isEmpty()) { + for (param in paramNameList) { + sentenceList.add(Sentence("@", param, PARAM)) + defineList.add(param) + } + } + // 第一轮解析获得基本语义 content.split(';').forEach { val line = it.trim() @@ -26,9 +34,9 @@ class CParser(content: String, paramNameList: List) { if (match != null) { val leftHand = match.groupValues[1].trim().split(' ').last() // Left-hand side (variable) val rightHand = match.groupValues[2].trim() // Right-hand side (value) - sentenceList.add(Sentence(leftHand, rightHand, CLanguage.Companion.OPERATION.DEFINE_VALUE)) + sentenceList.add(Sentence(leftHand, rightHand, DEFINE_VALUE)) defineList.add(leftHand) - sentenceList.addAll(rightHandSimpleParser(rightHand, CLanguage.Companion.OPERATION.DEFINE_VALUE)) + sentenceList.addAll(rightHandSimpleParser(rightHand, DEFINE_VALUE)) } } } else { // 重新定义 @@ -36,13 +44,13 @@ class CParser(content: String, paramNameList: List) { if (match != null) { val leftHand = match.groupValues[1].trim() // Left-hand side (variable) val rightHand = match.groupValues[2].trim() // Right-hand side (value) - sentenceList.add(Sentence(leftHand, rightHand, CLanguage.Companion.OPERATION.CHANGE_VALUE)) - sentenceList.addAll(rightHandSimpleParser(rightHand, CLanguage.Companion.OPERATION.CHANGE_VALUE)) + sentenceList.add(Sentence(leftHand, rightHand, CHANGE_VALUE)) + sentenceList.addAll(rightHandSimpleParser(rightHand, CHANGE_VALUE)) } } } else if (line.contains("return")) { // return val returnValue = line.split(' ').last() - sentenceList.add(Sentence("return", returnValue, CLanguage.Companion.OPERATION.RETURN)) + sentenceList.add(Sentence("return", returnValue, RETURN)) } else { // 调用函数,解析参数就行了 val match = func_invoke_regex.find(line) // 如果是后面的就要这个 if (match != null) { @@ -50,7 +58,7 @@ class CParser(content: String, paramNameList: List) { val args = match.groupValues[2].trim() // Right-hand side (value) args.split(',').forEach { arg -> if (arg in defineList) { // 定义过的变量 - sentenceList.add(Sentence(func_name, arg, CLanguage.Companion.OPERATION.FUNCTION_INVOCATION)) + sentenceList.add(Sentence(func_name, arg, FUNCTION_INVOCATION)) } } } @@ -61,16 +69,16 @@ class CParser(content: String, paramNameList: List) { private fun rightHandSimpleParser(right: String, type: CLanguage.Companion.OPERATION): List { // 解析右边表达式的 fun getType(): CLanguage.Companion.OPERATION { return when (type) { // 改变类型 - CLanguage.Companion.OPERATION.DEFINE_VALUE -> { - CLanguage.Companion.OPERATION.DEFINE_VALUE_PARAM + DEFINE_VALUE -> { + DEFINE_VALUE_PARAM } - CLanguage.Companion.OPERATION.CHANGE_VALUE -> { - CLanguage.Companion.OPERATION.CHANGE_VALUE_PARAM + CHANGE_VALUE -> { + CHANGE_VALUE_PARAM } else -> { - CLanguage.Companion.OPERATION.RETURN + RETURN } } } diff --git a/src/main/kotlin/core/SourceFile.kt b/src/main/kotlin/core/SourceFile.kt index 73f2328..476b172 100644 --- a/src/main/kotlin/core/SourceFile.kt +++ b/src/main/kotlin/core/SourceFile.kt @@ -1,7 +1,9 @@ +@file:Suppress("unused") + package core import java.io.File - +import core.CLanguage.Companion.OPERATION.* class SourceFile { companion object { val function_define_regex = """\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)\s*\{""".toRegex() // main(){ 匹配函数名 @@ -68,7 +70,7 @@ class SourceFile { it.cParser.sentenceList.forEach { sentence -> when (sentence.type) { - CLanguage.Companion.OPERATION.FUNCTION_INVOCATION, CLanguage.Companion.OPERATION.RETURN -> { + FUNCTION_INVOCATION, RETURN -> { if (useCache.isNotEmpty()) { funcResult.add(useCache.toString()) useCache.clear() // 清空 @@ -76,7 +78,7 @@ class SourceFile { funcResult.add("${sentence.right}-use") } - CLanguage.Companion.OPERATION.DEFINE_VALUE, CLanguage.Companion.OPERATION.CHANGE_VALUE -> { + DEFINE_VALUE, CHANGE_VALUE -> { if (useCache.isNotEmpty()) { funcResult.add(useCache.toString()) useCache.clear() @@ -84,9 +86,11 @@ class SourceFile { useCache.append("${sentence.left}-def") } - CLanguage.Companion.OPERATION.DEFINE_VALUE_PARAM, CLanguage.Companion.OPERATION.CHANGE_VALUE_PARAM -> { + DEFINE_VALUE_PARAM, CHANGE_VALUE_PARAM -> { useCache.append(";${sentence.right}-use") } + + PARAM -> {} // 参数只用于构造def-use跨函数 } } if (useCache.isNotEmpty()) { @@ -103,11 +107,12 @@ fun main() { val funcs = sourceFile.parseFunction() funcs.forEach { println("${it.name}(${it.params}) -> ${it.returnType} {\n${it.content}\n} ") -// it.cParser.sentenceList.forEach{ s-> -// println("${s.left},${s.right},${s.type}") -// } - it.getTraceTree().print() + it.cParser.sentenceList.forEach{ s-> + println("${s.left},${s.right},${s.type}") + } + println(it.getTraceTree().getStringRepr()) } + println(funcs.getInvokeTree("main").getFuncRepr("main")) println(sourceFile.getDef()) println(sourceFile.getUse()) diff --git a/src/main/kotlin/core/TraceTree.kt b/src/main/kotlin/core/TraceTree.kt index d8ec6b6..514c60b 100644 --- a/src/main/kotlin/core/TraceTree.kt +++ b/src/main/kotlin/core/TraceTree.kt @@ -2,8 +2,12 @@ package core data class TraceTree( val name: String, - var changedBy: TraceTree?, - var upperFuncName: String? + var changes: MutableList, +) + +data class InvokeInfo( + val caller: String, + val param: List, ) fun List.findNode(name: String): TraceTree? { @@ -15,43 +19,35 @@ fun List.findNode(name: String): TraceTree? { return null } -fun List.print() { - fun traceChain(node: TraceTree?): String { - return if (node == null) { - "" // 读取完了 + +fun List.getStringRepr(): String { + fun getChanges(node: TraceTree, currentPath: String = node.name): String { + val paths = mutableListOf() + + // 没修改过就介绍 + if (node.changes.isEmpty()) { + paths.add(currentPath) } else { - traceChain(node.changedBy) + if (node.changedBy != null) { - "->" - } else { - "" - } + node.name + // 挨个获取 change + for (child in node.changes) { + paths.add(getChanges(child, "$currentPath->${child.name}")) + } } + + // 合为一个 String + return paths.joinToString("\n") } - this.forEach { traceTree -> - println(traceChain(traceTree)) + val result = StringBuilder() + this.forEach { + result.append(getChanges(it)) + result.append('\n') } + result.dropLast(1) + return result.toString() } -fun List.getDeepest(): List { - // 使用 Map 记录每个节点的深度 - val depthMap = mutableMapOf() - - // 计算每个节点的深度(从终点向上追溯) - for (trace in this) { - var depth = 0 - var current = trace - while (current.changedBy != null) { - depth++ - current = current.changedBy!! - } - // 将链起点的深度记录在 depthMap 中 - depthMap[trace] = depth - } - - // 找到最大深度值 - val maxDepth = depthMap.values.maxOrNull() ?: 0 - - // 返回具有最大深度的节点 - return depthMap.filterValues { it == maxDepth }.keys.toList() -} +fun List.getFuncRepr(func: String): String { + val strs = this.getStringRepr() + return strs.split('\n').filter { it.startsWith(func) }.joinToString("\n") +} \ No newline at end of file