文章目录
- 安装 pycparser 模块
- 模块开发者网址
- 获取抽象语法树
- 1. 需要导入的模块
- 2. 获取 不关注预处理相关 c语言文件的抽象语法树ast
- 3. 获取 预处理后的c语言文件的抽象语法树ast
- 语法树组成
- 1. 数据类型定义 Typedef
- 2. 类型声明 TypeDecl
- 3. 标识符类型 IdentifierType
- 4. 变量声明 Decl
- 5. 常量 Constant
- 6. 函数定义 FuncDef
- 7. 函数声明 FuncDecl
- 8. 函数参数列表 ParamList
- 9. 代码块 Compound
- to do
感谢这两篇文章对于我学习之初的帮助
https://blog.csdn.net/u011079613/article/details/122462729
https://blog.csdn.net/qq_38808667/article/details/118059074
安装 pycparser 模块
pip install pycparser -i https://mirrors.aliyun.com/pypi/simple/
模块开发者网址
https://github.com/eliben/pycparser
获取抽象语法树
1. 需要导入的模块
# parser_file 用于处理c语言文件
from pycparser import parse_file
from pycparser import CParser
# c语言有错误时,会引出此错误
from pycparser.plyparser import ParseError
# c_ast.py 文件下包含了抽象语法树的节点类
from pycparser.c_ast import *
2. 获取 不关注预处理相关 c语言文件的抽象语法树ast
文件中需删除 #开头 预处理代码,不能有注释代码
- 方法1:
ast = parse_file(filename, use_cpp = False)
- 方法2:
with open(filename, encoding='utf-8',) as f:
txt = f.read()
ast = CParser().parse(txt) # 使用此方法需要 删除头文件
3. 获取 预处理后的c语言文件的抽象语法树ast
获取c语言文件的抽象语法树ast,如果要处理 #include 等语句,需要下载fake_libc_include文件夹,让编译器预处理常用的方法(添加其到代码的抽象语法树中)
点击此处下载 fake_libc_include

使用 parse_file 类获取 预处理后的c语言文件的抽象语法树ast
parse_file 参数 | 说明 |
|---|---|
filename | 需要解析的 .c 文件名 |
use_cpp | 是否使用本地c语言编译器预处理代码,去掉其中的#命令(头文件、宏定义、pragma)值:False/True |
cpp_path | 本地c语言编译器路径 |
cpp_args | fake_libc_include文件夹路径,需要在路径添加 -I 指明所包头文件路径; use_cpp=True 时使用 |
语法树组成
抽象语法树 ast 类型为 <class 'pycparser.c_ast.FileAST'>
其解析的具体内容通过 print(ast.ext) 查看,ext 数据类型为列表
FileAST 下级节点只有 3 种可能 :
Typedef:typedef数据类型定义Decl:变量声明FuncDef:函数声明
示例:
test.c
typedef int uint32;
int g =0;
int add(int a, int b)
{
int c = 0;
c = a + b;
return c;
}
int main(void)
{
printf("hello world");
return 0;
}
cparser.py
# parser_file 用于处理c语言文件
from pycparser import parse_file
from pycparser import CParser
# c语言有错误时,会引出此错误
from pycparser.plyparser import ParseError
# c_ast.py 文件下包含了抽象语法树的节点类
from pycparser.c_ast import *
filename = 'test.c'
ast = parse_file(filename, use_cpp = False)
print(type(ast))
for eachNode in ast.ext:
print(eachNode.__class__.__name__) # 打印节点类型名
#print(eachNode) # 打印节点内容
输出

1. 数据类型定义 Typedef
Typedef 数据结构类型 <class 'pycparser.c_ast.Typedef'>
数据类型定义 Typedef 属性如下:
Typedef.name = str(Typedef定义对象)Typedef.quals = [str](限定符号列表:const, volatile)Typedef.storage = [str](存储说明符列表:extern, register, etc.)Typedef.type = Node(TypeDecl节点)Typedef.coord= str(定义对象所在行列)Typedef.coord.column= str(定义对象所在列)Typedef.coord.line= str(定义对象所在行)Typedef.coord.file= str(定义对象所在文件)
示例:
test.c
typedef const int cuint32;
cparser.py
# parser_file 用于处理c语言文件
from pycparser import parse_file
from pycparser import CParser
# c语言有错误时,会引出此错误
from pycparser.plyparser import ParseError
# c_ast.py 文件下包含了抽象语法树的节点类
from pycparser.c_ast import *
filename = 'test.c'
ast = parse_file(filename, use_cpp = False)
print(type(ast.ext[0]))
print('name = ', ast.ext[0].name) # Typedef 定义对象
print('quals = ', ast.ext[0].quals)
print('storage = ', ast.ext[0].storage)
print('type = ', ast.ext[0].type)
print('coord = ', ast.ext[0].coord)
输出

2. 类型声明 TypeDecl
Typedef 的下一级 类型声明 TypeDecl 是以typedef语句格式为中心
类型声明 TypeDecl 属性如下:
TypeDecl.declname= str(typedef定义对象)TypeDecl.quals = [str](限定符号列表:const, volatile)TypeDecl.align= [str](暂不清楚)TypeDecl.type = Node(IdentifierType节点)TypeDecl.coord= str(定义对象所在行列)TypeDecl.coord.column= str(定义对象所在列)TypeDecl.coord.line= str(定义对象所在行)TypeDecl.coord.file= str(定义对象所在文件)
示例:
test.c
typedef const int cuint32;
cparser.py
# parser_file 用于处理c语言文件
from pycparser import parse_file
from pycparser import CParser
# c语言有错误时,会引出此错误
from pycparser.plyparser import ParseError
# c_ast.py 文件下包含了抽象语法树的节点类
from pycparser.c_ast import *
filename = 'test.c'
ast = parse_file(filename, use_cpp = False)
print(type(ast.ext[0].type))
my_typeDecl = ast.ext[0].type
print('name = ', my_typeDecl.declname) # Typedef 定义对象
print('quals = ', my_typeDecl.quals)
print('type = ', my_typeDecl.type)
print('storage = ', my_typeDecl.align)
print('coord = ', my_typeDecl.coord)
print('coord.column = ', my_typeDecl.coord.column) # (定义对象所在列)
print('coord.line = ', my_typeDecl.coord.line) # (定义对象所在行)
print('coord.file = ', my_typeDecl.coord.file) # (定义对象所在文件)
输出

3. 标识符类型 IdentifierType
TypeDecl 的下一级 标识符类型 IdentifierType 是简单标识符,比如 void, char 定义之类
原数据类型 : <class 'pycparser.c_ast.IdentifierType'>
标识符类型 IdentifierType 属性如下:
IdentifierType.name = [str](标识符字符串列表)IdentifierType.coord= str(定义对象所在行列)IdentifierType.coord.column= str(定义对象所在列)IdentifierType.coord.line= str(定义对象所在行)IdentifierType.coord.file= str(定义对象所在文件)
4. 变量声明 Decl
Decl 数据结构类型 <class 'pycparser.c_ast.Decl'>
变量声明 Decl 属性如下:
Decl.name = str(被声明的变量名)Decl.quals = [str](限定符号列表: const, volatile)Decl.align= [str](暂不清楚)Decl.storage = [str](存储说明符列表: extern, register, static等)Decl.funcspec = [str](函数说明符列表: C99的inline)Decl.type = Node(TypeDecl节点)Decl.init = Node(初始化值,Constant节点)Decl.bitsize = Node(位域bit field大小,或者为None)Decl.coord= str(定义对象所在行列)Decl.coord.column= str(定义对象所在列)Decl.coord.line= str(定义对象所在行)Decl.coord.file= str(定义对象所在文件)
示例:
test.c
typedef const int cuint32;
static const int g =0;
cparser.py
# parser_file 用于处理c语言文件
from pycparser import parse_file
from pycparser import CParser
# c语言有错误时,会引出此错误
from pycparser.plyparser import ParseError
# c_ast.py 文件下包含了抽象语法树的节点类
from pycparser.c_ast import *
filename = 'test.c'
ast = parse_file(filename, use_cpp = False)
print(type(ast.ext[1]))
my_ext = ast.ext[1]
print('name = ', ast.ext[1].name) # Typedef 定义对象
print('quals = ', ast.ext[1].quals)
print('align = ', ast.ext[1].align)
print('storage = ', ast.ext[1].storage)
print('funcspec = ', ast.ext[1].funcspec)
print('type = ', ast.ext[1].type)
print('init = ', ast.ext[1].init)
print('bitsize = ', ast.ext[1].bitsize)
print('coord = ', ast.ext[1].coord)
输出

5. 常量 Constant
常量 Constant 属性如下:
Constant.type= str(基本数据类型,int等)Constant.value= str(数值)Constant.coord= str(定义对象所在行列)Constant.coord.column= str(定义对象所在列)Constant.coord.line= str(定义对象所在行)Constant.coord.file= str(定义对象所在文件)
6. 函数定义 FuncDef
FuncDef 方法定义,不同于 FuncDecl,有具体的函数实现过程
函数定义 FuncDef 属性如下:
FuncDef.decl = Node(一般是包含Decl的节点)param_decls=None(暂不清楚)FuncDef.body = Node(函数实现的代码块 一般是包含Compound的节点)FuncDef.coord= str(标识符字符串所在行列)FuncDef.coord.column= str(定义对象所在列)FuncDef.coord.line= str(定义对象所在行)FuncDef.coord.file= str(定义对象所在文件)
7. 函数声明 FuncDecl
FuncDecl 既可以单独存在,也可以是函数定义的一部分
函数定义 FuncDecl 属性如下:
FuncDecl.args= Node(一般是包含ParamList的节点)FuncDecl.type= [str](一般是包含TypeDecl的节点)
8. 函数参数列表 ParamList
以 list 形式,可遍历 参数
函数定义 ParamList 属性如下:
ParamList.params= [str](有哪些参数 ,一般是包含Decl的节点)
9. 代码块 Compound
以 list 形式,可遍历 代码块内容
函数定义 Compound 属性如下:
Compound .block_items= [str](有哪些参数 ,一般是包含Decl Assignment 和 Return的节点)
to do
解析任意编程语言 tree-sitter



















