Tree-sitter0.24.0 Parser的使用


优快云和中文互联网有不少tree-sitter的用法博客,但是由于tree-sitter更新速度较快,很多内容例如函数接口都迅速的过时且无法使用了;

所以笔者根据Tree-sitter官方document来梳理了自己入门tree-sitter的一些内容;欢迎大家一起讨论学习;


当然,最好的tree-sitter学习资料仍然是官方文档,更多的信息可以翻阅以下链接:

官方文档
playground

0. 介绍

tree-sitter是 解析器 生成器 工具
为源文件构建具体的语法树

  • 通用:多语言转换AST
  • 快速
  • Robust:错误语法也能解析
  • 无依赖:纯C11编写,可以无缝嵌入,也是性能高的原因

tree-sitter支持增量解析
代码出现小范围修改时,解析器不会重新解析,只更新出现变更的部分

术语

  • 编译 compile
    将代码翻译为计算机执行的机器码;
    会进行语法错误检查、优化代码、生成可执行文件

  • 解析 parse
    将代码拆解成计算机能理解的结构
    代码->结构化表示(语法树)
    解析器会检查语法

  • 生成 generate
    把中间处理好的代码转换为目标代码(机器码或者汇编)

  • 中间表示 IR Intermediate Representation
    IR是编译器内部的通用格式;让优化和跨平台更容易;例如LLVM的IR

  • AST 抽象语法树
    树形结构来表示代码的逻辑
    不包含括号分号等无关信息,只保留代码的核心语义;
    不同的解析器生成的AST可能不同,但都是为了捕捉代码的语义

  • CFG 控制流图
    表示执行流程,代码块与条件循环语句

  • LLVM
    LLVM 是一个编译器框架,使用LLVM IR进行中间表示;LLVM IR显式表示了内存操作(load store)
    Clang,基于LLVM的编译器

编译和解析

编译器阶段:

  • 词法分析,源代码->tokens
  • 语法分析,tokens->AST
  • 语义分析,检查语义正确(变量声明与类型匹配等)
  • IR生成 ,再优化
  • 目标代码生成 Generate

解析器不会生成和执行代码,只进行分析
解析器主要是进行:

  • 词法分析:输入字符串(源代码)->tokens
  • 语法分析:tokens->语法树AST

1. Tree-sitter Parser的使用

提供了多语言的API

tree-sitter在2025年一月更新到了0.24
Language类中的build_library疑似被删除

from tree-sitter import Language
print(dir(Language))
# 查看输出中有哪些方法,如果没有build_library说明方法已经删除
# 亲测0.19.0有,而0.24.0没有
# 0.21.3 还有build_library方法

·PyPI — tree-sitter 0.21.3 · PyPI中的Build from source引用中提示:
build_library将于0.22.0删除

更为详细的使用可以参考tree-sitter0.24.0使用手册 · PyPI

最新版本tree-sitter使用

截至2025 1月0.24.0的更新,删除了build_library方法和parser的set_language方法

配置环境和准备解析器

pip install tree-sitter

# 根据需要的语言下载解析器
pip install tree-sitter-cpp
pip install tree-sitter-python

解析

import tree_sitter_python
import tree_sitter_cpp
from tree_sitter import Language, Parser

# 加载Language对象
PY_LANGAUGE = Language(tree_sitter_python.language())
CPP_LANGAUGE = Language(tree_sitter_cpp.language())

# 创建Parser并配置语言
cpp_parser = Parser(CPP_LANGUAGE)
# insdead of cpp_parser=Parser()   cpp_parser.set_language(CPP_LANGUAGE)

# 准备用于解析的代码段
cpp_code_snippet = '''
// Your Code
'''

# 进行解析
tree = cpp_parser.parse(
	bytes(
		cpp_code_snippet, "utf-8"
	)
)

# 获取AST的节点
root_node = tree.root_node

# 遍历AST
cursor = tree.walk() 

解析后的节点访问

单个节点的访问可以通过TSNode这个API去访问;

节点

root_node = tree.root_node

root_node.type
# 类型,例如函数定义(function_definition),字符串(string)

节点有哪些属性

属性 说明
type 类型
start_point 节点在代码的开始位置,(row, column)
end_point 节点在代码的结束位置
start_byte
end_byte
children 子节点列表
sexp() 返回S表达式,string

cursor遍历

但是大量的访问还是使用光标tree cursor更加合适
cursor是一个带有状态的对象

tree = parser.parse(
	bytes(code, 'utf-8')
)
cursor = tree.walk() # 创建了一个cursor对象

cursor的遍历

cursor.goto_first_child()
# 成功返回True,并移动到第一个子节点; 否则返回False

cursor.goto_next_sibling()
# 成功返回True,并移动到下一个兄弟节点;  否则返回False

cursor.goto_parent()
# 返回到父节点,返回True; 否则返回False


print(f"Node type: {
     
     cursor.node.type}")

print(f"Text: {
     
     code[cursor.node.start_byte:cursor.node.end_byte].decode('utf-8')}")
# 获取节点的源代码

递归进行遍历

# 递归进行遍历
def traverse(cursor):
    node 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值