import tkinter as tk
from tkinter import scrolledtext, ttk, messagebox
import os
import subprocess
import sys
import urllib.request
import logging
from datetime import datetime
import tempfile
import antlr4
from antlr4 import InputStream, CommonTokenStream, ParseTreeWalker
class SimpleCLexer(antlr4.Lexer):
def __init__(self, input=None):
super().__init__(input)
self.tokens = []
self._interp = None
def getAllTokens(self):
if not self.tokens:
self.tokens = self.tokenize(self._input)
return self.tokens
def tokenize(self, input_str):
# 简化的词法分析器实现
tokens = []
pos = 0
line = 1
column = 0
# 定义C语言的关键词和类型
keywords = {
'void', 'int', 'char', 'float', 'double', 'short', 'long', 'signed', 'unsigned',
'struct', 'union', 'enum', 'typedef', 'static', 'extern', 'auto', 'register',
'const', 'volatile', 'return', 'if', 'else', 'switch', 'case', 'default', 'for',
'while', 'do', 'break', 'continue', 'goto', 'sizeof'
}
types = {'U1', 'U2', 'U4', 'S1', 'S2', 'S4'}
while pos < len(input_str):
# 跳过空白字符
if input_str[pos] in ' \t':
pos += 1
column += 1
continue
# 处理换行
if input_str[pos] == '\n':
line += 1
column = 0
pos += 1
continue
# 处理注释
if input_str.startswith('//', pos):
end = input_str.find('\n', pos)
if end == -1:
end = len(input_str)
pos = end
continue
if input_str.startswith('/*', pos):
end = input_str.find('*/', pos)
if end == -1:
end = len(input_str)
else:
end += 2
pos = end
continue
# 处理标识符
if input_str[pos].isalpha() or input_str[pos] == '_':
start = pos
pos += 1
while pos < len(input_str) and (input_str[pos].isalnum() or input_str[pos] == '_'):
pos += 1
token_text = input_str[start:pos]
token_type = 'IDENTIFIER'
# 检查是否为关键字或类型
if token_text in keywords:
token_type = 'KEYWORD'
elif token_text in types:
token_type = 'TYPE'
tokens.append({
'type': token_type,
'text': token_text,
'line': line,
'column': column
})
column += (pos - start)
continue
# 处理数字
if input_str[pos].isdigit():
start = pos
pos += 1
while pos < len(input_str) and (input_str[pos].isdigit() or input_str[pos] in '.xXabcdefABCDEF'):
pos += 1
tokens.append({
'type': 'NUMBER',
'text': input_str[start:pos],
'line': line,
'column': column
})
column += (pos - start)
continue
# 处理字符串
if input_str[pos] == '"':
start = pos
pos += 1
while pos < len(input_str) and input_str[pos] != '"':
if input_str[pos] == '\\' and pos + 1 < len(input_str):
pos += 2
else:
pos += 1
if pos < len(input_str) and input_str[pos] == '"':
pos += 1
tokens.append({
'type': 'STRING',
'text': input_str[start:pos],
'line': line,
'column': column
})
column += (pos - start)
continue
# 处理字符
if input_str[pos] == "'":
start = pos
pos += 1
while pos < len(input_str) and input_str[pos] != "'":
if input_str[pos] == '\\' and pos + 1 < len(input_str):
pos += 2
else:
pos += 1
if pos < len(input_str) and input_str[pos] == "'":
pos += 1
tokens.append({
'type': 'CHAR',
'text': input_str[start:pos],
'line': line,
'column': column
})
column += (pos - start)
continue
# 处理运算符和标点符号
operators = {
'(', ')', '{', '}', '[', ']', ';', ',', '.', '->',
'++', '--', '&', '*', '+', '-', '~', '!',
'/', '%', '<<', '>>', '<', '>', '<=', '>=', '==', '!=',
'^', '|', '&&', '||', '?', ':', '=', '+=', '-=', '*=',
'/=', '%=', '<<=', '>>=', '&=', '^=', '|=', ','
}
# 尝试匹配最长的运算符
matched = False
for op_len in range(3, 0, -1):
if pos + op_len <= len(input_str) and input_str[pos:pos+op_len] in operators:
tokens.append({
'type': 'OPERATOR',
'text': input_str[pos:pos+op_len],
'line': line,
'column': column
})
pos += op_len
column += op_len
matched = True
break
if matched:
continue
# 无法识别的字符
tokens.append({
'type': 'UNKNOWN',
'text': input_str[pos],
'line': line,
'column': column
})
pos += 1
column += 1
return tokens
class FunctionAnalyzer:
def __init__(self):
self.function_name = ""
self.parameters = set()
self.local_vars = []
self.global_vars = []
self.function_calls = []
self.current_function = None
self.in_function = False
self.in_global_scope = True
self.variable_declarations = {}
self.control_structures = {"if", "for", "while", "switch", "return", "else"}
self.current_line = 0
self.macro_definitions = set()
self.parameter_lines = {}
self.type_aliases = {"U1", "U2", "U4", "S1", "S2", "S4"}
self.in_function_body = False
self.brace_depth = 0
self.recorded_globals = set()
def analyze(self, tokens):
self.tokens = tokens
self.pos = 0
self.current_line = 0
# 第一步:识别宏定义(全大写标识符)
self._identify_macros()
# 第二步:分析函数体
while self.pos < len(self.tokens):
token = self.tokens[self.pos]
self.current_line = token['line']
# 检测函数定义
if token['text'] in {'void', 'int', 'char', 'float', 'double', 'U1', 'U2', 'U4', 'S1', 'S2', 'S4', 'static'}:
if self._is_function_definition():
self._handle_function_definition()
continue
# 在函数体内检测变量声明
if self.in_function_body:
if token['text'] in {'U1', 'U2', 'U4', 'S1', 'S2', 'S4', 'int', 'char', 'float', 'double'}:
self._handle_variable_declaration()
continue
# 检测函数调用
if token['type'] == 'IDENTIFIER' and self.pos + 1 < len(self.tokens):
next_token = self.tokens[self.pos + 1]
if next_token['text'] == '(':
self._handle_function_call()
continue
# 检测变量使用
if token['type'] == 'IDENTIFIER':
self._handle_identifier_use(token)
# 跟踪大括号深度
if token['text'] == '{':
self.brace_depth += 1
if self.in_function and self.brace_depth == 1:
self.in_function_body = True
elif token['text'] == '}':
self.brace_depth -= 1
if self.brace_depth == 0 and self.in_function:
self.in_function = False
self.in_function_body = False
self.pos += 1
return self
def _identify_macros(self):
"""识别宏定义(全大写标识符)"""
for token in self.tokens:
if token['type'] == 'IDENTIFIER' and token['text'].isupper():
self.macro_definitions.add(token['text'])
def _is_function_definition(self):
# 检查是否是函数定义
pos = self.pos
depth = 0
found_name = False
# 跳过可能的static修饰符
if self.tokens[pos]['text'] == 'static':
pos += 1
# 检查返回类型
if self.tokens[pos]['text'] not in {'void', 'int', 'char', 'float', 'double', 'U1', 'U2', 'U4', 'S1', 'S2', 'S4'}:
return False
pos += 1
# 检查函数名
if pos < len(self.tokens) and self.tokens[pos]['type'] == 'IDENTIFIER':
found_name = True
pos += 1
else:
return False
# 检查左括号
if pos < len(self.tokens) and self.tokens[pos]['text'] == '(':
depth = 1
pos += 1
else:
return False
# 检查参数列表和右括号
while pos < len(self.tokens) and depth > 0:
token = self.tokens[pos]
if token['text'] == '(':
depth += 1
elif token['text'] == ')':
depth -= 1
if depth == 0:
# 检查后面是否是 {
if pos + 1 < len(self.tokens) and self.tokens[pos + 1]['text'] == '{':
return True
return False
pos += 1
return False
def _handle_function_definition(self):
# 跳过可能的static修饰符
if self.tokens[self.pos]['text'] == 'static':
self.pos += 1
# 提取返回类型
return_type = self.tokens[self.pos]['text']
self.pos += 1
# 获取函数名
if self.pos < len(self.tokens) and self.tokens[self.pos]['type'] == 'IDENTIFIER':
func_name = self.tokens[self.pos]['text']
self.pos += 1
# 跳过左括号
if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '(':
self.pos += 1
depth = 1
current_param = []
params = []
# 提取参数
while self.pos < len(self.tokens) and depth > 0:
token = self.tokens[self.pos]
if token['text'] == '(':
depth += 1
elif token['text'] == ')':
depth -= 1
if depth == 0:
break
elif token['text'] == ',' and depth == 1:
# 参数结束
if current_param:
# 提取参数名(最后一个标识符)
param_name = None
for t in reversed(current_param):
if t['type'] == 'IDENTIFIER':
param_name = t['text']
break
if param_name:
params.append(param_name)
self.parameter_lines[param_name] = token['line']
current_param = []
self.pos += 1
continue
current_param.append(token)
self.pos += 1
# 处理最后一个参数
if current_param:
param_name = None
for t in reversed(current_param):
if t['type'] == 'IDENTIFIER':
param_name = t['text']
break
if param_name:
params.append(param_name)
self.parameter_lines[param_name] = token['line']
# 记录参数
self.parameters = set(params)
# 将参数视为已声明的变量
for param in params:
self.variable_declarations[param] = True
# 进入函数体
if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '{':
self.in_function = True
self.in_function_body = False # 将在遇到第一个{时设置为True
self.brace_depth = 0
self.current_function = func_name
self.function_name = func_name
self.pos += 1
def _handle_variable_declaration(self):
# 提取类型
var_type = self.tokens[self.pos]['text']
self.pos += 1
# 获取变量名
var_names = []
while self.pos < len(self.tokens):
token = self.tokens[self.pos]
# 标识符 - 变量名
if token['type'] == 'IDENTIFIER':
var_names.append(token['text'])
self.pos += 1
# 逗号 - 多个变量声明
elif token['text'] == ',':
self.pos += 1
continue
# 结束声明
elif token['text'] == ';':
self.pos += 1
break
# 赋值 - 跳过赋值表达式
elif token['text'] == '=':
self.pos += 1
# 跳过整个赋值表达式
depth = 0
while self.pos < len(self.tokens):
t = self.tokens[self.pos]
if t['text'] in {'(', '['}:
depth += 1
elif t['text'] in {')', ']'}:
depth -= 1
elif t['text'] in {',', ';'} and depth == 0:
break
self.pos += 1
# 数组声明 - 跳过数组大小
elif token['text'] == '[':
self.pos += 1
depth = 1
while self.pos < len(self.tokens) and depth > 0:
t = self.tokens[self.pos]
if t['text'] == '[':
depth += 1
elif t['text'] == ']':
depth -= 1
self.pos += 1
else:
self.pos += 1
# 添加到局部变量
for var_name in var_names:
self.local_vars.append({
'type': var_type,
'name': var_name,
'line': self.current_line
})
self.variable_declarations[var_name] = True
def _handle_function_call(self):
# 提取函数名
func_name = self.tokens[self.pos]['text']
line = self.current_line
self.pos += 2 # 跳过函数名和 '('
# 提取参数
params = []
depth = 1
current_param = []
while self.pos < len(self.tokens) and depth > 0:
token = self.tokens[self.pos]
if token['text'] == '(':
depth += 1
elif token['text'] == ')':
depth -= 1
if depth == 0:
break
elif token['text'] == ',' and depth == 1:
params.append(''.join([t['text'] for t in current_param]).strip())
current_param = []
self.pos += 1
continue
current_param.append(token)
self.pos += 1
if current_param:
params.append(''.join([t['text'] for t in current_param]).strip())
# 跳过 ')' 如果还在范围内
if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == ')':
self.pos += 1
# 确定返回类型
return_type = "unknown"
if func_name.startswith("vd_"):
return_type = "void"
elif func_name.startswith(("u1_", "u2_", "u4_", "s1_", "s2_", "s4_")):
prefix = func_name.split("_")[0]
return_type = prefix.upper()
# 添加到函数调用列表
self.function_calls.append({
'name': func_name,
'return_type': return_type,
'type': "function",
'params': ", ".join(params),
'line': line
})
def _handle_identifier_use(self, token):
var_name = token['text']
line = token['line']
# 跳过宏定义(全大写)
if var_name in self.macro_definitions:
return
# 跳过已声明的变量(局部变量)
if var_name in self.variable_declarations:
return
# 跳过参数
if var_name in self.parameters:
return
# 跳过函数调用(函数名已经在函数调用处理中记录)
for call in self.function_calls:
if call['name'] == var_name:
return
# 跳过控制结构
if var_name in self.control_structures:
return
# 跳过类型别名
if var_name in self.type_aliases:
return
# 跳过已经记录过的全局变量
if var_name in self.recorded_globals:
return
# 添加到全局变量
self.global_vars.append({
'name': var_name,
'line': line
})
self.recorded_globals.add(var_name)
class FunctionParserApp:
def __init__(self, root):
self.root = root
self.root.title("C语言函数解析器 (内置解析器版)")
self.root.geometry("900x700")
self.setup_logging()
# 创建输入区域
input_frame = tk.LabelFrame(root, text="输入C语言函数体", padx=5, pady=5)
input_frame.pack(fill="both", expand=True, padx=10, pady=5)
self.input_text = scrolledtext.ScrolledText(input_frame, width=100, height=20)
self.input_text.pack(fill="both", expand=True, padx=5, pady=5)
# 按钮区域
btn_frame = tk.Frame(root)
btn_frame.pack(fill="x", padx=10, pady=5)
# 解析按钮
parse_btn = tk.Button(btn_frame, text="解析函数", command=self.parse_function, bg="#4CAF50", fg="white")
parse_btn.pack(side="left", padx=5)
# 保存日志按钮
save_log_btn = tk.Button(btn_frame, text="保存日志", command=self.save_logs)
save_log_btn.pack(side="right", padx=5)
# 进度条
self.progress = ttk.Progressbar(btn_frame, orient="horizontal", length=300, mode="determinate")
self.progress.pack(side="left", padx=10, fill="x", expand=True)
# 创建输出区域
output_frame = tk.LabelFrame(root, text="解析结果", padx=5, pady=5)
output_frame.pack(fill="both", expand=True, padx=10, pady=5)
self.output_text = scrolledtext.ScrolledText(output_frame, width=100, height=15)
self.output_text.pack(fill="both", expand=True, padx=5, pady=5)
self.output_text.config(state=tk.DISABLED)
# 日志区域
log_frame = tk.LabelFrame(root, text="日志信息", padx=5, pady=5)
log_frame.pack(fill="both", expand=True, padx=10, pady=5)
self.log_text = scrolledtext.ScrolledText(log_frame, width=100, height=8)
self.log_text.pack(fill="both", expand=True, padx=5, pady=5)
self.log_text.config(state=tk.DISABLED)
# 添加示例按钮
example_btn = tk.Button(btn_frame, text="加载示例", command=self.load_example)
example_btn.pack(side="right", padx=5)
# 示例函数体
self.example_code = """static void Diag21_PID_C9(U1 u1_a_num)
{
U1 u1_t_cmplt;
U1 u1_t_cnt;
if((U1)DIAG_CNT_ZERO == u1_t_swrstcnt) /* Determine if a software reset is in progress */
{
for(u1_t_cnt = (U1)DIAG21_ZERO; u1_t_cnt < (U1)DIAG21_PIDC9_FLAG; u1_t_cnt ++)
{
u1_t_cmplt = u1_g_InspSoftwareVersion(u4_g_cmd, &u4_g_data, (U1)TRUE);
}
vd_s_Diag21_U2ToU1(u2_g_buf, u1_g_data, (U1)DIAG21_PIDC9_FLAG);
}
else
{
/* Do Nothing */
}
}"""
def setup_logging(self):
"""配置日志系统"""
self.log_filename = f"parser_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
logging.basicConfig(
filename=self.log_filename,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("应用程序启动")
def log_to_gui(self, message, level="info"):
"""将日志信息显示在GUI中"""
self.log_text.config(state=tk.NORMAL)
timestamp = datetime.now().strftime("%H:%M:%S")
self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
self.log_text.see(tk.END)
self.log_text.config(state=tk.DISABLED)
if level == "info":
logging.info(message)
elif level == "warning":
logging.warning(message)
elif level == "error":
logging.error(message)
def save_logs(self):
"""保存日志到文件"""
try:
log_content = self.log_text.get("1.0", tk.END)
filename = f"saved_log_{datetime.now().strftime('%H%M%S')}.txt"
with open(filename, "w") as f:
f.write(log_content)
self.log_to_gui(f"日志已保存到: {filename}", "info")
messagebox.showinfo("保存成功", f"日志已保存到:\n{filename}")
except Exception as e:
self.log_to_gui(f"保存日志失败: {str(e)}", "error")
messagebox.showerror("保存失败", f"无法保存日志:\n{str(e)}")
def update_progress(self, value):
"""更新进度条"""
self.progress['value'] = value
self.root.update_idletasks()
def load_example(self):
"""加载示例函数体"""
self.input_text.delete(1.0, tk.END)
self.input_text.insert(tk.END, self.example_code)
self.log_to_gui("已加载示例函数体")
def parse_function(self):
"""使用内置解析器解析C语言函数体"""
try:
code = self.input_text.get(1.0, tk.END)
if not code.strip():
self.log_to_gui("错误: 没有输入函数体", "error")
messagebox.showerror("错误", "请输入要解析的C语言函数体")
return
self.log_to_gui("开始解析函数体...")
self.output_text.config(state=tk.NORMAL)
self.output_text.delete(1.0, tk.END)
self.update_progress(0)
# 使用内置词法分析器
self.log_to_gui("执行词法分析...")
lexer = SimpleCLexer()
tokens = lexer.tokenize(code)
self.update_progress(30)
# 使用内置语法分析器
self.log_to_gui("执行语法分析...")
analyzer = FunctionAnalyzer()
analyzer.analyze(tokens)
self.update_progress(70)
# 显示结果
self.log_to_gui("生成解析报告...")
self.display_results(
analyzer.local_vars,
analyzer.global_vars,
analyzer.function_calls,
analyzer.function_name,
analyzer.parameters
)
self.update_progress(100)
self.output_text.config(state=tk.DISABLED)
self.log_to_gui("解析完成!")
messagebox.showinfo("完成", "函数体解析成功完成!")
except Exception as e:
self.log_to_gui(f"解析错误: {str(e)}", "error")
messagebox.showerror("解析错误", f"发生错误:\n{str(e)}")
self.update_progress(0)
def display_results(self, local_vars, global_vars, function_calls, func_name, func_params):
"""显示解析结果"""
# 显示函数签名
if func_name:
self.output_text.insert(tk.END, "=== 函数签名 ===\n")
self.output_text.insert(tk.END, f"函数名: {func_name}\n")
self.output_text.insert(tk.END, f"参数: {', '.join(func_params)}\n\n")
else:
self.output_text.insert(tk.END, "=== 函数签名 ===\n")
self.output_text.insert(tk.END, "警告: 无法识别函数签名\n\n")
self.log_to_gui("无法识别函数签名", "warning")
# 显示局部变量
if local_vars:
self.output_text.insert(tk.END, "=== 局部变量 ===\n")
for var in local_vars:
self.output_text.insert(tk.END, f"{var['type']} {var['name']} (行号: {var['line']})\n")
self.log_to_gui(f"找到局部变量: {var['type']} {var['name']}")
self.output_text.insert(tk.END, "\n")
else:
self.output_text.insert(tk.END, "未找到局部变量\n\n")
self.log_to_gui("未找到局部变量", "warning")
# 显示使用的全局变量
if global_vars:
self.output_text.insert(tk.END, "=== 使用的全局变量 ===\n")
for var in global_vars:
self.output_text.insert(tk.END, f"{var['name']} (行号: {var['line']})\n")
self.log_to_gui(f"找到全局变量: {var['name']}")
self.output_text.insert(tk.END, "\n")
else:
self.output_text.insert(tk.END, "未使用全局变量\n\n")
self.log_to_gui("未使用全局变量", "warning")
# 显示函数调用
if function_calls:
self.output_text.insert(tk.END, "=== 函数调用 ===\n")
for func in function_calls:
self.output_text.insert(tk.END, f"函数名: {func['name']} (行号: {func['line']})\n")
self.output_text.insert(tk.END, f"返回类型: {func['return_type']}\n")
self.output_text.insert(tk.END, f"函数类型: {func['type']}\n")
self.output_text.insert(tk.END, f"参数: {func['params']}\n")
self.output_text.insert(tk.END, "-" * 50 + "\n")
self.log_to_gui(f"找到函数调用: {func['name']}")
else:
self.output_text.insert(tk.END, "未调用任何函数\n\n")
self.log_to_gui("未调用任何函数", "warning")
# 显示统计信息
self.output_text.insert(tk.END, "=== 解析统计 ===\n")
self.output_text.insert(tk.END, f"局部变量数量: {len(local_vars)}\n")
self.output_text.insert(tk.END, f"使用的全局变量数量: {len(global_vars)}\n")
self.output_text.insert(tk.END, f"函数调用数量: {len(function_calls)}\n")
self.output_text.insert(tk.END, "\n")
if __name__ == "__main__":
root = tk.Tk()
app = FunctionParserApp(root)
root.mainloop()
=== 函数签名 ===
警告: 无法识别函数签名
未找到局部变量
=== 使用的全局变量 ===
u1_t_cmplt (行号: 4)
u1_t_cnt (行号: 5)
u1_t_swrstcnt (行号: 7)
=== 函数调用 ===
函数名: u1_g_InspSoftwareVersion (行号: 11)
返回类型: U1
函数类型: function
参数: u4_g_cmd, &u4_g_data, (U1)TRUE
函数名: vd_s_Diag21_U2ToU1 (行号: 13)
返回类型: void
函数类型: function
参数: u2_g_buf, u1_g_data, (U1)DIAG21_PIDC9_FLAG
=== 解析统计 ===
局部变量数量: 0
使用的全局变量数量: 3
函数调用数量: 2
请修改上述问题,并且将每一步的解析结果都记录到日志,我会将记录的日志发给你,你找到原因并修改