Python实现三地址码转伪代码:循环逻辑生成卡壳求助
循环三地址码转伪代码的实现思路与方案
针对你遇到的循环三地址码转伪代码的问题,我们可以通过结构化解析三地址码特征、识别循环边界与逻辑块、语义映射优化可读性这几个核心步骤来解决,以下是具体实现方案:
核心思路
循环三地址码的典型结构包含:初始化语句、循环入口标签、条件判断跳转、循环体、迭代操作、循环出口标签。我们需要先识别这些模块,再将每个模块转换成自然语言伪代码。
步骤1:结构化解析三地址码
首先把输入的三地址码转换成机器可识别的结构化数据,比如用类或字典存储每条语句的类型、目标变量、操作符、操作数:
class ThreeAddrStmt: def __init__(self, stmt_type, target=None, op=None, operands=None): self.stmt_type = stmt_type # 可选值:'assign', 'label', 'if_goto', 'goto', 'print' self.target = target # 赋值目标或标签名 self.op = op # 操作符:=, +, *, addr, [] 等 self.operands = operands or [] # 操作数列表 # 示例解析:把输入的三地址码字符串转成结构化列表 def parse_three_addr_code(code_str): stmts = [] lines = [line.strip() for line in code_str.split('\n') if line.strip()] for line in lines: if line.endswith(':'): # 标签语句,比如 L1: stmts.append(ThreeAddrStmt('label', target=line[:-1])) elif line.startswith('if'): # 条件跳转语句,比如 if i >=3 goto L2 parts = line.split() op = parts[2] operands = [parts[1], parts[3]] target_label = parts[-1] stmts.append(ThreeAddrStmt('if_goto', op=op, operands=operands + [target_label])) elif line.startswith('goto'): # 无条件跳转语句 target_label = line.split()[-1] stmts.append(ThreeAddrStmt('goto', target=target_label)) elif line.startswith('print'): # 打印语句 var = line.split()[-1] stmts.append(ThreeAddrStmt('print', operands=[var])) else: # 赋值语句,比如 sum=0, T1=addr(a) target, rest = line.split('=', 1) target = target.strip() rest = rest.strip() if ' ' in rest: op, *operands = rest.split() stmts.append(ThreeAddrStmt('assign', target=target, op=op, operands=operands)) else: # 直接赋值,比如 sum=0 stmts.append(ThreeAddrStmt('assign', target=target, op='=', operands=[rest])) return stmts
步骤2:识别循环结构模块
遍历结构化后的语句,定位循环的各个组成部分:
def extract_loop_structure(stmts): # 1. 记录所有标签的位置 label_positions = {stmt.target: idx for idx, stmt in enumerate(stmts) if stmt.stmt_type == 'label'} # 2. 找到循环入口:通过goto语句反向定位(循环体末尾会goto回入口标签) loop_entry_label = None goto_index = None for idx, stmt in enumerate(stmts): if stmt.stmt_type == 'goto': loop_entry_label = stmt.target goto_index = idx break if not loop_entry_label: return None # 无循环结构 # 3. 提取循环初始化语句(入口标签之前的代码) init_stmts = stmts[:label_positions[loop_entry_label]] # 4. 提取循环终止条件(入口标签后的if_goto语句) if_stmt = stmts[label_positions[loop_entry_label] + 1] cond_var, cond_op, cond_val, exit_label = if_stmt.operands # 反转条件:比如 if i>=3 goto L2 → 循环条件是 i<3 reverse_ops = {'>=': '<', '>': '<=', '<': '>=', '<=': '>'} loop_condition = f"{cond_var} {reverse_ops[cond_op]} {cond_val}" # 5. 提取循环体(if_goto之后到goto之前的代码) loop_body_stmts = stmts[label_positions[loop_entry_label]+2 : goto_index] # 6. 提取迭代操作(循环体末尾修改循环变量的语句) iter_stmt = None for stmt in reversed(loop_body_stmts): if stmt.stmt_type == 'assign' and stmt.op == '+' and stmt.operands[1] == '1': iter_var = stmt.target iter_stmt = f"Increment {iter_var} by 1" loop_body_stmts = loop_body_stmts[:-1] # 从循环体中移除迭代语句 break # 7. 提取循环后代码(出口标签之后的代码) exit_pos = label_positions[exit_label] post_loop_stmts = stmts[exit_pos+1:] return { 'init': init_stmts, 'condition': loop_condition, 'body': loop_body_stmts, 'iteration': iter_stmt, 'post': post_loop_stmts }
步骤3:处理数组访问与临时变量语义
三地址码中的数组访问会拆成多步(比如addr(arr1)、i*4、T1[T2]),我们需要识别这类语句并映射成自然语言,同时跟踪临时变量的语义来优化可读性:
def process_body_stmts(stmts): pseudo_lines = [] temp_semantics = {} # 记录临时变量对应的语义,比如 T3 → "value of arr1[i]" idx = 0 while idx < len(stmts): stmt = stmts[idx] # 识别数组访问语句块 if stmt.stmt_type == 'assign' and stmt.op == 'addr': arr_name = stmt.operands[0] temp_semantics[stmt.target] = f"address of {arr_name}" # 下一句是索引计算(i*4) idx +=1 idx_stmt = stmts[idx] temp_semantics[idx_stmt.target] = f"{idx_stmt.operands[0]} * 4" # 再下一句是取值(T1[T2]) idx +=1 val_stmt = stmts[idx] arr_access = f"{arr_name}[{idx_stmt.operands[0]}]" temp_semantics[val_stmt.target] = f"value of {arr_access}" pseudo_lines.append(f"Get value of {arr_access}") # 处理乘法/加法操作 elif stmt.stmt_type == 'assign' and stmt.op in ['*', '+']: # 用临时变量的语义替换变量名 op1 = temp_semantics.get(stmt.operands[0], stmt.operands[0]) op2 = temp_semantics.get(stmt.operands[1], stmt.operands[1]) if stmt.op == '*': pseudo_lines.append(f"Multiply {op1} and {op2}") temp_semantics[stmt.target] = f"product of {op1} and {op2}" elif stmt.op == '+' and stmt.target == 'sum': pseudo_lines.append(f"Add {op1} to sum") # 其他赋值语句 else: val = temp_semantics.get(stmt.operands[0], stmt.operands[0]) pseudo_lines.append(f"Set {stmt.target} to {val}") idx +=1 return pseudo_lines
步骤4:生成最终伪代码
把所有模块组合起来,生成带编号的伪代码:
def generate_pseudo_code(loop_info): pseudo = [] # 生成初始化代码 for stmt in loop_info['init']: val = stmt.operands[0] pseudo.append(f"Set {stmt.target} to {val}") # 生成循环结构 pseudo.append(f"While {loop_info['condition']}:") # 生成循环体 body_lines = process_body_stmts(loop_info['body']) for line in body_lines: pseudo.append(f" {line}") # 生成迭代语句 pseudo.append(f" {loop_info['iteration']}") # 生成循环后代码 for stmt in loop_info['post']: if stmt.stmt_type == 'print': pseudo.append(f"Print {stmt.operands[0]}") # 添加编号 numbered_pseudo = [f"{i+1}. {line}" for i, line in enumerate(pseudo)] return '\n'.join(numbered_pseudo)
示例测试
针对你提供的三地址码,运行上述代码后会生成如下伪代码:
1. Set sum to 0 2. Set i to 0 3. While i < 3: Get value of arr1[i] Get value of arr2[i] Multiply value of arr1[i] and value of arr2[i] Add product of value of arr1[i] and value of arr2[i] to sum Increment i by 1 4. Print sum
内容的提问来源于stack exchange,提问作者Jasleen Kaur
相关产品推荐
相关产品推荐

