Rust语法分析库tree-sitter-kotlin-ng的使用:支持Kotlin语言的高效解析与语法树生成

Rust语法分析库tree-sitter-kotlin-ng的使用:支持Kotlin语言的高效解析与语法树生成

tree-sitter-kotlin是Kotlin语言的语法分析库,基于tree-sitter框架构建。

安装

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

cargo add tree-sitter-kotlin-ng

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

tree-sitter-kotlin-ng = "1.1.0"

示例代码

以下是使用tree-sitter-kotlin-ng进行Kotlin代码解析的完整示例:

use tree_sitter::Parser;
use tree_sitter_kotlin_ng::language;

fn main() {
    // 创建解析器
    let mut parser = Parser::new();
    
    // 设置Kotlin语言
    parser.set_language(language()).expect("Error loading Kotlin grammar");
    
    // 要解析的Kotlin代码
    let kotlin_code = r#"
        fun main() {
            println("Hello, World!")
        }
    "#;
    
    // 解析代码
    let tree = parser.parse(kotlin_code, None).unwrap();
    
    // 获取根节点
    let root_node = tree.root_node();
    
    // 打印语法树
    println!("{}", root_node.to_sexp());
    
    // 遍历语法树
    let mut cursor = root_node.walk();
    for child in root_node.children(&mut cursor) {
        println!("Child node: {}", child.kind());
    }
}

功能说明

  1. 该库提供了Kotlin语言的完整语法解析能力
  2. 可以生成详细的语法树结构
  3. 支持语法树的遍历和查询

完整示例demo

以下是一个更完整的示例,展示如何解析Kotlin文件并提取函数定义信息:

use tree_sitter::{Parser, TreeCursor};
use tree_sitter_kotlin_ng::language;

fn main() {
    // 初始化解析器
    let mut parser = Parser::new();
    parser.set_language(language()).expect("Error loading Kotlin grammar");

    // 示例Kotlin代码
    let code = r#"
        package com.example

        class MyClass {
            fun greet(name: String): String {
                return "Hello, $name"
            }
            
            private fun helper() {
                println("Helper function")
            }
        }
    "#;

    // 解析代码
    let tree = parser.parse(code, None).unwrap();
    let root = tree.root_node();

    // 查找所有函数定义
    let mut cursor = root.walk();
    find_functions(&mut cursor);
}

// 递归查找函数定义
fn find_functions(cursor: &mut TreeCursor) {
    loop {
        let node = cursor.node();
        
        // 如果是函数定义节点
        if node.kind() == "function_declaration" {
            // 获取函数名
            let name_node = node.child_by_field_name("name").unwrap();
            let function_name = name_node.utf8_text(code.as_bytes()).unwrap();
            
            // 获取返回类型
            let return_type = node.child_by_field_name("return_type")
                .map(|n| n.utf8_text(code.as_bytes()).unwrap())
                .unwrap_or("Unit");
                
            println!("Found function: {}(...) -> {}", function_name, return_type);
        }
        
        // 如果有子节点,递归遍历
        if cursor.goto_first_child() {
            find_functions(cursor);
            cursor.goto_parent();
        }
        
        // 移动到下一个兄弟节点
        if !cursor.goto_next_sibling() {
            break;
        }
    }
}

许可证

MIT License


1 回复

Rust语法分析库tree-sitter-kotlin-ng的使用:支持Kotlin语言的高效解析与语法树生成

tree-sitter-kotlin-ng是一个基于Rust的Tree-sitter语法分析器,专门为Kotlin语言设计,能够高效地解析Kotlin代码并生成语法树。

主要特性

  • 完整的Kotlin语法支持
  • 高性能解析
  • 增量解析能力
  • 错误恢复机制
  • 生成具体语法树(CST)

安装方法

在Cargo.toml中添加依赖:

[dependencies]
tree-sitter-kotlin-ng = "0.1.0"

基本使用方法

1. 解析Kotlin代码

use tree_sitter_kotlin_ng as tree_sitter_kotlin;
use tree_sitter::Parser;

fn main() {
    let code = r#"
        fun main() {
            println("Hello, World!")
        }
    "#;

    let mut parser = Parser::new();
    parser.set_language(tree_sitter_kotlin::language()).unwrap();
    
    let tree = parser.parse(code, None).unwrap();
    println!("{}", tree.root_node().to_sexp());
}

2. 遍历语法树

fn traverse(node: tree_sitter::Node, code: &str, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}{:?}", indent, node.kind());
    
    if node.child_count() == 0 {
        println!("{}  Text: {:?}", indent, node.utf8_text(code.as_bytes()).unwrap());
    }
    
    for i in 0..node.child_count() {
        traverse(node.child(i).unwrap(), code, depth + 1);
    }
}

3. 查询语法树

use tree_sitter::Query;

fn find_functions(tree: &tree_sitter::Tree, code: &str) {
    let query = Query::new(
        tree_sitter_kotlin::language(),
        "(function_declaration name: (simple_identifier) @fn-name)"
    ).unwrap();
    
    let mut cursor = tree_sitter::QueryCursor::new();
    for match_ in cursor.matches(&query, tree.root_node(), code.as_bytes()) {
        for capture in match_.captures {
            if capture.index == 0 { // @fn-name capture
                let node = capture.node;
                println!("Found function: {}", node.utf8_text(code.as_bytes()).unwrap());
            }
        }
    }
}

高级用法

1. 增量解析

let mut parser = Parser::new();
parser.set_language(tree_sitter_kotlin::language()).unwrap();

// 首次解析
let mut tree = parser.parse(code, None).unwrap();

// 修改代码后增量解析
let new_code = code.replace("Hello", "Hi");
let new_tree = parser.parse(new_code, Some(&tree)).unwrap();

2. 处理语法错误

let code_with_errors = "fun main() { println( }";
let tree = parser.parse(code_with_errors, None).unwrap();

if tree.root_node().has_error() {
    println!("Code contains syntax errors");
}

实际应用示例

1. 代码格式化工具的基础

fn format_code(code: &str) -> String {
    let mut parser = Parser::new();
    parser.set_language(tree_sitter_kotlin::language()).unwrap();
    let tree = parser.parse(code, None).unwrap();
    
    // 实现格式化逻辑...
    // 遍历语法树并根据节点类型添加适当的缩进和换行
    
    formatted_code
}

2. 静态代码分析

fn find_unused_variables(tree: &tree_sitter::Tree, code: &str) -> Vec<String> {
    let query = Query::new(
        tree_sitter_kotlin::language(),
        r#"
        (property_declaration (simple_identifier) @var-name)
        (not (reference_expression (simple_identifier) @var-name))
        "#
    ).unwrap();
    
    // 实现变量使用分析...
    
    unused_vars
}

性能提示

  1. 重用Parser实例以避免重复初始化开销
  2. 对于大型文件,使用增量解析
  3. 缓存常用查询以提高性能

tree-sitter-kotlin-ng为Kotlin代码分析提供了强大的基础,可以用于构建IDE插件、代码格式化工具、静态分析器等各类开发工具。

完整示例Demo

以下是一个完整的示例,展示了如何使用tree-sitter-kotlin-ng解析Kotlin代码并分析函数:

use tree_sitter_kotlin_ng as tree_sitter_kotlin;
use tree_sitter::{Parser, Query, QueryCursor};

fn main() {
    // 示例Kotlin代码
    let code = r#"
        class Example {
            fun greet(name: String) {
                println("Hello, $name!")
            }
            
            fun calculate(a: Int, b: Int): Int {
                return a + b
            }
        }
    "#;

    // 1. 初始化解析器
    let mut parser = Parser::new();
    parser.set_language(tree_sitter_kotlin::language()).unwrap();
    
    // 2. 解析代码
    let tree = parser.parse(code, None).unwrap();
    
    // 3. 打印语法树S表达式
    println!("语法树结构:\n{}\n", tree.root_node().to_sexp());
    
    // 4. 遍历语法树
    println!("遍历语法树:");
    traverse(tree.root_node(), code, 0);
    
    // 5. 查询所有函数
    println!("\n查询结果:");
    find_functions(&tree, code);
}

// 递归遍历语法树
fn traverse(node: tree_sitter::Node, code: &str, depth: usize) {
    let indent = "  ".repeat(depth);
    println!("{}{:?}", indent, node.kind());
    
    // 如果是叶子节点,打印文本内容
    if node.child_count() == 0 {
        println!("{}  Text: {:?}", indent, node.utf8_text(code.as_bytes()).unwrap());
    }
    
    // 递归处理子节点
    for i in 0..node.child_count() {
        if let Some(child) = node.child(i) {
            traverse(child, code, depth + 1);
        }
    }
}

// 查找所有函数声明
fn find_functions(tree: &tree_sitter::Tree, code: &str) {
    // 定义查询:查找函数声明并捕获函数名
    let query = Query::new(
        tree_sitter_kotlin::language(),
        "(function_declaration name: (simple_identifier) @fn-name)"
    ).unwrap();
    
    let mut cursor = QueryCursor::new();
    
    // 执行查询
    for match_ in cursor.matches(&query, tree.root_node(), code.as_bytes()) {
        for capture in match_.captures {
            // @fn-name捕获组
            if capture.index == 0 {
                let node = capture.node;
                println!("找到函数: {}", node.utf8_text(code.as_bytes()).unwrap());
            }
        }
    }
}

这个完整示例演示了:

  1. 如何初始化解析器
  2. 如何解析Kotlin代码
  3. 如何遍历语法树
  4. 如何使用查询功能查找特定语法结构
  5. 如何处理和显示结果

运行此程序将输出语法树结构、遍历过程和找到的函数名称。

回到顶部