This commit is contained in:
Kagura 2024-10-30 09:37:32 +08:00
parent fa9ff80214
commit 20956c52fd
7 changed files with 104 additions and 63 deletions

View file

@ -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_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_23" 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>

View file

@ -1,19 +1,10 @@
int main(){ int main(){
int x=0,y =0; int a = 0,b=1;
int z =1; int k = add(a,b);
printf("%d\n",z);//用户输入 print(k)
x= A(z);
y= x;
printf("%d\n",y);//main函数尾部
} }
int A(int a){ int add(int a, int b){
int m = a; int c = a+b;
return m; return c;
} }
//char Test(int para1,char para2){
// int c1 = para1, i_doNothingbuttest = 2;
// c1 = para2;
// return c2;
//}

View file

@ -84,22 +84,27 @@ class CFunction(
// y,x,CHANGE_VALUE // y,x,CHANGE_VALUE
// -,x,CHANGE_VALUE_PARAM // -,x,CHANGE_VALUE_PARAM
if (index > 0) { // 按理来说肯定成立,加个检查防止意外 if (index > 0) { // 按理来说肯定成立,加个检查防止意外
val left = cParser.sentenceList[index - 1].left var i = 0
var left = cParser.sentenceList[index - 1].left
while (left == "-" && index - i >= 0) {
left = cParser.sentenceList[index - i].left
i++
}
val lNode = nodes.findNode(left) val lNode = nodes.findNode(left)
val rNode = nodes.findNode(sentence.right) val rNode = nodes.findNode(sentence.right)
if (lNode != null && rNode != null) { if (lNode != null && rNode != null) {
rNode.changes.add(lNode) rNode.changes.add(lNode)
} }
} }
} else if (sentence.type == PARAM && invokeInfo != null){ } else if (sentence.type == PARAM && invokeInfo != null) {
if (invokeInfo.param.lastIndex >= paramIndex){ // 在 InvokeTree 里面 if (invokeInfo.param.lastIndex >= paramIndex) { // 在 InvokeTree 里面
val rNode = nodes.findNode(sentence.right) val rNode = nodes.findNode(sentence.right)
val lNode = TraceTree("${invokeInfo.caller}:${invokeInfo.param[paramIndex]}",mutableListOf<TraceTree>()) val lNode = TraceTree("${invokeInfo.caller}:${invokeInfo.param[paramIndex]}", mutableListOf<TraceTree>())
if (rNode!= null) { if (rNode != null) {
lNode.changes.add(rNode) lNode.changes.add(rNode)
} }
nodes.add(lNode) nodes.add(lNode)
paramIndex ++ paramIndex++
} }
} }
} }
@ -127,14 +132,14 @@ fun List<CFunction>.find(name: String): CFunction? {
* @param name: 从哪个函数开始查找 * @param name: 从哪个函数开始查找
* @return 特制的 TraceTree * @return 特制的 TraceTree
*/ */
fun List<CFunction>.getInvokeTree(name: String): Map<String,List<TraceTree>> { fun List<CFunction>.getInvokeTree(name: String): Map<String, List<TraceTree>> {
// 先找到开始的函数 // 先找到开始的函数
val func = this.find(name) ?: return emptyMap() val func = this.find(name) ?: return emptyMap()
val invokeTrees = mutableListOf<TraceTree>() val invokeTrees = mutableListOf<TraceTree>()
val args = mutableListOf<String>() val args = mutableListOf<String>()
var funcName = "" var funcName = ""
val resultMap = mutableMapOf<String,List<TraceTree>>() val resultMap = mutableMapOf<String, List<TraceTree>>()
func.cParser.sentenceList.forEach { sentence -> func.cParser.sentenceList.forEach { sentence ->
// 🌰: // 🌰:
@ -144,10 +149,10 @@ fun List<CFunction>.getInvokeTree(name: String): Map<String,List<TraceTree>> {
args.add(sentence.right) args.add(sentence.right)
funcName = sentence.left funcName = sentence.left
} }
}else{ // 更新 } else { // 更新
val function = this.find(funcName) val function = this.find(funcName)
if (function!=null) { if (function != null) {
val info = InvokeInfo(name,args) val info = InvokeInfo(name, args)
val tt = function.getTraceTree(info) val tt = function.getTraceTree(info)
invokeTrees.addAll(tt) invokeTrees.addAll(tt)
} }

View file

@ -2,7 +2,8 @@ package core
class CLanguage { class CLanguage {
companion object { companion object {
val types = listOf("void","char","int","short","long","float","double","struct") val types = listOf("void", "char", "int", "short", "long", "float", "double", "struct")
enum class OPERATION { enum class OPERATION {
DEFINE_VALUE, // `type` identifier = RHand 题目里 def-use DEFINE_VALUE, // `type` identifier = RHand 题目里 def-use
FUNCTION_INVOCATION, // func(value-param) 题目里 FUNCTION_INVOCATION, // func(value-param) 题目里
@ -12,6 +13,7 @@ class CLanguage {
PARAM, // 函数的参数初始化 PARAM, // 函数的参数初始化
RETURN // 字面意思 RETURN // 字面意思
} }
enum class CTYPES { enum class CTYPES {
void, void,
char, char,
@ -23,6 +25,9 @@ class CLanguage {
struct struct
} }
val typeRegex = types.joinToString("|") { "\\b$it\\b" }
val declarationRegex = Regex("($typeRegex)\\s+([^;]+);")
fun typenameToTypeEnum(typename: String): CTYPES? { fun typenameToTypeEnum(typename: String): CTYPES? {
return when (typename) { return when (typename) {
"void" -> CTYPES.void "void" -> CTYPES.void

View file

@ -9,6 +9,8 @@ class CParser(content: String, paramNameList: List<String>) {
companion object { companion object {
val lrexp_regex = "(.*)[ ]?=[ ]?(.*)[ ]?;?$".toRegex() // 左1右2 val lrexp_regex = "(.*)[ ]?=[ ]?(.*)[ ]?;?$".toRegex() // 左1右2
val func_invoke_regex = "(.*)[ ]?\\((.*)\\)[ ]?$".toRegex() // 匹配到的是1:函数名2:参数列表 val func_invoke_regex = "(.*)[ ]?\\((.*)\\)[ ]?$".toRegex() // 匹配到的是1:函数名2:参数列表
val c_op_list = listOf("+", "-", "*", "/", "%", "<<", ">>")
} }
val sentenceList = mutableListOf<Sentence>() val sentenceList = mutableListOf<Sentence>()
@ -29,16 +31,15 @@ class CParser(content: String, paramNameList: List<String>) {
if (line.contains('=')) { // 出现了left hand 和 right hand if (line.contains('=')) { // 出现了left hand 和 right hand
if (line.split(' ').first() in CLanguage.types) { // 最开始是一个 type if (line.split(' ').first() in CLanguage.types) { // 最开始是一个 type
// 说明这是一个 define 语句 // 说明这是一个 define 语句
line.split(',').forEach { val match = lrexp_regex.find(" " + line) // 如果是后面的就要这个
val match = lrexp_regex.find(" " + it.trim()) // 如果是后面的就要这个 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, DEFINE_VALUE))
sentenceList.add(Sentence(leftHand, rightHand, DEFINE_VALUE)) defineList.add(leftHand)
defineList.add(leftHand) sentenceList.addAll(rightHandSimpleParser(rightHand, DEFINE_VALUE))
sentenceList.addAll(rightHandSimpleParser(rightHand, DEFINE_VALUE))
}
} }
} else { // 重新定义 } else { // 重新定义
val match = lrexp_regex.find(line.trim()) val match = lrexp_regex.find(line.trim())
if (match != null) { if (match != null) {
@ -96,13 +97,23 @@ class CParser(content: String, paramNameList: List<String>) {
} }
} }
} }
} else { }
else {
if (right in defineList) { // 看看有没有使用值 if (right in defineList) { // 看看有没有使用值
result.add( result.add(
Sentence( Sentence(
"-", right, getType() "-", right, getType()
) )
) )
} else{ // 看是不是有运算符号
for (op in c_op_list){
if (op in right){
val splits = right.split(op)
splits.forEach { split ->
result.addAll(rightHandSimpleParser(split.trim(),type))
}
}
}
} }
} }
return result return result

View file

@ -1,5 +1,7 @@
package core package core
import kotlin.math.abs
data class Relation(val from: String, val to: String) data class Relation(val from: String, val to: String)
fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<String>? = null): String { fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<String>? = null): String {
@ -14,7 +16,8 @@ fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<
for (relation in edges) { for (relation in edges) {
uniquePaths.add("${relation.from} -> ${relation.to}") uniquePaths.add("${relation.from} -> ${relation.to}")
sb.append(" ${relation.from} -> ${relation.to};\n") sb.append("${relation.from}$label[label=${relation.from}];\n${relation.to}$label[label=${relation.to}];\n")
sb.append("${relation.from}$label -> ${relation.to}$label;\n")
} }
sb.append(" }\n") sb.append(" }\n")
@ -30,7 +33,7 @@ fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<
val fromNode = subPath[0] // 这里就是z val fromNode = subPath[0] // 这里就是z
val toNode = subPath[1] // 下一个就是 val toNode = subPath[1] // 下一个就是
// from 到 to 用虚线 // from 到 to 用虚线
sb.append(" $fromNode -> $toNode [style=dashed];\n") sb.append(" $fromNode${parts[1]} -> $toNode${parts[0]} [style=dashed];\n")
} }
} }
} }
@ -71,21 +74,5 @@ fun List<CFunction>.getInvokeGraph(funcName: String): String {
} }
val crossLabelPaths = this.getInvokeTree(func.name).getFuncRepr(func.name) val crossLabelPaths = this.getInvokeTree(func.name).getFuncRepr(func.name)
return generateGraph(relations,crossLabelPaths.split('\n')) return generateGraph(relations,crossLabelPaths.split('\n')) + "\n"
} }
fun main() {
val relations = mapOf(
"main" to listOf(
Relation("x", "y"),
Relation("z", "x"),
Relation("c", "d")
),
"A" to listOf(
Relation("a", "m")
)
)
val graphCode = generateGraph(relations)
println(graphCode)
}

View file

@ -4,6 +4,8 @@ package core
import java.io.File import java.io.File
import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.OPERATION.*
import core.CLanguage.Companion.declarationRegex
import core.CLanguage.Companion.types
import utils.getDefineList import utils.getDefineList
import utils.getUseList import utils.getUseList
@ -11,13 +13,53 @@ 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(){ 匹配函数名
fun deleteNotes(src: String): String { fun formatSource(src: String): String {
return src.lines() val noComment = src.lines()
.filter { line -> !line.trimStart().startsWith("#include") && !line.trimStart().startsWith("//") } .filter { line -> !line.trimStart().startsWith("#include") && !line.trimStart().startsWith("//") }
.joinToString("\n") { line -> .joinToString("\n") { line ->
val withoutTrailingComment = line.replace(Regex("//.*$"), "") val withoutTrailingComment = line.replace(Regex("//.*$"), "")
withoutTrailingComment.trimStart() withoutTrailingComment.trimStart()
} }
val noContinueValue = StringBuilder()
noComment.lines().forEach { line ->
if (line.contains('=') && line.contains(',')){ // 或许是连续赋值
if (!line.contains('{')){ // 不是函数调用
if (line.trim().matches(declarationRegex)){ // 满足像是连续赋值的样子
val splits = line.split(' ')
val identifier = splits.first()
val remain = splits.drop(1).joinToString(" ")
if (identifier in types){ // 获取标识符
val parts = remain.split(',') // 逗号分开
var allHasEqual = true
for (part in parts){
if (!part.contains('=')){
allHasEqual = false
}
}
if (allHasEqual){
parts.forEach { part ->
noContinueValue.append("$identifier $part;")
}
}else{
noContinueValue.append(line)
}
}else{
noContinueValue.append(line)
}
}else{
noContinueValue.append(line)
}
}else{
noContinueValue.append(line)
}
}else{
noContinueValue.append(line)
}
}
return noContinueValue
.toString()
.replace(";;",";")
.replace(";",";\n")
} }
} }
@ -28,11 +70,11 @@ class SourceFile {
if (!file.isFile) { if (!file.isFile) {
throw NoSuchFileException(file) throw NoSuchFileException(file)
} }
content = deleteNotes(file.readText()) content = formatSource(file.readText())
} }
constructor(content: String) { constructor(content: String) {
this.content = deleteNotes(content.trim()) this.content = formatSource(content.trim())
} }
fun parseFunction(): List<CFunction> { // 找所有的函数定义 fun parseFunction(): List<CFunction> { // 找所有的函数定义