Go语言规格说明书 之 变量声明(Variable/Short variable declarations)

本文详细介绍了Go语言中的两种变量声明方式:普通的变量声明和简短的变量声明,并通过实例展示了如何使用这两种方式来声明变量及其注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

go version go1.11 windows/amd64

 

本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,完整的介绍Go语言的 变量声明(Variable declarations)简短变量声明(Short variable declarations)

 

Go语言有两种 变量声明方式:普通的、简短的。

普通的 方式 需要 使用 var关键字,简短的需要使用 := 组合符号。

普通的 方式 可以在任何作用域使用,而 简短的 方式 仅限于 函数的作用域内,或者,函数内的 if、for、switch 等语句中使用。

下面分别介绍。

 

注意,本文说的是 变量声明,而不是变量定义、初始化,但也会包含一些定义、初始化的内容。

 

普通的变量声明方式

和Python类似,可以在一行声明一个变量,也可以同时声明多个变量(变量列表)。

对于多个变量的声明,其中可以存在 空标识符(_),表示忽略对应位置的 值的表达式列表中的值。

 

官文示例 及 解释

var i int // 这里的类型 int 不能少
var U, V, W float64 // 声明三个变量,初始化为 float64的默认值 0.0。这样来看,每个 声明了的变量 都是有值得,只不过,有些是默认值。可以查看 zero value。
var k = 0 // 没有指定类型,但基于了初始值,那么,k的类型是什么呢?下面会进行测试,结果为 int
var x, y float32 = -1, -2 // 指定了类型,也提供了值列表
var ( // 这个还不太理解,前面某博文说这样的方式是定义 全局变量!
	i       int
	u, v, s = 2.0, 3.0, "bar"
)
var re, im = complexSqrt(-1)
var _, found = entries[name]  // map lookup; only interested in "found" // 空标识符(_)表示忽略函数返回的第一个值,只需要(关注)第二个

 

进一步测试:

func main() {
	var x1 = 0
	fmt.Println(typeof(x1))
	var x2 = 0.0
	fmt.Println(typeof(x2))
}

// 测试函数
func typeof(v interface{}) string {
	return fmt.Sprintf("%T", v)
}

测试结果:

int
float64

 

关于声明的变量的类型:

如果声明语句中存在类型名称,那么,变量就是这个类型;

否则,变量的类型为各自的初始化的值的类型(前面说过,变量的类型、初始化值 不能都不存在),此时,如果值是一位未类型化的常量(an untyped constant),变量的类型就是这个常量转换后的默认类型——如上面的测试中,0的默认类型是int、0.0的默认类型是float64;如果值是一个未类型化的布尔值(an untyped boolean value),那么,变量的类型为bool。

注意,预定义值 nil 不能用于给一个 没有指明类型 的变量赋值(指明了就可以了吧)。

 

官文示例:

var d = math.Sin(0.5)  // d is float64
var i = 42             // i is int
var t, ok = x.(T)      // t is T, ok is bool // 不懂!还需要dig
var n = nil            // illegal // 没有指定类型

 

注意,编译器会将函数体内 声明了却从未使用 的变量设置为非法,编译 自然就不能通过,程序也不能执行了。

 

简短的变量声明方式

前面的变量声明需要关键字 var,而这里是 禁止用它的,也不需要指定变量类型,也不需要使用单独的等号(=),,需要用 := 组合符号——必须的,其后是一个或多个值,或者返回一个或多个值得 表达式。

声明中没有类型,不代表 变量没有类型,其类型根据赋予它们的值类进行推断的(推断规则TBD,我要去找找文档)。

官方示例:

i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)
r, w := os.Pipe(fd)  // os.Pipe() returns two values
_, y, _ := coord(p)  // coord() returns three values; only interested in y coordinate

 

进阶:

比普通变量声明方式多了一个 重新声明变量(redeclare) 的特性。

重新定义 可以 认为是 重新给 前面声明的变量赋值,因此,新的值得类型要匹配。

还有一个关键要求

重新声明变量 只能出现在 变量列表的声明方式中,而且,在这个变量列表中,至少存在着一个 新的非空变量。

我的测试:

a := 123 // 声明变量a,成功,int型

a := 321 // 失败,只是一个变量,而不是变量列表,删除,再测试

a := "str" // 类型错误,单个变量错误,删除上面所有,再测试

// ----翻篇----
v1, a := "v1", 123 // 声明两个变量 v1、a
v1, a := "v11", 123 // 失败,不存在一个新的非空变量,删除此句,再测试
v2, a := "v2", 123 // 和变量v2一起重新声明a,成功

a, v3 := 999, "v2" // 切换变量a在重新声明语句中的位置

 

再次提示,简短声明语句 仅限于 函数的作用域内,或者,函数内的 if、for、switch 等语句中使用。

 

本文完。

需要结合 作用域、类型初始化值等一起看,会获得更完整的知识。

 

转载于:https://www.cnblogs.com/luo630/p/9639926.html

=== 函数签名 === 函数名: Diag21_PID_C9 参数: U1 u1_a_num === 所有变量分析 === 类型 | 名称 | 作用域 | 行号 -------------------------------------------------- 参数 | u1_a_num | 参数 | 1 变量 | u1_t_cmplt | 全局 | 3 变量 | u1_t_cnt | 全局 | 4 变量 | sensor | 全局 | 5 变量 | u1_t_swrstcnt | 全局 | 7 变量 | u4_g_cmd | 全局 | 11 变量 | u4_g_data | 全局 | 11 变量 | u2_g_buf | 全局 | 13 变量 | u1_g_data | 全局 | 13 函数调用 | u1_g_InspSoftwareVersion | 调用 | 11 函数调用 | vd_s_Diag21_U2ToU1 | 调用 | 13 未找到局部变量 === 使用的全局变量 === u1_t_cmplt (行号: 3) u1_t_cnt (行号: 4) sensor (行号: 5) u1_t_swrstcnt (行号: 7) u4_g_cmd (行号: 11) u4_g_data (行号: 11) u2_g_buf (行号: 13) u1_g_data (行号: 13) === 函数调用 === 函数名: u1_g_InspSoftwareVersion (行号: 11) 返回类型: U1 参数: u4_g_cmd, &u4_g_data, (U1)TRUE -------------------------------------------------- 函数名: vd_s_Diag21_U2ToU1 (行号: 13) 返回类型: void 参数: u2_g_buf, u1_g_data, (U1)DIAG21_PIDC9_FLAG -------------------------------------------------- === 解析统计 === 参数数量: 1 局部变量数量: 0 全局变量数量: 8 函数调用数量: 2 总变量数量: 11 1、没有识别出来局部变量 2、结构体要单独识别出来,不要与变量混为一谈 3、结构体不一定会在函数体内被定义,可能在函数体外被声明,函数体内只是SensorData sensor; 代码如下: import tkinter as tk from tkinter import scrolledtext, ttk, messagebox import logging from datetime import datetime import traceback class SimpleCLexer: def __init__(self): self.tokens = [] def tokenize(self, input_str): tokens = [] pos = 0 line = 1 column = 0 length = len(input_str) # 定义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', 'BOOL', 'BYTE', 'WORD', 'DWORD'} while pos < length: char = input_str[pos] # 跳过空白字符 if char in ' \t': pos += 1 column += 1 continue # 处理换行 if char == '\n': line += 1 column = 0 pos += 1 continue # 处理单行注释 if pos + 1 < length and input_str[pos:pos+2] == '//': end = input_str.find('\n', pos) if end == -1: end = length pos = end continue # 处理多行注释 if pos + 1 < length and input_str[pos:pos+2] == '/*': end = input_str.find('*/', pos + 2) if end == -1: end = length else: end += 2 pos = end continue # 处理标识符 if char.isalpha() or char == '_': start = pos pos += 1 while pos < length 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 char.isdigit(): start = pos pos += 1 while pos < length 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 char == '"': start = pos pos += 1 while pos < length and input_str[pos] != '"': if input_str[pos] == '\\' and pos + 1 < length: pos += 2 else: pos += 1 if pos < length and input_str[pos] == '"': pos += 1 tokens.append({ 'type': 'STRING', 'text': input_str[start:pos], 'line': line, 'column': column }) column += (pos - start) continue # 处理字符 if char == "'": start = pos pos += 1 while pos < length and input_str[pos] != "'": if input_str[pos] == '\\' and pos + 1 < length: pos += 2 else: pos += 1 if pos < length 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 <= length 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': char, 'line': line, 'column': column }) pos += 1 column += 1 return tokens class FunctionAnalyzer: def __init__(self): self.function_name = "" self.parameters = [] self.global_vars = [] self.function_calls = [] self.in_function = False self.in_function_body = False self.brace_depth = 0 self.variable_declarations = {} self.macro_definitions = set() self.storage_classes = {"static", "extern", "auto", "register"} self.local_vars = [] # 局部变量列表 self.struct_tags = set() # 存储识别的结构体标签 self.recorded_locals = set() # 新增:跟踪已记录的局部变量 self.recorded_globals = set() self.recorded_params = set() # 定义允许的类型 self.basic_types = {'void', 'int', 'char', 'float', 'double', 'short', 'long', 'signed', 'unsigned'} self.type_aliases = {"U1", "U2", "U4", "S1", "S2", "S4"} self.allowed_types = self.basic_types | self.type_aliases self.allowed_types.add('struct') # 添加结构体支持 self.debug_level = 2 # 1=基本, 2=详细 def analyze(self, tokens): self.tokens = tokens self.pos = 0 self.current_line = 0 self.brace_depth = 0 # 识别宏定义 self._identify_macros() while self.pos < len(self.tokens): token = self.tokens[self.pos] self.current_line = token['line'] # 检测结构体类型声明 if token['text'] == 'struct' and self.pos + 1 < len(self.tokens): next_token = self.tokens[self.pos + 1] if next_token['type'] == 'IDENTIFIER': self.struct_tags.add(next_token['text']) self.allowed_types.add(next_token['text']) # 添加为有效类型 self.pos += 2 # 跳过 'struct' 和标识符 continue # 跟踪大括号深度 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 # 检测函数定义 if token['text'] in self.storage_classes or token['text'] in self.allowed_types: if self._is_function_definition(): self._handle_function_definition() continue # 检测变量声明 - 只在函数体内处理 if self.in_function_body and token['text'] in self.allowed_types: # 检查下一个token是否是标识符(变量名) if self.pos + 1 < len(self.tokens) and \ self.tokens[self.pos + 1]['type'] == 'IDENTIFIER': # 确保不是函数返回类型 if self.pos + 2 < len(self.tokens) and self.tokens[self.pos + 2]['text'] != '(': 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) 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 storage_class = None # 检测存储类说明符 if self.tokens[pos]['text'] in self.storage_classes: storage_class = self.tokens[pos]['text'] pos += 1 # 检测返回类型 if pos >= len(self.tokens) or self.tokens[pos]['text'] not in self.allowed_types: return False return_type = self.tokens[pos]['text'] pos += 1 # 处理指针声明 if pos < len(self.tokens) and self.tokens[pos]['text'] == '*': return_type += '*' pos += 1 # 检测函数名 if pos < len(self.tokens) and self.tokens[pos]['type'] == 'IDENTIFIER': func_name = self.tokens[pos]['text'] pos += 1 else: return False # 检测参数列表开头的'(' if pos < len(self.tokens) and self.tokens[pos]['text'] == '(': pos += 1 else: return False # 检测函数体开头的'{' (允许最多5个token的间隔) found_brace = False for i in range(min(5, len(self.tokens) - pos)): if self.tokens[pos + i]['text'] == '{': found_brace = True break return found_brace def _handle_function_definition(self): start_pos = self.pos storage_class = None # 处理存储类说明符 if self.tokens[self.pos]['text'] in self.storage_classes: storage_class = self.tokens[self.pos]['text'] self.pos += 1 # 获取返回类型 return_type = self.tokens[self.pos]['text'] self.pos += 1 # 处理指针声明 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': return_type += '*' 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 else: self.pos = start_pos return # 记录函数名 self.function_name = func_name self.variable_declarations[func_name] = True # 跳过 '(' if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '(': self.pos += 1 # 提取参数 params = [] current_param = [] depth = 1 param_line = self.current_line 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: # 提取参数类型和名称 param_type, param_name = self._extract_param_info(current_param) if param_type and param_name: params.append({ 'type': param_type, 'name': param_name, 'line': param_line }) self.variable_declarations[param_name] = True current_param = [] param_line = token['line'] self.pos += 1 continue current_param.append(token) self.pos += 1 # 处理最后一个参数 if current_param: param_type, param_name = self._extract_param_info(current_param) if param_type and param_name: params.append({ 'type': param_type, 'name': param_name, 'line': param_line }) self.variable_declarations[param_name] = True # 记录参数 self.parameters = params # 记录参数为参数类型 for param in params: self.recorded_params.add(param['name']) self.variable_declarations[param['name']] = True # 查找函数体开头的'{' while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] != '{': self.pos += 1 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '{': self.in_function = True self.brace_depth = 0 self.pos += 1 return [p['name'] for p in params] if params else [] def _extract_param_info(self, tokens): """从参数token列表中提取类型和名称""" param_type = [] param_name = None for token in tokens: if token['type'] in ('KEYWORD', 'TYPE') or token['text'] in self.allowed_types: param_type.append(token['text']) elif token['type'] == 'IDENTIFIER' and not token['text'].isupper(): param_name = token['text'] return ' '.join(param_type), param_name def _handle_variable_declaration(self): start_pos = self.pos current_line = self.current_line # 获取变量类型 var_type = self.tokens[self.pos]['text'] # 处理结构体声明 if var_type == 'struct': # 收集结构体类型名 struct_type = [] self.pos += 1 while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] != ';': token = self.tokens[self.pos] if token['text'] == '{': # 跳过结构体定义 depth = 1 self.pos += 1 while self.pos < len(self.tokens) and depth > 0: if self.tokens[self.pos]['text'] == '{': depth += 1 elif self.tokens[self.pos]['text'] == '}': depth -= 1 self.pos += 1 continue elif token['type'] == 'IDENTIFIER': struct_type.append(token['text']) self.pos += 1 if struct_type: var_type = 'struct ' + ' '.join(struct_type) else: var_type = 'struct' else: self.pos += 1 # 处理指针声明 while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': var_type += '*' self.pos += 1 var_names = [] # 处理变量名和声明 while self.pos < len(self.tokens): token = self.tokens[self.pos] # 结束声明 if token['text'] == ';': self.pos += 1 break # 标识符 - 变量名 if token['type'] == 'IDENTIFIER' and not token['text'].isupper(): var_name = token['text'] # 跳过宏定义 if var_name not in self.macro_definitions: var_names.append(var_name) self.variable_declarations[var_name] = True self.pos += 1 continue # 逗号 - 多个变量声明 elif token['text'] == ',': self.pos += 1 # 处理指针声明 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': var_type += '*' self.pos += 1 continue # 数组声明 - 跳过数组大小 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 continue # 初始化 - 跳过初始化表达式 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 continue self.pos += 1 # 添加到局部变量 (确保在函数体内) if self.in_function_body: for var_name in var_names: # 检查是否在参数列表中 is_param = any(param['name'] == var_name for param in self.parameters) if not is_param and var_name not in self.macro_definitions: # 添加到局部变量 self.local_vars.append({ 'type': var_type, 'name': var_name, 'line': current_line, 'scope': 'local' }) # 记录为局部变量 self.recorded_locals.add(var_name) self.variable_declarations[var_name] = True else: # 全局变量处理 for var_name in var_names: if var_name not in self.recorded_globals: self.global_vars.append({ 'name': var_name, 'line': current_line, 'scope': 'global' }) self.recorded_globals.add(var_name) self.variable_declarations[var_name] = True def _handle_identifier_use(self, token): var_name = token['text'] line = token['line'] # 跳过已处理的标识符 skip_conditions = ( var_name in self.variable_declarations, var_name in self.macro_definitions, var_name == self.function_name, var_name in self.struct_tags # 跳过结构体标签 ) if any(skip_conditions): return # 函数体内使用的标识符 if self.in_function_body: # 如果未声明,则视为全局变量 if var_name not in self.recorded_locals and var_name not in self.recorded_globals: if var_name not in self.recorded_globals: self.global_vars.append({ 'name': var_name, 'line': line, 'scope': 'global' }) self.variable_declarations[var_name] = True self.recorded_globals.add(var_name) else: # 函数体外使用的标识符 if var_name not in self.recorded_globals: self.global_vars.append({ 'name': var_name, 'line': line, 'scope': 'global' }) self.variable_declarations[var_name] = True self.recorded_globals.add(var_name) def _handle_function_call(self): # 提取函数名 func_name = self.tokens[self.pos]['text'] line = self.current_line self.pos += 2 # 跳过函数名和 '(' # 提取参数 params = [] depth = 1 current_param = [] # 保存所有参数token用于后续分析 param_tokens = [] 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()) param_tokens.extend(current_param) 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()) param_tokens.extend(current_param) # 跳过 ')' 如果还在范围内 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == ')': self.pos += 1 # 处理参数中的标识符 for token in param_tokens: if token['type'] == 'IDENTIFIER' and not token['text'].isupper(): self._handle_identifier_use(token) # 确定返回类型 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, 'params': ", ".join(params), 'line': line }) class FunctionParserApp: def __init__(self, root): self.root = root self.root.title("C语言函数解析器") self.root.geometry("1000x800") self.root.configure(bg="#f0f0f0") self.setup_logging() # 创建样式 style = ttk.Style() style.configure("TFrame", background="#f0f0f0") style.configure("TLabelFrame", background="#f0f0f0", font=("Arial", 10, "bold")) style.configure("TButton", font=("Arial", 10), padding=5) style.configure("TCombobox", padding=5) style.configure("TProgressbar", thickness=10) # 主框架 main_frame = ttk.Frame(root) main_frame.pack(fill="both", expand=True, padx=15, pady=15) # 创建输入区域 input_frame = ttk.LabelFrame(main_frame, text="输入C语言函数体") input_frame.pack(fill="both", expand=True, padx=5, pady=5) self.input_text = scrolledtext.ScrolledText(input_frame, width=100, height=15, font=("Consolas", 11), bg="#ffffff") self.input_text.pack(fill="both", expand=True, padx=10, pady=10) # 按钮区域 btn_frame = ttk.Frame(main_frame) btn_frame.pack(fill="x", padx=5, pady=5) # 解析按钮 parse_btn = ttk.Button(btn_frame, text="解析函数", command=self.parse_function) parse_btn.pack(side="left", padx=5) # 保存日志按钮 save_log_btn = ttk.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) # 调试级别控制 debug_frame = ttk.Frame(btn_frame) debug_frame.pack(side="left", padx=10) ttk.Label(debug_frame, text="调试级别:").pack(side="left") self.debug_level = tk.IntVar(value=1) ttk.Combobox(debug_frame, textvariable=self.debug_level, values=[1, 2], width=3).pack(side="left") # 示例按钮 example_btn = ttk.Button(btn_frame, text="加载示例", command=self.load_example) example_btn.pack(side="right", padx=5) # 创建输出区域 output_frame = ttk.LabelFrame(main_frame, text="解析结果") output_frame.pack(fill="both", expand=True, padx=5, pady=5) self.output_text = scrolledtext.ScrolledText(output_frame, width=100, height=15, font=("Consolas", 11), bg="#ffffff") self.output_text.pack(fill="both", expand=True, padx=10, pady=10) self.output_text.config(state=tk.DISABLED) # 日志区域 log_frame = ttk.LabelFrame(main_frame, text="日志信息") log_frame.pack(fill="both", expand=True, padx=5, pady=5) self.log_text = scrolledtext.ScrolledText(log_frame, width=100, height=6, font=("Consolas", 10), bg="#f8f8f8") self.log_text.pack(fill="both", expand=True, padx=10, pady=10) self.log_text.config(state=tk.DISABLED) # 示例函数体 self.example_code = """static void Diag21_PID_C9(U1 u1_a_num) { U1 u1_t_cmplt; U1 u1_t_cnt; struct SensorData sensor; 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 */ } }""" # 加载示例 self.load_example() def setup_logging(self): """配置日志系统""" self.log_filename = f"parser_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" # 创建文件处理器 file_handler = logging.FileHandler(self.log_filename, encoding='utf-8') file_handler.setLevel(logging.INFO) file_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) # 配置根日志器 root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) root_logger.addHandler(file_handler) def log_to_gui(self, message, level="info"): """将日志信息显示在GUI中""" try: 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) except Exception as e: logging.error(f"GUI日志错误: {str(e)}") 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", encoding='utf-8') 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.debug_level = self.debug_level.get() analyzer.analyze(tokens) # 显示结果 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") self.log_to_gui(f"错误详情: {traceback.format_exc()}", "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): """增强版结果显示,包含所有变量信息""" # 显示函数签名 self.output_text.insert(tk.END, "=== 函数签名 ===\n", "header") if func_name: self.output_text.insert(tk.END, f"函数名: {func_name}\n") if func_params: param_list = [] for param in func_params: param_list.append(f"{param['type']} {param['name']}") self.output_text.insert(tk.END, f"参数: {', '.join(param_list)}\n\n") else: self.output_text.insert(tk.END, "参数: 无\n\n") else: self.output_text.insert(tk.END, "警告: 无法识别函数签名\n\n") # 显示所有找到的变量 self.output_text.insert(tk.END, "=== 所有变量分析 ===\n", "header") self.output_text.insert(tk.END, "类型 | 名称 | 作用域 | 行号\n", "subheader") self.output_text.insert(tk.END, "-" * 50 + "\n") # 显示参数 for param in func_params: self.output_text.insert(tk.END, f"参数 | {param['name']} | 参数 | {param['line']}\n") # 显示局部变量 for var in local_vars: self.output_text.insert(tk.END, f"变量 | {var['name']} | 局部 | {var['line']}\n") # 显示全局变量 for var in global_vars: self.output_text.insert(tk.END, f"变量 | {var['name']} | 全局 | {var['line']}\n") # 显示函数调用 for func in function_calls: self.output_text.insert(tk.END, f"函数调用 | {func['name']} | 调用 | {func['line']}\n") self.output_text.insert(tk.END, "\n") # 显示局部变量 if local_vars: self.output_text.insert(tk.END, "=== 局部变量 ===\n", "header") for var in local_vars: self.output_text.insert(tk.END, f"{var['type']} {var['name']} (行号: {var['line']})\n") else: self.output_text.insert(tk.END, "未找到局部变量\n\n") # 显示使用的全局变量 if global_vars: self.output_text.insert(tk.END, "=== 使用的全局变量 ===\n", "header") for var in global_vars: self.output_text.insert(tk.END, f"{var['name']} (行号: {var['line']})\n") self.output_text.insert(tk.END, "\n") else: self.output_text.insert(tk.END, "未使用全局变量\n\n") # 显示函数调用 if function_calls: self.output_text.insert(tk.END, "=== 函数调用 ===\n", "header") 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['params']}\n") self.output_text.insert(tk.END, "-" * 50 + "\n") else: self.output_text.insert(tk.END, "未调用任何函数\n\n") # 添加变量统计 self.output_text.insert(tk.END, "=== 解析统计 ===\n", "header") self.output_text.insert(tk.END, f"参数数量: {len(func_params)}\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, f"总变量数量: {len(func_params) + len(local_vars) + len(global_vars) + len(function_calls)}\n") # 配置标签样式 self.output_text.tag_config("header", font=("Arial", 12, "bold"), foreground="#2c3e50") self.output_text.tag_config("subheader", font=("Arial", 10, "bold"), foreground="#34495e") if __name__ == "__main__": root = tk.Tk() app = FunctionParserApp(root) root.mainloop()
最新发布
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值