Rust正则表达式解析库tree-sitter-regex的使用,支持高效语法树构建和模式匹配

tree-sitter-regex

安装

在项目目录中运行以下Cargo命令:

cargo add tree-sitter-regex

或者在Cargo.toml中添加以下行:

tree-sitter-regex = "0.24.3"

使用示例

下面是一个使用tree-sitter-regex库解析正则表达式并构建语法树的完整示例:

use tree_sitter::Parser;
use tree_sitter_regex::language;

fn main() {
    // 创建解析器
    let mut parser = Parser::new();
    
    // 设置正则表达式语言
    let language = language();
    parser.set_language(language).unwrap();

    // 要解析的正则表达式
    let regex = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
    
    // 解析正则表达式
    let tree = parser.parse(regex, None).unwrap();
    
    // 获取根节点
    let root_node = tree.root_node();
    
    // 打印语法树
    println!("Syntax tree:");
    print_tree(&root_node, 0);
}

// 递归打印语法树
fn print_tree(node: &tree_sitter::Node, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}{:?}", indent, node);
    
    let mut cursor = node.walk();
    for child in node.children(&mut cursor) {
        print_tree(&child, depth + 1);
    }
}

功能特点

  1. 高效的正则表达式语法解析
  2. 构建详细的语法树结构
  3. 支持正则表达式模式匹配
  4. 与其他tree-sitter工具集成

完整示例demo

下面是一个更完整的示例,展示如何解析不同的正则表达式模式并分析语法树:

use tree_sitter::{Parser, Node};
use tree_sitter_regex::language;

fn main() {
    // 初始化解析器
    let mut parser = Parser::new();
    parser.set_language(language()).unwrap();

    // 测试不同的正则表达式模式
    let patterns = vec![
        r"\d{3}-\d{2}-\d{4}",       // 社会安全号码模式
        r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}",  // 电子邮件模式
        r"^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$",  // URL模式
        r"(\d{1,3}\.){3}\d{1,3}",   // IP地址模式
    ];

    for pattern in patterns {
        println!("\n解析正则表达式: {}", pattern);
        
        // 解析正则表达式
        let tree = parser.parse(pattern, None).unwrap();
        let root = tree.root_node();
        
        // 打印语法树
        println!("语法树结构:");
        print_tree(&root, 0);
        
        // 分析特定节点
        analyze_pattern(&root);
    }
}

fn print_tree(node: &Node, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}{:?}", indent, node);
    
    let mut cursor = node.walk();
    for child in node.children(&mut cursor) {
        print_tree(&child, depth + 1);
    }
}

fn analyze_pattern(root: &Node) {
    let mut cursor = root.walk();
    println!("\n正则表达式分析结果:");
    
    // 遍历所有量词节点
    for node in root.children(&mut cursor) {
        if node.kind() == "quantifier" {
            println!(" - 找到量词: {}", node.utf8_text(root.start_byte()).unwrap());
        }
    }
    
    // 检查字符类
    for node in root.children(&mut cursor) {
        if node.kind() == "character_class" {
            println!(" - 找到字符类: {}", node.utf8_text(root.start_byte()).unwrap());
        }
    }
}

功能特点

  1. 高效的正则表达式语法解析
  2. 构建详细的语法树结构
  3. 支持正则表达式模式匹配
  4. 与其他tree-sitter工具集成

1 回复

Rust正则表达式解析库tree-sitter-regex使用指南

概述

tree-sitter-regex是一个基于Tree-sitter的Rust正则表达式解析库,能够将正则表达式解析为语法树,支持高效的语法分析和模式匹配操作。

主要特性

  • 将正则表达式解析为语法树结构
  • 支持高效的模式匹配
  • 提供详细的语法节点信息
  • 可与其他Tree-sitter工具集成

安装方法

在Cargo.toml中添加依赖:

[dependencies]
tree-sitter-regex = "0.20.0"
tree-sitter = "0.20.0"

基本使用方法

1. 解析正则表达式

use tree_sitter::Parser;
use tree_sitter_regex::language;

fn main() {
    // 创建解析器实例
    let mut parser = Parser::new();
    // 设置正则表达式语言
    parser.set_language(language()).unwrap();
    
    // 定义要解析的正则表达式(电子邮件验证)
    let regex = r"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$";
    // 解析正则表达式
    let tree = parser.parse(regex, None).unwrap();
    
    // 打印语法树的S表达式表示
    println!("{}", tree.root_node().to_sexp());
}

2. 遍历语法树

// 递归打印语法树节点
fn print_nodes(node: tree_sitter::Node, source: &str, depth: usize) {
    // 创建缩进字符串
    let indent = "  ".repeat(depth);
    // 打印节点类型和内容
    println!("{}{:?} - {}", indent, node.kind(), node.utf8_text(source.as_bytes()).unwrap());
    
    // 创建游标遍历子节点
    let mut cursor = node.walk();
    // 递归打印所有子节点
    for child in node.children(&mut cursor) {
        print_nodes(child, source, depth + 1);
    }
}

3. 模式匹配检查

use tree_sitter_regex::RegexQuery;

// 检查文本是否匹配正则表达式
fn check_pattern(regex: &str, text: &str) -> bool {
    // 创建正则查询
    let query = RegexQuery::new(regex).unwrap();
    // 检查匹配
    query.matches(text)
}

fn main() {
    // 电子邮件正则表达式
    let email_regex = r"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$";
    // 测试有效电子邮件
    println!("Valid email? {}", check_pattern(email_regex, "test@example.com")); // true
    // 测试无效电子邮件
    println!("Valid email? {}", check_pattern(email_regex, "invalid-email"));    // false
}

高级用法

1. 提取匹配组

use tree_sitter_regex::RegexQuery;

// 提取正则表达式匹配的组
fn extract_groups(regex: &str, text: &str) {
    // 创建正则查询
    let query = RegexQuery::new(regex).unwrap();
    // 获取捕获组
    if let Some(captures) = query.captures(text) {
        // 打印所有捕获组
        for (i, group) in captures.iter().enumerate() {
            println!("Group {}: {:?}", i, group.map(|g| g.to_string()));
        }
    }
}

fn main() {
    // 日期正则表达式(包含捕获组)
    let date_regex = r"(\d{4})-(\d{2})-(\d{2})";
    // 提取日期各部分
    extract_groups(date_regex, "2023-05-15");
    // 输出:
    // Group 0: Some("2023-05-15")
    // Group 1: Some("2023")
    // Group 2: Some("05")
    // Group 3: Some("15")
}

2. 语法树可视化

use tree_sitter::Parser;
use tree_sitter_regex::language;

// 可视化正则表达式语法树
fn visualize_tree(regex: &str) {
    // 创建解析器
    let mut parser = Parser::new();
    parser.set_language(language()).unwrap();
    // 解析正则表达式
    let tree = parser.parse(regex, None).unwrap();
    
    // 使用栈进行深度优先遍历
    let mut cursor = tree.walk();
    let mut stack = vec![(cursor.node(), 0)];
    
    while let Some((node, depth)) = stack.pop() {
        // 打印节点类型和缩进
        let indent = "  ".repeat(depth);
        println!("{}{:?}", indent, node.kind());
        
        // 收集子节点并逆序(因为栈是后进先出)
        let mut child_cursor = node.walk();
        let mut children: Vec<_> = node.children(&mut child_cursor).collect();
        children.reverse();
        
        // 将子节点压入栈
        for child in children {
            stack.push((child, depth + 1));
        }
    }
}

fn main() {
    // 可视化社保号格式正则表达式
    visualize_tree(r"\d{3}-\d{2}-\d{4}");
}

性能优化建议

  1. 重用Parser实例:Parser创建成本较高,应尽量重用
  2. 预编译常用正则表达式:将频繁使用的正则表达式预先解析为RegexQuery
  3. 使用更简单的正则表达式:复杂正则表达式会生成更大的语法树,影响性能

常见问题

1. 不支持的正则特性

tree-sitter-regex可能不支持某些高级正则特性,如:

  • 后向引用
  • 复杂的断言
  • 某些递归模式

2. 错误处理

use tree_sitter_regex::RegexQuery;

// 安全解析正则表达式
fn safe_parse(regex: &str) -> Result<RegexQuery, String> {
    RegexQuery::new(regex).map_err(|e| format!("Regex parse error: {:?}", e))
}

fn main() {
    // 测试无效正则表达式
    match safe_parse(r"invalid[regex") {
        Ok(_) => println!("Valid regex"),
        Err(e) => println!("Error: {}", e),
    }
}

完整示例代码

下面是一个结合了上述功能的完整示例:

use tree_sitter::{Parser, Node};
use tree_sitter_regex::{language, RegexQuery};

fn main() {
    // 1. 解析正则表达式
    let mut parser = Parser::new();
    parser.set_language(language()).unwrap();
    
    let regex_pattern = r"(\w+)=(\d+)";
    let tree = parser.parse(regex_pattern, None).unwrap();
    println!("Syntax tree:\n{}", tree.root_node().to_sexp());
    
    // 2. 遍历语法树
    println!("\nTree traversal:");
    print_nodes(tree.root_node(), regex_pattern, 0);
    
    // 3. 模式匹配检查
    println!("\nPattern matching:");
    let text_to_match = "count=42";
    println!("Does '{}' match pattern? {}", text_to_match, 
        check_pattern(regex_pattern, text_to_match));
    
    // 4. 提取匹配组
    println!("\nCaptured groups:");
    extract_groups(regex_pattern, text_to_match);
    
    // 5. 语法树可视化
    println!("\nTree visualization:");
    visualize_tree(regex_pattern);
    
    // 6. 错误处理示例
    println!("\nError handling:");
    match safe_parse(r"invalid[regex") {
        Ok(_) => println!("Valid regex"),
        Err(e) => println!("Error: {}", e),
    }
}

// 遍历语法树的辅助函数
fn print_nodes(node: Node, source: &str, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}{:?} - {}", indent, node.kind(), node.utf8_text(source.as_bytes()).unwrap());
    
    let mut cursor = node.walk();
    for child in node.children(&mut cursor) {
        print_nodes(child, source, depth + 1);
    }
}

// 检查模式匹配的辅助函数
fn check_pattern(regex: &str, text: &str) -> bool {
    RegexQuery::new(regex).unwrap().matches(text)
}

// 提取捕获组的辅助函数
fn extract_groups(regex: &str, text: &str) {
    let query = RegexQuery::new(regex).unwrap();
    if let Some(captures) = query.captures(text) {
        for (i, group) in captures.iter().enumerate() {
            println!("Group {}: {:?}", i, group.map(|g| g.to_string()));
        }
    }
}

// 可视化语法树的辅助函数
fn visualize_tree(regex: &str) {
    let mut parser = Parser::new();
    parser.set_language(language()).unwrap();
    let tree = parser.parse(regex, None).unwrap();
    
    let mut cursor = tree.walk();
    let mut stack = vec![(cursor.node(), 0)];
    
    while let Some((node, depth)) = stack.pop() {
        let indent = "  ".repeat(depth);
        println!("{}{:?}", indent, node.kind());
        
        let mut child_cursor = node.walk();
        let mut children: Vec<_> = node.children(&mut child_cursor).collect();
        children.reverse();
        
        for child in children {
            stack.push((child, depth + 1));
        }
    }
}

// 安全解析的辅助函数
fn safe_parse(regex: &str) -> Result<RegexQuery, String> {
    RegexQuery::new(regex).map_err(|e| format!("Regex parse error: {:?}", e))
}

这个完整示例演示了tree-sitter-regex库的主要功能:

  1. 解析正则表达式为语法树
  2. 遍历和可视化语法树结构
  3. 进行模式匹配检查
  4. 提取匹配的捕获组
  5. 处理可能出现的错误

tree-sitter-regex为Rust开发者提供了强大的正则表达式解析能力,特别适合需要深入分析正则表达式结构或构建正则相关工具的场景。

回到顶部