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
相关推荐
寻星探路10 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
2601_9491465312 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
ValhallaCoder13 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
猫头虎13 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
八零后琐话14 小时前
干货:程序员必备性能分析工具——Arthas火焰图
开发语言·python
知南x14 小时前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
青春不朽51215 小时前
Scrapy框架入门指南
python·scrapy
MZ_ZXD00116 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
全栈老石16 小时前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python