Compare commits
2 commits
fa9ff80214
...
9c75f37409
Author | SHA1 | Date | |
---|---|---|---|
9c75f37409 | |||
20956c52fd |
8 changed files with 110 additions and 67 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_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>
|
|
@ -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;
|
|
||||||
//}
|
|
|
@ -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 !in cParser.defineList && 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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -14,7 +14,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 +31,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 +72,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)
|
|
||||||
}
|
|
|
@ -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> { // 找所有的函数定义
|
||||||
|
@ -118,8 +160,7 @@ fun main() {
|
||||||
relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr()))
|
relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr()))
|
||||||
}
|
}
|
||||||
println(funcs.getInvokeTree("main").getFuncRepr("main"))
|
println(funcs.getInvokeTree("main").getFuncRepr("main"))
|
||||||
println(sourceFile.getDef())
|
|
||||||
println(sourceFile.getUse())
|
|
||||||
println(generateGraph(relations))
|
println(generateGraph(relations))
|
||||||
println(funcs.getInvokeGraph("main"))
|
println(funcs.getInvokeGraph("main"))
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,15 @@ fun List<TraceTree>.getStringRepr(): String {
|
||||||
|
|
||||||
fun Map<String, List<TraceTree>>.getFuncRepr(func: String): String {
|
fun Map<String, List<TraceTree>>.getFuncRepr(func: String): String {
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
|
var fName = ""
|
||||||
this.forEach { (name, list) ->
|
this.forEach { (name, list) ->
|
||||||
result.append("$name:")
|
fName = name
|
||||||
val listRepr = list.getStringRepr()
|
val listRepr = list.getStringRepr()
|
||||||
result.append(listRepr.split('\n').filter { it.startsWith(func) }.joinToString("\n"))
|
result.append(listRepr.split('\n').filter { it.startsWith(func) }.joinToString("\n"))
|
||||||
}
|
}
|
||||||
return result.toString()
|
val fixedResult = StringBuilder()
|
||||||
|
result.lines().forEach { line ->
|
||||||
|
fixedResult.append("$fName:$line\n")
|
||||||
|
}
|
||||||
|
return fixedResult.toString()
|
||||||
}
|
}
|
Loading…
Reference in a new issue