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
相关推荐
yashuk9 分钟前
C语言 vs. C++ ,哪个更适合初学者?
c语言·c++·面向对象编程·初学者·学习路径
l1t9 分钟前
用wsl自带的python 3.10下载适用于3.12的pandas版本结合uv安装python 3.12模拟离线安装场景
python·pandas·uv
飞Link30 分钟前
【AI大模型实战】万字长文肝透大语言模型(LLM):从底层原理解析到企业级Python项目落地
开发语言·人工智能·python·语言模型·自然语言处理
翻斗包菜34 分钟前
第 03 章 Python 操作 MySQL 数据库实战全解
数据库·python·mysql
泛凡(Linyongui)34 分钟前
PY32F002B实践之四--宠物腹背理疗仪项目踩坑及项目总结复盘
c语言·keil·32位单片机·腹背理疗仪项目实践·普苒py32
Hello小赵39 分钟前
C语言如何自定义链接库——编译与调用
android·java·c语言
xcjbqd01 小时前
如何修改Oracle服务器默认的日期格式_NLS_DATE_FORMAT全局配置
jvm·数据库·python
white-persist1 小时前
【vulhub spring CVE-2018-1270】CVE-2018-1270 Spring Messaging 远程命令执行漏洞 完整复现详细分析解释
java·服务器·网络·数据库·后端·python·spring
JaneHan_1 小时前
STM32CubeMX+HAL+Keil5 PWM呼吸灯
c语言·stm32·单片机
EnCi Zheng1 小时前
P2G-Python字符串方法完全指南-split、join、strip、replace的Python编程利器
开发语言·python