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