前言
在使用 tree-sitter 时候,希望把 C/C++ 的源代码表征成一段 AST (抽象语法树)的结构文本序列,以便于代码的分类预测任务,基于个人摸索,发现其实操作很简单。
什么是AST结构文本序列?
就是下面👇这个东西(它其实是一个树形文本),而我希望拿到这个代码的 AST 信息全部拼接在一起的文本序列(也就是整合成一句话)
👉 具体操作参考官方说明wiki:tree-sitter | Introduction
👉 注意,如果您还未安装tree-sitter环境,请先移步博客 👉 tree-sitter环境安装入门教程
如何生成 AST 序列?
关键就是 sexp = root.sexp()
这一句代码,可以直接将代码生成AST结构文本序列(AST sequence)。
然后,在拿到结构序列后面就接NLP(自然语言处理)
相关的技术,或者LSH(模糊哈希)
等技术,就完成了代码结构语义的表征了,精度高而且性能也好。
源代码实例
from tree_sitter import Language, Parser # 解析器库
# 这是测试用的cpp代码片段, 斐波那契数列
cpp_code_snippet = '''
int fib(int n){
long long f1 = 1, f2 = 1;
int time = (n + 1) / 2;
for (int i = 1; i < time; i++){
f1 = f1 + f2;
f2 = f2 + f1;
}
if (n % 2 == 0) return f2;
else return f1;
}
'''
# tree-sitter CPP解析器
CPP_LANGUAGE = Language('build/my-languages.so', 'cpp')
cpp_parser = Parser()
cpp_parser.set_language(CPP_LANGUAGE)
# 解析指定的源代码段
tree = cpp_parser.parse(bytes(cpp_code_snippet, "utf8"))
root = tree.root_node # 注意,root_node 才是可遍历的树节点
# 获取AST序列
sexp = root.sexp()
# 打印AST文本序列
print(sexp)
程序得到的AST序列的结果如下:
(translation_unit (function_definition type: (primitive_type) declarator: (function_declarator declarator: (identifier) parameters: (parameter_list (parameter_declaration type: (primitive_type) declarator: (identifier)))) body: (compound_statement (declaration type: (sized_type_specifier) declarator: (init_declarator declarator: (identifier) value: (number_literal)) declarator: (init_declarator declarator: (identifier) value: (number_literal))) (declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (binary_expression left: (parenthesized_expression (binary_expression left: (identifier) right: (number_literal))) right: (number_literal)))) (for_statement initializer: (declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal))) condition: (binary_expression left: (identifier) right: (identifier)) update: (update_expression argument: (identifier)) body: (compound_statement (expression_statement (assignment_expression left: (identifier) right: (binary_expression left: (identifier) right: (identifier)))) (expression_statement (assignment_expression left: (identifier) right: (binary_expression left: (identifier) right: (identifier)))))) (if_statement condition: (condition_clause value: (binary_expression left: (binary_expression left: (identifier) right: (number_literal)) right: (number_literal))) consequence: (return_statement (identifier)) alternative: (else_clause (return_statement (identifier)))))))
与 tree-sitter | playground 得到的ast tree结果的完全一致,只不过ast序列通过括号的形式来表示了树形的层级,相当于扁平化了这个AST Tree。那么后面就可以针对这个AST文本序列做一些语义抽象上的事情啦!
个人创作不易,请多多支持,欢迎提问,谢谢!