diff --git a/.idea/misc.xml b/.idea/misc.xml index f2a2ad2..b2652fc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/src/main/kotlin/core/CFunction.kt b/src/main/kotlin/core/CFunction.kt index d57d9b7..68cb69c 100644 --- a/src/main/kotlin/core/CFunction.kt +++ b/src/main/kotlin/core/CFunction.kt @@ -2,6 +2,7 @@ package core import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.typenameToTypeEnum +import utils.Helper.Companion.antiC class CFunction( val name: String, source: String // 函数名 @@ -34,13 +35,27 @@ class CFunction( paramNameList = if (paramsList.isNullOrEmpty() || paramsList.first().isEmpty()) { emptyList() } else { - paramsList.map { it.split(' ').last() } + paramsList.map { + val param = it.split(' ').last() + val name = if (param.contains('`')) { // struct`*po -> *po) + param.split('`').last() + }else{ + param + } + antiC(name) + } } return paramsList?.map { param -> - val parts = param.split(" ") - val type = typenameToTypeEnum(parts[0]) ?: return@map emptyMap() - val name = parts.getOrNull(1) ?: "" - mapOf(name to type) + if (param.contains('`')){ // struct`*po -> *po + val name = antiC(param.split(' ').last()) + val type = CLanguage.Companion.TYPES.void + mapOf(name to type) + }else { + val parts = param.split(" ") + val type = typenameToTypeEnum(parts[0]) ?: return@map emptyMap() + val name = antiC(parts.getOrNull(1) ?: "") + mapOf(name to type) + } } } diff --git a/src/main/kotlin/core/CLanguage.kt b/src/main/kotlin/core/CLanguage.kt index 874b4c4..bf29e33 100644 --- a/src/main/kotlin/core/CLanguage.kt +++ b/src/main/kotlin/core/CLanguage.kt @@ -2,7 +2,7 @@ package core class CLanguage { companion object { - val types = listOf("void", "char", "int", "short", "long", "float", "double", "struct") + var types = mutableListOf("void", "char", "int", "short", "long", "float", "double") enum class OPERATION { DEFINE_VALUE, // `type` identifier = RHand 题目里 def-use @@ -11,7 +11,8 @@ class CLanguage { DEFINE_VALUE_PARAM, // int a=b, 一直接在上一个后面 CHANGE_VALUE_PARAM, // a = b PARAM, // 函数的参数初始化 - RETURN // 字面意思 + RETURN, // 字面意思 + IF_PARAM, } @Suppress("EnumEntryName") diff --git a/src/main/kotlin/core/CParser.kt b/src/main/kotlin/core/CParser.kt index 7a6a337..703370b 100644 --- a/src/main/kotlin/core/CParser.kt +++ b/src/main/kotlin/core/CParser.kt @@ -1,6 +1,7 @@ package core import core.CLanguage.Companion.OPERATION.* +import utils.Helper.Companion.antiC class Sentence(val left: String, val right: String, val type: CLanguage.Companion.OPERATION) @@ -50,13 +51,19 @@ class CParser(content: String, paramNameList: List) { } else if (line.contains("return")) { // return val returnValue = line.split(' ').last() sentenceList.add(Sentence("return", returnValue, RETURN)) + } else if (line.startsWith("if")){ + val args = line.split('(').last().split(')').first() + args.split(',').forEach { arg -> + sentenceList.add(Sentence("if",arg.trim(),IF_PARAM)) + } } else { // 调用函数,解析参数就行了 val match = func_invoke_regex.find(line) // 如果是后面的就要这个 if (match != null) { val funcName = match.groupValues[1].trim().split(' ').last() // Left-hand side (variable) val args = match.groupValues[2].trim() // Right-hand side (value) - args.split(',').forEach { arg -> - if (arg in defineList) { // 定义过的变量 + args.split(',').forEach { ar -> + var arg = antiC(ar).trim() + if (arg.split('.').first() in defineList) { // 定义过的变量 sentenceList.add(Sentence(funcName, arg, FUNCTION_INVOCATION)) } } @@ -90,16 +97,16 @@ class CParser(content: String, paramNameList: List) { val funName = match.groupValues[1].trim() val params = match.groupValues[2].trim().split(',') for (param in params) { - if (param.trim() in defineList) { // 定义过的才操作 - result.add(Sentence(funName, param.trim(), getType())) + if (antiC(param.trim()) in defineList) { // 定义过的才操作 + result.add(Sentence(funName, antiC(param.trim()), getType())) } } } } else { - if (right in defineList) { // 看看有没有使用值 + if (antiC(right) in defineList) { // 看看有没有使用值 result.add( Sentence( - "-", right, getType() + "-", antiC(right), getType() ) ) } else { // 看是不是有运算符号 diff --git a/src/main/kotlin/core/SourceFile.kt b/src/main/kotlin/core/SourceFile.kt index 6d8aaf5..0016a5e 100644 --- a/src/main/kotlin/core/SourceFile.kt +++ b/src/main/kotlin/core/SourceFile.kt @@ -4,6 +4,7 @@ import java.io.File import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.declarationRegex import core.CLanguage.Companion.types +import utils.Helper.Companion.transformIfStatement class SourceFile { @Suppress("unused") // IDE 错误 @@ -96,9 +97,30 @@ class SourceFile { noDefine.append(noFuncInDefine) } + val noFor = StringBuilder() + var hasFor = false + noDefine.lines().forEach { line -> + if (line.trim().startsWith("for")) { + val useful = line.trim().split('(').last().split(';').first() + noFor.append("$useful;\n") + hasFor = true + } else { + if (hasFor) { + if (line.trim().startsWith('}')) { + hasFor = false + } else { + noFor.append(line + '\n') + } + } else { + noFor.append(line + '\n') + } + } + } + + // 将 int a = 1, b=2,c=3;这样的行变为 int a = 1; int b =2; int c = 3; 方便分析 val noContinueValue = StringBuilder() - noDefine.lines().forEach { line -> + noFor.toString().lines().forEach { line -> if (line.contains('=') && line.contains(',')// 或许是连续赋值 && !line.contains('{') // 不是函数调用 && line.trim().matches(declarationRegex) // 满足像是连续赋值的样子 @@ -119,23 +141,91 @@ class SourceFile { noContinueValue.append("$identifier $part;") } } else { - noContinueValue.append(line) + noContinueValue.append("$line\n") } } else { - noContinueValue.append(line) + noContinueValue.append("$line\n") + } + } else if (line.trim().split(' ').first() in types && line.contains(';') && !line.contains('(') && !line.contains('=')) { + val paras = line.trim().split(' ').drop(1).joinToString("").split(';').first().split(',') + val type = line.trim().split(' ').first() + paras.forEach { param -> + noContinueValue.append("$type $param=0;\n") } } else { - noContinueValue.append(line) + noContinueValue.append("$line\n") } } - return noContinueValue.toString() + val noIf = StringBuilder() + var hasIf = false + noContinueValue.lines().forEach { line -> + if (line.trim().startsWith("if")) { + noIf.append(transformIfStatement(line + '\n')) + hasIf = true + } else { + if (hasIf && line.trim().startsWith('}')) { + hasIf = false + } else { + noIf.append("$line\n") + } + } + } + + // 处理 Struct + val noStruct = StringBuilder() + noIf.lines().forEach { line -> + if (line.trim().contains("struct")){ + if (line.split('{').last().split(' ').first() in types){ // 定义结构体 + val structName = line.trim().split(' ')[1].split('{').first() + types.add("struct`$structName") + }else{ + val parts = line.replace("(","( ").split(' ') + val res = StringBuilder() + var findStruct = false + parts.forEach { part -> + if (part.contains("struct")){ + findStruct = true + }else if (findStruct == false){ + res.append("$part ") + }else { + res.append("struct`$part ") + findStruct = false + } + } + noStruct.append("$res\n") + } + }else if(line.isNotEmpty()){ + noStruct.append(line.trim()+'\n') + } + } + + + // 修复创建 struct + val fixStruct = StringBuilder() + for (line in noStruct.toString().replace(";",";\n").lines()) { + if (line.contains('`') && line.contains('{') && line.contains('=')){ // 含有创建struct + // struct`Point p1 = {1, 2}; + val left = line.split('=').first() + fixStruct.append("$left= struct_define_value;\n") + }else if (line.isNotEmpty()){ + fixStruct.append("$line\n") + } + } + + return fixStruct.toString() .replace(";;", ";") + .replace(" "," ") .replace(";", ";\n") .replace("{", "{\n") .replace("}", "}\n") .replace(" =", "=") .replace("= ", "=") + .replace("\n\n","\n") + .replace("\n\n","\n") + .replace("->",".") + .replace("( ","(") + .replace("\".*\"".toRegex(),"\"string_literal\"") } } @@ -190,7 +280,6 @@ class SourceFile { val globalResult = mutableMapOf>() functions.forEach { val funcResult = mutableListOf() - // 第一个处理参数 if (it.paramNameList.isEmpty()) { funcResult.add("void") @@ -202,24 +291,53 @@ class SourceFile { // 后面的 val useCache = StringBuilder() + var useFuncName: String = "" + val ifCache = StringBuilder() + + fun invalidCache(){ + if (useCache.isNotEmpty()) { + funcResult.add(useCache.toString()) + useCache.clear() // 清空 + } + if (ifCache.isNotEmpty()) { + funcResult.add(ifCache.toString().dropLast(1)) + ifCache.clear() + } + } it.cParser.sentenceList.forEach { sentence -> when (sentence.type) { - FUNCTION_INVOCATION, RETURN -> { - if (useCache.isNotEmpty()) { + FUNCTION_INVOCATION -> { + invalidCache() + if (useFuncName != sentence.left && useFuncName.isNotEmpty()){ + useFuncName = sentence.left funcResult.add(useCache.toString()) useCache.clear() // 清空 } + if (sentence.right in it.cParser.defineList) { + useCache.append("${sentence.right}-use;") + }else if (sentence.right.contains('.')) { + val param = sentence.right.split('.').first() + if (param in it.cParser.defineList){ + useCache.append("${param}-use;") + } + } + } + + RETURN -> { + invalidCache() if (sentence.right in it.cParser.defineList) { funcResult.add("${sentence.right}-use") + }else if (sentence.right.contains('.')) { + val param = sentence.right.split('.').first() + if (param in it.cParser.defineList){ + funcResult.add("${param}-use") + } } } DEFINE_VALUE, CHANGE_VALUE -> { - if (useCache.isNotEmpty()) { - funcResult.add(useCache.toString()) - useCache.clear() - } + invalidCache() useCache.append("${sentence.left}-def") } @@ -227,11 +345,19 @@ class SourceFile { useCache.append(";${sentence.right}-use") } + IF_PARAM -> { + if (useCache.isNotEmpty()) { + funcResult.add(useCache.toString()) + useCache.clear() + } + ifCache.append("${sentence.right}-use;") + } + PARAM -> {} // 参数只用于构造def-use跨函数 } } if (useCache.isNotEmpty()) { - funcResult.add(useCache.toString()) + funcResult.add(useCache.toString())s } globalResult[it.name] = funcResult } diff --git a/src/main/kotlin/utils/Helper.kt b/src/main/kotlin/utils/Helper.kt new file mode 100644 index 0000000..c9e3a8e --- /dev/null +++ b/src/main/kotlin/utils/Helper.kt @@ -0,0 +1,18 @@ +package utils + +class Helper { + companion object{ + fun transformIfStatement(input: String): String { + val regex = Regex("""\bif\s*\(\s*([^)]+)\s*\)\s*\{""") + return input.replace(regex) { matchResult -> + val condition = matchResult.groupValues[1] + val modifiedCondition = condition.replace(Regex("""\s*[><=!]+\s*"""), ",") + "if($modifiedCondition);\n" + } + } + + // 解决引用解引用 + fun antiC(string: String): String = string.replace("*","") + .replace("&","") + } +} \ No newline at end of file