I need relax
This commit is contained in:
parent
1ba58caa2b
commit
1ce8f94be6
6 changed files with 137 additions and 68 deletions
|
@ -4,7 +4,7 @@
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -1,8 +1,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
|
import core.CLanguage.Companion.OPERATION.*
|
||||||
import core.CLanguage.Companion.typenameToTypeEnum
|
import core.CLanguage.Companion.typenameToTypeEnum
|
||||||
import org.w3c.dom.Node
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class CFunction(
|
class CFunction(
|
||||||
val name: String, source: String // 函数名
|
val name: String, source: String // 函数名
|
||||||
|
@ -68,35 +67,95 @@ class CFunction(
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTraceTree(): List<TraceTree> {
|
fun getTraceTree(invokeInfo: InvokeInfo? = null): List<TraceTree> {
|
||||||
// 初始化 Trace Tree
|
// 初始化 Trace Tree
|
||||||
val nodes = mutableListOf<TraceTree>()
|
val nodes = mutableListOf<TraceTree>()
|
||||||
cParser.defineList.forEach {
|
cParser.defineList.forEach {
|
||||||
nodes.add(TraceTree(it, null, null))
|
nodes.add(TraceTree(it, mutableListOf<TraceTree>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 然后根据句子来获得 TraceTree
|
// 然后根据句子来获得 TraceTree
|
||||||
|
var paramIndex = 0 // 标记是第几个参数
|
||||||
cParser.sentenceList.forEachIndexed { index, sentence ->
|
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
|
// x,A(z),CHANGE_VALUE
|
||||||
// A,z,CHANGE_VALUE_PARAM
|
// A,z,CHANGE_VALUE_PARAM
|
||||||
// y,x,CHANGE_VALUE
|
// y,x,CHANGE_VALUE
|
||||||
// -,x,CHANGE_VALUE_PARAM
|
// -,x,CHANGE_VALUE_PARAM
|
||||||
if (index > 1) { // 按理来说肯定成立,加个检查防止意外
|
if (index > 0) { // 按理来说肯定成立,加个检查防止意外
|
||||||
val left = cParser.sentenceList[index - 1].left
|
val left = cParser.sentenceList[index - 1].left
|
||||||
val lNode = nodes.findNode(left)
|
val lNode = nodes.findNode(left)
|
||||||
val rNode = nodes.findNode(sentence.right)
|
val rNode = nodes.findNode(sentence.right)
|
||||||
val funName = sentence.left
|
|
||||||
if (lNode != null && rNode != null) {
|
if (lNode != null && rNode != null) {
|
||||||
lNode.changedBy = rNode
|
rNode.changes.add(lNode)
|
||||||
if (funName != "-") {
|
|
||||||
lNode.upperFuncName = funName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} 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<TraceTree>())
|
||||||
|
if (rNode!= null) {
|
||||||
|
lNode.changes.add(rNode)
|
||||||
|
}
|
||||||
|
nodes.add(lNode)
|
||||||
|
paramIndex ++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodes.getDeepest()
|
|
||||||
|
// 去掉没有改过别人的
|
||||||
|
val result = mutableListOf<TraceTree>()
|
||||||
|
for (tree in nodes) {
|
||||||
|
if (!tree.changes.isEmpty()) {
|
||||||
|
result.add(tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<CFunction>.find(name: String): CFunction? {
|
||||||
|
this.forEach { if (it.name == name) return it }
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List<CFunction>.getInvokeTree
|
||||||
|
* @param List<CFunction>: 要求包含所有函数以查找
|
||||||
|
* @param name: 从哪个函数开始查找
|
||||||
|
* @return 特制的 TraceTree
|
||||||
|
*/
|
||||||
|
fun List<CFunction>.getInvokeTree(name: String): List<TraceTree> {
|
||||||
|
// 先找到开始的函数
|
||||||
|
val func = this.find(name)
|
||||||
|
if (func == null) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val invokeTrees = mutableListOf<TraceTree>()
|
||||||
|
val args = mutableListOf<String>()
|
||||||
|
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
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ class CLanguage {
|
||||||
CHANGE_VALUE, // identifier = RHAND
|
CHANGE_VALUE, // identifier = RHAND
|
||||||
DEFINE_VALUE_PARAM, // int a=b, 一直接在上一个后面
|
DEFINE_VALUE_PARAM, // int a=b, 一直接在上一个后面
|
||||||
CHANGE_VALUE_PARAM, // a = b
|
CHANGE_VALUE_PARAM, // a = b
|
||||||
|
PARAM, // 函数的参数初始化
|
||||||
RETURN // 字面意思
|
RETURN // 字面意思
|
||||||
}
|
}
|
||||||
enum class CTYPES {
|
enum class CTYPES {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
|
import core.CLanguage.Companion.OPERATION.*
|
||||||
|
|
||||||
class Sentence(val left: String, val right: String, val type: CLanguage.Companion.OPERATION)
|
class Sentence(val left: String, val right: String, val type: CLanguage.Companion.OPERATION)
|
||||||
|
|
||||||
class CParser(content: String, paramNameList: List<String>) {
|
class CParser(content: String, paramNameList: List<String>) {
|
||||||
|
@ -14,7 +16,13 @@ class CParser(content: String, paramNameList: List<String>) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// 把参数加进去
|
// 把参数加进去
|
||||||
defineList.addAll(paramNameList)
|
if (!paramNameList.isEmpty()) {
|
||||||
|
for (param in paramNameList) {
|
||||||
|
sentenceList.add(Sentence("@", param, PARAM))
|
||||||
|
defineList.add(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 第一轮解析获得基本语义
|
// 第一轮解析获得基本语义
|
||||||
content.split(';').forEach {
|
content.split(';').forEach {
|
||||||
val line = it.trim()
|
val line = it.trim()
|
||||||
|
@ -26,9 +34,9 @@ class CParser(content: String, paramNameList: List<String>) {
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
val leftHand = match.groupValues[1].trim().split(' ').last() // Left-hand side (variable)
|
val leftHand = match.groupValues[1].trim().split(' ').last() // Left-hand side (variable)
|
||||||
val rightHand = match.groupValues[2].trim() // Right-hand side (value)
|
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)
|
defineList.add(leftHand)
|
||||||
sentenceList.addAll(rightHandSimpleParser(rightHand, CLanguage.Companion.OPERATION.DEFINE_VALUE))
|
sentenceList.addAll(rightHandSimpleParser(rightHand, DEFINE_VALUE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // 重新定义
|
} else { // 重新定义
|
||||||
|
@ -36,13 +44,13 @@ class CParser(content: String, paramNameList: List<String>) {
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
val leftHand = match.groupValues[1].trim() // Left-hand side (variable)
|
val leftHand = match.groupValues[1].trim() // Left-hand side (variable)
|
||||||
val rightHand = match.groupValues[2].trim() // Right-hand side (value)
|
val rightHand = match.groupValues[2].trim() // Right-hand side (value)
|
||||||
sentenceList.add(Sentence(leftHand, rightHand, CLanguage.Companion.OPERATION.CHANGE_VALUE))
|
sentenceList.add(Sentence(leftHand, rightHand, CHANGE_VALUE))
|
||||||
sentenceList.addAll(rightHandSimpleParser(rightHand, CLanguage.Companion.OPERATION.CHANGE_VALUE))
|
sentenceList.addAll(rightHandSimpleParser(rightHand, CHANGE_VALUE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (line.contains("return")) { // return
|
} else if (line.contains("return")) { // return
|
||||||
val returnValue = line.split(' ').last()
|
val returnValue = line.split(' ').last()
|
||||||
sentenceList.add(Sentence("return", returnValue, CLanguage.Companion.OPERATION.RETURN))
|
sentenceList.add(Sentence("return", returnValue, RETURN))
|
||||||
} else { // 调用函数,解析参数就行了
|
} else { // 调用函数,解析参数就行了
|
||||||
val match = func_invoke_regex.find(line) // 如果是后面的就要这个
|
val match = func_invoke_regex.find(line) // 如果是后面的就要这个
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
|
@ -50,7 +58,7 @@ class CParser(content: String, paramNameList: List<String>) {
|
||||||
val args = match.groupValues[2].trim() // Right-hand side (value)
|
val args = match.groupValues[2].trim() // Right-hand side (value)
|
||||||
args.split(',').forEach { arg ->
|
args.split(',').forEach { arg ->
|
||||||
if (arg in defineList) { // 定义过的变量
|
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<String>) {
|
||||||
private fun rightHandSimpleParser(right: String, type: CLanguage.Companion.OPERATION): List<Sentence> { // 解析右边表达式的
|
private fun rightHandSimpleParser(right: String, type: CLanguage.Companion.OPERATION): List<Sentence> { // 解析右边表达式的
|
||||||
fun getType(): CLanguage.Companion.OPERATION {
|
fun getType(): CLanguage.Companion.OPERATION {
|
||||||
return when (type) { // 改变类型
|
return when (type) { // 改变类型
|
||||||
CLanguage.Companion.OPERATION.DEFINE_VALUE -> {
|
DEFINE_VALUE -> {
|
||||||
CLanguage.Companion.OPERATION.DEFINE_VALUE_PARAM
|
DEFINE_VALUE_PARAM
|
||||||
}
|
}
|
||||||
|
|
||||||
CLanguage.Companion.OPERATION.CHANGE_VALUE -> {
|
CHANGE_VALUE -> {
|
||||||
CLanguage.Companion.OPERATION.CHANGE_VALUE_PARAM
|
CHANGE_VALUE_PARAM
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
CLanguage.Companion.OPERATION.RETURN
|
RETURN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import core.CLanguage.Companion.OPERATION.*
|
||||||
class SourceFile {
|
class SourceFile {
|
||||||
companion object {
|
companion object {
|
||||||
val function_define_regex = """\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)\s*\{""".toRegex() // main(){ 匹配函数名
|
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 ->
|
it.cParser.sentenceList.forEach { sentence ->
|
||||||
when (sentence.type) {
|
when (sentence.type) {
|
||||||
CLanguage.Companion.OPERATION.FUNCTION_INVOCATION, CLanguage.Companion.OPERATION.RETURN -> {
|
FUNCTION_INVOCATION, RETURN -> {
|
||||||
if (useCache.isNotEmpty()) {
|
if (useCache.isNotEmpty()) {
|
||||||
funcResult.add(useCache.toString())
|
funcResult.add(useCache.toString())
|
||||||
useCache.clear() // 清空
|
useCache.clear() // 清空
|
||||||
|
@ -76,7 +78,7 @@ class SourceFile {
|
||||||
funcResult.add("${sentence.right}-use")
|
funcResult.add("${sentence.right}-use")
|
||||||
}
|
}
|
||||||
|
|
||||||
CLanguage.Companion.OPERATION.DEFINE_VALUE, CLanguage.Companion.OPERATION.CHANGE_VALUE -> {
|
DEFINE_VALUE, CHANGE_VALUE -> {
|
||||||
if (useCache.isNotEmpty()) {
|
if (useCache.isNotEmpty()) {
|
||||||
funcResult.add(useCache.toString())
|
funcResult.add(useCache.toString())
|
||||||
useCache.clear()
|
useCache.clear()
|
||||||
|
@ -84,9 +86,11 @@ class SourceFile {
|
||||||
useCache.append("${sentence.left}-def")
|
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")
|
useCache.append(";${sentence.right}-use")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PARAM -> {} // 参数只用于构造def-use跨函数
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (useCache.isNotEmpty()) {
|
if (useCache.isNotEmpty()) {
|
||||||
|
@ -103,11 +107,12 @@ fun main() {
|
||||||
val funcs = sourceFile.parseFunction()
|
val funcs = sourceFile.parseFunction()
|
||||||
funcs.forEach {
|
funcs.forEach {
|
||||||
println("${it.name}(${it.params}) -> ${it.returnType} {\n${it.content}\n} ")
|
println("${it.name}(${it.params}) -> ${it.returnType} {\n${it.content}\n} ")
|
||||||
// it.cParser.sentenceList.forEach{ s->
|
it.cParser.sentenceList.forEach{ s->
|
||||||
// println("${s.left},${s.right},${s.type}")
|
println("${s.left},${s.right},${s.type}")
|
||||||
// }
|
}
|
||||||
it.getTraceTree().print()
|
println(it.getTraceTree().getStringRepr())
|
||||||
}
|
}
|
||||||
|
println(funcs.getInvokeTree("main").getFuncRepr("main"))
|
||||||
|
|
||||||
println(sourceFile.getDef())
|
println(sourceFile.getDef())
|
||||||
println(sourceFile.getUse())
|
println(sourceFile.getUse())
|
||||||
|
|
|
@ -2,8 +2,12 @@ package core
|
||||||
|
|
||||||
data class TraceTree(
|
data class TraceTree(
|
||||||
val name: String,
|
val name: String,
|
||||||
var changedBy: TraceTree?,
|
var changes: MutableList<TraceTree>,
|
||||||
var upperFuncName: String?
|
)
|
||||||
|
|
||||||
|
data class InvokeInfo(
|
||||||
|
val caller: String,
|
||||||
|
val param: List<String>,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun List<TraceTree>.findNode(name: String): TraceTree? {
|
fun List<TraceTree>.findNode(name: String): TraceTree? {
|
||||||
|
@ -15,43 +19,35 @@ fun List<TraceTree>.findNode(name: String): TraceTree? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<TraceTree>.print() {
|
|
||||||
fun traceChain(node: TraceTree?): String {
|
fun List<TraceTree>.getStringRepr(): String {
|
||||||
return if (node == null) {
|
fun getChanges(node: TraceTree, currentPath: String = node.name): String {
|
||||||
"" // 读取完了
|
val paths = mutableListOf<String>()
|
||||||
|
|
||||||
|
// 没修改过就介绍
|
||||||
|
if (node.changes.isEmpty()) {
|
||||||
|
paths.add(currentPath)
|
||||||
} else {
|
} else {
|
||||||
traceChain(node.changedBy) + if (node.changedBy != null) {
|
// 挨个获取 change
|
||||||
"->"
|
for (child in node.changes) {
|
||||||
} else {
|
paths.add(getChanges(child, "$currentPath->${child.name}"))
|
||||||
""
|
}
|
||||||
} + node.name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 合为一个 String
|
||||||
|
return paths.joinToString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.forEach { traceTree ->
|
val result = StringBuilder()
|
||||||
println(traceChain(traceTree))
|
this.forEach {
|
||||||
|
result.append(getChanges(it))
|
||||||
|
result.append('\n')
|
||||||
}
|
}
|
||||||
|
result.dropLast(1)
|
||||||
|
return result.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<TraceTree>.getDeepest(): List<TraceTree> {
|
fun List<TraceTree>.getFuncRepr(func: String): String {
|
||||||
// 使用 Map 记录每个节点的深度
|
val strs = this.getStringRepr()
|
||||||
val depthMap = mutableMapOf<TraceTree, Int>()
|
return strs.split('\n').filter { it.startsWith(func) }.joinToString("\n")
|
||||||
|
}
|
||||||
// 计算每个节点的深度(从终点向上追溯)
|
|
||||||
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()
|
|
||||||
}
|
|
Loading…
Reference in a new issue