文章目錄
- 安裝 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