南城东莞网站建设网站源码下载视频
文章目录
- 安装 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
 
 cpp_args必须加上 -E , 否则返回的抽象语法树是个空列表
ast = parse_file(filename, use_cpp = True, cpp_path=r'C:\MinGW\bin\gcc.exe', cpp_args=['-E', r'-Iutils/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].typeprint('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
