Rust Sitter:用Tree Sitter在Rust中轻松构建高效解析器的终极指南
【免费下载链接】rust-sitterUse Tree Sitter to parse your own languages in Rust项目地址: https://gitcode.com/gh_mirrors/ru/rust-sitter
Rust Sitter 是一个强大的工具,它能让开发者在 Rust 中轻松创建高效解析器,其核心是借助 Tree Sitter 解析器生成器。通过 Rust Sitter,你只需在惯用的 Rust 代码上添加注解来定义整个语法,宏就会为你生成解析器和类型安全的绑定!
🚀 快速安装步骤
要开始使用 Rust Sitter,首先需要在Cargo.toml中添加相关依赖:
[dependencies] rust-sitter = "0.4.5" [build-dependencies] rust-sitter-tool = "0.4.5"注意:默认情况下,Rust Sitter 使用 Tree Sitter 的一个分支,该分支具有纯 Rust 运行时,以支持
wasm32-unknown-unknown。如果要使用标准 C 运行时,请禁用默认功能并启用tree-sitter-standard功能。
接下来,配置build.rs来编译和链接生成的 Tree Sitter 解析器:
use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=src"); rust_sitter_tool::build_parsers(&PathBuf::from("src/main.rs")); }📝 定义语法的简单方法
Rust Sitter 语法是在带注解的 Rust 模块中定义的。下面以一个简单的算术表达式解析器为例,展示如何定义语法。
首先,定义包含语法的模块:
#[rust_sitter::grammar("arithmetic")] mod grammar { }然后,在模块内部定义 AST 节点。我们将定义一个可用于数学表达式的枚举,并使用#[rust_sitter::language]注解将其标记为根 AST 类型:
#[rust_sitter::language] pub enum Expr { Number(u32), Add(Box<Expr>, Box<Expr>) }对于Number变体,使用rust_sitter::leaf注解,通过正则表达式匹配数字,并定义将匹配的字符串转换为u32的转换函数:
Number( #[rust_sitter::leaf(pattern = r"\d+", transform = |v| v.parse().unwrap())] u32, )对于Add变体,需要在两个子表达式之间匹配+号。使用text参数指定匹配的字符串,由于我们解析为(),因此不需要提供转换函数:
#[rust_sitter::prec_left(1)] Add( Box<Expr>, #[rust_sitter::leaf(text = "+")] (), Box<Expr>, )小贴士:
#[rust_sitter::prec_left(1)]注解用于指定左结合性,解决类似1 + 2 + 3的表达式解析歧义,确保解析为(1 + 2) + 3。
完整的语法如下:
#[rust_sitter::grammar("arithmetic")] mod grammar { #[rust_sitter::language] pub enum Expr { Number( #[rust_sitter::leaf(pattern = r"\d+", transform = |v| v.parse().unwrap())] u32, ), #[rust_sitter::prec_left(1)] Add( Box<Expr>, #[rust_sitter::leaf(text = "+")] (), Box<Expr>, ) } }✨ 轻松解析文本
定义好语法后,就可以使用它来解析文本了:
dbg!(grammar::parse("1+2+3")); /* grammar::parse("1+2+3") = Ok(Add( Add( Number( 1, ), (), Number( 2, ), ), (), Number( 3, ), )) */📚 核心类型注解与字段注解
类型注解
#[rust_sitter::language]:标记解析的入口点,确定从解析返回的 AST 类型。一个语法中只能有一个类型被标记为入口点。#[rust_sitter::language] struct Code { ... }#[rust_sitter::extra]:标记一个节点为额外节点,在解析时可以安全跳过,适用于处理空格、换行和注释等。#[rust_sitter::extra] struct Whitespace { #[rust_sitter::leaf(pattern = r"\s")] _whitespace: (), }
字段注解
#[rust_sitter::leaf(...)]:用于定义 AST 中的叶节点,可通过pattern参数指定正则表达式,或text参数指定字符串来匹配文本,transform参数用于将匹配的文本转换为所需类型。#[rust_sitter::leaf(text = "9")] struct BigDigit; enum SmallDigit { #[rust_sitter::leaf(text = "0")] Zero, #[rust_sitter::leaf(text = "1")] One, }#[rust_sitter::prec(...)]/#[rust_sitter::prec_left(...)]/#[rust_sitter::prec_right(...)]:用于定义非关联、左关联或右关联运算符,参数为运算符的优先级(值越高绑定越紧密)。#[rust_sitter::skip(...)]:定义不对应输入字符串中任何内容的字段,参数为运行时用于填充该字段的值。#[rust_sitter::word]:将字段标记为 Tree Sitter 关键字,在处理涉及关键字的错误时很有用,一个语法中只能有一个字段被标记为 word。
🧩 特殊类型助力复杂语法
Vec<T>
用于解析重复结构,可通过#[rust_sitter::delimited(...)]指定元素间的分隔符,通过#[rust_sitter::repeat(...)]指定额外配置,如non_empty = true要求列表至少包含一个元素。
pub struct CommaSeparatedExprs { #[rust_sitter::repeat(non_empty = true)] #[rust_sitter::delimited( #[rust_sitter::leaf(text = ",")] () )] numbers: Vec<Expr>, }Option<T>
用于解析可选结构,可解析单个T或什么都不解析。
pub struct CommaSeparatedExprs { #[rust_sitter::repeat(non_empty = true)] #[rust_sitter::delimited( #[rust_sitter::leaf(text = ",")] () )] numbers: Vec<Option<Expr>>, }rust_sitter::Spanned<T>
用于捕获解析节点对应的文本范围,包含底层解析的T以及对应子字符串的起始(包含)和结束(不包含)索引。
pub struct CommaSeparatedExprs { #[rust_sitter::repeat(non_empty = true)] #[rust_sitter::delimited( #[rust_sitter::leaf(text = ",")] () )] numbers: Vec<Option<Spanned<Expr>>>, }Box<T>
在解析时会自动围绕内部类型构建,除此之外 Rust Sitter 不会做其他额外处理。
🔍 调试技巧
要查看生成的语法,可以将RUST_SITTER_EMIT_ARTIFACTS环境变量设置为true。生成的语法将被写入 cargo 设置的OUT_DIR(通常是target/debug/build/<crate>-<hash>/out)。
🎉 开始使用 Rust Sitter
现在你已经了解了 Rust Sitter 的基本用法,赶快尝试使用它来构建自己的解析器吧!可以通过以下命令克隆仓库开始探索:
git clone https://gitcode.com/gh_mirrors/ru/rust-sitterRust Sitter 让在 Rust 中构建解析器变得前所未有的简单,无论是用于构建编译器、静态分析工具还是其他需要解析文本的应用,它都能为你提供强大的支持。
【免费下载链接】rust-sitterUse Tree Sitter to parse your own languages in Rust项目地址: https://gitcode.com/gh_mirrors/ru/rust-sitter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考