基于 Tree-sitter 获取分析 AST
Tree-sitter
Tree-sitter 是一个通用的解析器生成工具和增量解析库,用于高效解析源代码并生成抽象语法树(AST)。其核心特点如下:
- 通用性(General):支持将任何编程语言解析成 AST
- 快速(Fast):增量式解析,十分高效
- 健壮性(Robust):即使代码中存在语法错误,也可以生成有用的部分 AST
- 无依赖性(Dependency-free):Tree-sitter 的运行时库是用纯 C11 编写的,可以无缝嵌入到任何应用中
与基于 Clang 的 AST 分析工具依赖编译参数和编译环境不同,Tree-sitter 只需要输入待处理的文件,不依赖任何额外操作,例如不需要编译参数,不会执行预处理。
*官方文档:https://tree-sitter.github.io/tree-sitter/index.html
*项目地址:https://github.com/tree-sitter/tree-sitter
Tree-sitter 使用
介绍的是 Python环境下 Tree-sitter 的使用方法
Install
1、安装 tree-sitter 包
pip install tree-sitter
2、 下载语言解析器
在当前工程目录下新建 vendor 目录用于存放语言解析器
进入 vendor 目录将对应语言的解析器项目代码从 GitHub克隆到本地
git clone https://github.com/tree-sitter/tree-sitter-c
git clone https://github.com/tree-sitter/tree-sitter-cpp
3、 创建 build.py
在根目录( vendor 同级目录)下创建 build.py
文件,意在构建一个包含多个语言解析器的共享库,在文件中写入如下内容:
# coding=utf-8
from tree_sitter import Language
import warnings
warnings.simplefilter('ignore', FutureWarning)
Language.build_library(
# Store the library in the `build` directory
'build/my-languages.so',
# Include one or more languages
[
'vendor/tree-sitter-c',
'vendor/tree-sitter-cpp'
]
)
运行 build.py
文件,会生成一个 build 文件夹,文件路径下创建了 my-languages.so
文件,即正确构建了相关语言的语法解析器。
4、 测试验证
加载前面生成的相关语言的解析器,测试其是否能够正常解析 C 和 C++ 源代码
测试用代码如下:
from tree_sitter import Language, Parser
import warnings
warnings.simplefilter('ignore', FutureWarning)
# 加载生成的共享库文件
# 确保路径和语言名正确,"build/my-languages.so" 是之前构建的库文件
LANG_C = Language('build/my-languages.so', 'c')
LANG_CPP = Language('build/my-languages.so', 'cpp')
# 创建解析器
parser_c = Parser()
parser_cpp = Parser()
# 设置解析器的语言
parser_c.set_language(LANG_C)
parser_cpp.set_language(LANG_CPP)
# 测试 C 语言代码
c_code = b"""
int main() {
printf("Hello, World!");
return 0;
}
"""
# 测试 C++ 语言代码
cpp_code = b"""
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
"""
# 解析 C 代码
tree_c = parser_c.parse(c_code)
print("C 代码的解析结果(S表达式):")
print(tree_c.root_node.sexp()) # 输出语法树的 S 表达式
# 解析 C++ 代码
tree_cpp = parser_cpp.parse(cpp_code)
print("\nC++ 代码的解析结果(S表达式):")
print(tree_cpp.root_node.sexp()) # 输出语法树的 S 表达式
输出结果:
S 表达式(S-expressions,Symbolic Expressions)是一种简洁的树形结构表示法,用括号和嵌套的文本结构表示树形数据,非常适合表达AST。
C 代码的解析结果(S表达式):
(translation_unit
(function_definition
(primitive_type)
(function_declarator
(identifier)
(parameter_list))
(compound_statement
(expression_statement
(call_expression
(identifier)
(argument_list
(string_literal))))
(return_statement
(number_literal)))))
C++ 代码的解析结果(S表达式):
(translation_unit
(preproc_include
(string_literal))
(namespace_definition
(namespace_identifier)
(compound_statement
(function_definition
(primitive_type)
(function_declarator
(identifier)
(parameter_list))
(compound_statement
(expression_statement
(call_expression
(field_expression
(identifier)
(field_identifier))
(argument_list
(string_literal))))
(return_statement
(number_literal))))))
输出结果暂不做详细的解释说明,能输出以上结果即可表明解析器已正常安装,可以使用了