You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:23:14