pycparser解析C代码构建AST

文章目录

构建AST语法树

  • pycparser解析C代码构建AST语法树;
  • pycparser是纯python实现的基于C99的解析器;
  • 不使用C标准的头文件,而是自己构建一套虚拟的头文件,在pycparser/utils/fake_libc_include 目录下;
  • 在分析C代码时,必须先预处理,比如注释掉标准头文件、size_t不支持的语法等;
  • python环境中安装pycparser, pip install pycparser;

编写C代码

如下C代码已经将标准头文件注释;

c 复制代码
//#include <stdio.h>
//#include <malloc.h> // 内存管理
//#include <string.h> // 字符串的头文件
//#include <math.h>
//#include <ctype.h>  // 处理字符的判断


typedef struct {
    int size;
    union {
        int age;
        int size;
        struct {
            int id;
        }mem1;
    }data;
}Variable;


// 声明一个结构体数组,并初始化
Variable arr[] = {{3, {{100}}}};

int idx = 0;

// 函数定义
void testLauf(){
    if(arr[idx].data.mem1.id < 200){
    printf("running...");
	}
}

分析C代码

基于pycparser 分析该样例C代码,并解析testLauf函数中的if条件内容;

python 复制代码
from pycparser import c_ast, parse_file

# 构建语法树
ast = parse_file(r"E:\jack.c", use_cpp=True, cpp_path="cpp", cpp_args=["-Ipycparser/utils/fake_libc_include"])


def process_func_def(node):
    # 处理函数体
    process_compound_or_single(node.body)


def process_compound_or_single(node):
    # 遍历{}中的每个语句
    for item in node.block_items:
        if isinstance(item, c_ast.If):
            r = get_expression_text(item.cond)
            print("r:", r)


stack = []
#
def get_expression_text(node):
    # *****************************
    if isinstance(node, c_ast.StructRef):
        if node.type == "." and get_expression_text(node.field):
            return get_expression_text(node.name) + f".{get_expression_text(node.field)}"
        else:
            return get_expression_text(node.name)
    # *****************************
    elif isinstance(node, c_ast.ArrayRef):
        return f"{get_expression_text(node.name)}[{get_expression_text(node.subscript)}]"

    if hasattr(node, "name"): # isinstance(node, c_ast.ID) and
        return node.name
    elif hasattr(node, "value"):  # isinstance(node, c_ast.Constant) and
        return node.value

    elif hasattr(node, "op"):
        if isinstance(node, c_ast.BinaryOp):
            left = get_expression_text(node.left)
            right = get_expression_text(node.right)
            return f"{left} {node.op} {right}"


# 遍历FileAst 节点的所有的子节点
for node in ast.ext:
    if isinstance(node, c_ast.FuncDef):
        process_func_def(node)

python代码运行输出r: arr[idx].data.mem1.id < 200

CLang方案

windows系统:

bash 复制代码
# 安装 MSYS2:https://www.msys2.org/
# 在 MSYS2 终端中:
pacman -Syu
pacman -S --needed base-devel mingw-w64-x86_64-toolchain

# 或单独安装 clang
pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-clang-analyzer
相关推荐
花酒锄作田14 小时前
使用 pkgutil 实现动态插件系统
python
前端付豪18 小时前
LangChain链 写一篇完美推文?用SequencialChain链接不同的组件
人工智能·python·langchain
曲幽19 小时前
FastAPI实战:打造本地文生图接口,ollama+diffusers让AI绘画更听话
python·fastapi·web·cors·diffusers·lcm·ollama·dreamshaper8·txt2img
老赵全栈实战19 小时前
Pydantic配置管理最佳实践(一)
python
阿尔的代码屋1 天前
[大模型实战 07] 基于 LlamaIndex ReAct 框架手搓全自动博客监控 Agent
人工智能·python
AI探索者2 天前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者2 天前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
FishCoderh2 天前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅2 天前
Python函数入门详解(定义+调用+参数)
python
曲幽2 天前
我用FastAPI接ollama大模型,差点被asyncio整崩溃(附对话窗口实战)
python·fastapi·web·async·httpx·asyncio·ollama