Rust JavaScript解析库parse-js的使用,高效解析与操作JS代码的Rust工具

Rust JavaScript解析库parse-js的使用,高效解析与操作JS代码的Rust工具

安装

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

cargo add parse-js

或者将以下行添加到您的Cargo.toml中:

parse-js = "0.24.1"

示例代码

以下是一个完整的示例,展示如何使用parse-js库解析和操作JavaScript代码:

use parse_js::{parse, ast::visit::Visitor, ast::visit::walk};

// 定义一个简单的访问者来遍历AST
struct MyVisitor;

impl Visitor for MyVisitor {
    fn visit_identifier(&mut self, node: &parse_js::ast::Identifier) {
        println!("Found identifier: {}", node.name);
    }
}

fn main() {
    // 要解析的JavaScript代码
    let js_code = r#"
        function hello(name) {
            console.log('Hello, ' + name);
        }
    "#;

    // 解析JavaScript代码
    match parse(js_code) {
        Ok(ast) => {
            println!("Successfully parsed JavaScript code!");
            
            // 创建访问者并遍历AST
            let mut visitor = MyVisitor;
            walk(&mut visitor, &ast);
        }
        Err(e) => {
            eprintln!("Failed to parse JavaScript: {}", e);
        }
    }
}

完整示例代码

以下是一个更完整的示例,展示了更多parse-js的功能:

use parse_js::{parse, ast::visit::Visitor, ast::visit::walk, ast::*};

// 定义一个更详细的访问者来遍历AST
struct DetailedVisitor;

impl Visitor for DetailedVisitor {
    // 处理函数声明
    fn visit_function_decl(&mut self, node: &FunctionDecl) {
        println!("Found function declaration: {}", node.id.name);
        println!("Parameters:");
        for param in &node.params {
            println!("- {}", param.name);
        }
    }

    // 处理调用表达式
    fn visit_call_expr(&mut self, node: &CallExpr) {
        if let Expr::Identifier(ident) = &*node.callee {
            println!("Found function call: {}", ident.name);
        }
        
        println!("Arguments count: {}", node.args.len());
    }

    // 处理字符串字面量
    fn visit_string_literal(&mut self, node: &StringLit) {
        println!("Found string literal: {}", node.value);
    }
}

fn main() {
    // 要解析的更复杂的JavaScript代码
    let js_code = r#"
        function greet(name, age) {
            const message = 'Hello, ' + name;
            console.log(message, age);
            return message;
        }
        
        greet('Alice', 25);
    "#;

    // 解析JavaScript代码
    match parse(js_code) {
        Ok(ast) => {
            println!("Successfully parsed JavaScript code!");
            
            // 创建详细访问者并遍历AST
            let mut visitor = DetailedVisitor;
            walk(&mut visitor, &ast);
        }
        Err(e) => {
            eprintln!("Failed to parse JavaScript: {}", e);
        }
    }
}

类别

  • 开发工具::构建工具
  • Web编程

许可证

Apache-2.0


1 回复

Rust JavaScript解析库parse-js的使用指南

parse-js是一个用Rust编写的JavaScript解析库,它可以将JavaScript代码解析为抽象语法树(AST),并允许你对AST进行操作和分析。

主要特性

  • 高性能的JavaScript解析器
  • 完整的ECMAScript标准支持
  • 生成详细的AST表示
  • 支持AST遍历和修改
  • 轻量级且无依赖

安装方法

在Cargo.toml中添加依赖:

[dependencies]
parse-js = "0.5.0"

基本使用方法

解析JavaScript代码

use parse_js::parse;

fn main() {
    let js_code = r#"
        function greet(name) {
            return "Hello, " + name + "!";
        }
    "#;
    
    let ast = parse(js_code).expect("Failed to parse JavaScript");
    println!("{:#?}", ast);
}

遍历AST节点

use parse_js::{parse, visit::Visitor};

struct MyVisitor;

impl Visitor for MyVisitor {
    fn visit_function(&mut self, func: &parse_js::ast::Function) {
        println!("Found function: {}", func.name.as_ref().unwrap());
    }
}

fn main() {
    let js_code = r#"
        function sayHello() { console.log("Hello"); }
        function sayGoodbye() { console.log("Goodbye"); }
    "#;
    
    let ast = parse(js_code).unwrap();
    let mut visitor = MyVisitor;
    ast.visit(&mut visitor);
}

修改AST并生成代码

use parse_js::{parse, ast::*, codegen};

fn main() {
    let js_code = "let x = 1 + 2;";
    let mut ast = parse(js_code).unwrap();
    
    // 修改AST - 将加法改为乘法
    if let Statement::VariableDeclaration(decl) = &mut ast.body[0] {
        if let Some(declarator) = &mut decl.declarations[0] {
            if let Some(Expression::Binary(bin)) = &mut declarator.init {
                if bin.operator == "+" {
                    bin.operator = "*".to_string();
                }
            }
        }
    }
    
    // 生成修改后的代码
    let new_code = codegen::to_string(&ast).unwrap();
    println!("Modified code: {}", new_code); // 输出: let x = 1 * 2;
}

高级用法

处理错误和警告

use parse_js::{parse, ParseOptions};

fn main() {
    let js_code = "const 123abc = 'invalid';";
    let options = ParseOptions {
        strict_mode: true,
        ..Default::default()
    };
    
    match parse(js_code).with_options(options) {
        Ok(ast) => println!("Parsed successfully: {:#?}", ast),
        Err(errors) => {
            for error in errors {
                eprintln!("Error at {}:{} - {}", error.loc.start.line, error.loc.start.column, error.message);
            }
        }
    }
}

提取特定信息

use parse_js::{parse, visit::Visitor};

struct FunctionCounter {
    count: usize,
}

impl Visitor for FunctionCounter {
    fn visit_function(&mut self, _: &parse_js::ast::Function) {
        self.count += 1;
    }
}

fn main() {
    let js_code = r#"
        function a() {}
        function b() {}
        const c = function() {};
    "#;
    
    let ast = parse(js_code).unwrap();
    let mut counter = FunctionCounter { count: 0 };
    ast.visit(&mut counter);
    
    println!("Found {} functions", counter.count); // 输出: Found 3 functions
}

完整示例demo

以下是一个结合多个功能的完整示例,展示了如何使用parse-js解析JavaScript代码、遍历AST、修改AST并重新生成代码:

use parse_js::{parse, ast::*, visit::Visitor, codegen};

// 自定义访问者,用于查找和修改函数名
struct FunctionRenamer {
    old_name: String,
    new_name: String,
}

impl Visitor for FunctionRenamer {
    fn visit_function(&mut self, func: &mut parse_js::ast::Function) {
        if let Some(name) = &func.name {
            if name == self.old_name {
                func.name = Some(self.new_name.clone());
                println!("Renamed function from {} to {}", self.old_name, self.new_name);
            }
        }
    }
}

fn main() {
    // 示例JavaScript代码
    let js_code = r#"
        function oldFunction() {
            console.log("This is the old function");
            let result = 1 + 2;
            return result;
        }
        
        function helper() {
            return "helper function";
        }
    "#;
    
    // 1. 解析代码为AST
    println!("Parsing JavaScript code...");
    let mut ast = parse(js_code).expect("Failed to parse JavaScript");
    
    // 2. 遍历并修改AST
    println!("\nModifying AST...");
    let mut renamer = FunctionRenamer {
        old_name: "oldFunction".to_string(),
        new_name: "newFunction".to_string(),
    };
    ast.visit(&mut renamer);
    
    // 3. 修改二进制操作符
    if let Statement::FunctionDeclaration(func) = &mut ast.body[0] {
        if let Some(BlockStatement(block)) = &mut func.body {
            for stmt in &mut block.body {
                if let Statement::Expression(expr) = stmt {
                    if let Expression::Binary(bin) = &mut expr.expression {
                        if bin.operator == "+" {
                            bin.operator = "*".to_string();
                            println!("Changed binary operator from + to *");
                        }
                    }
                }
            }
        }
    }
    
    // 4. 生成修改后的代码
    println!("\nGenerating modified code...");
    let new_code = codegen::to_string(&ast).unwrap();
    println!("\nModified code:\n{}", new_code);
}

性能提示

  1. 对于大型JavaScript文件,考虑使用增量解析
  2. 如果只需要部分信息,可以实现自定义访问者来避免完整遍历AST
  3. 重用Parser实例可以提高多次解析的性能

parse-js是构建JavaScript代码分析工具、转译器或代码修改工具的强大基础库。通过其详细的AST表示和灵活的访问者模式,你可以实现各种复杂的JavaScript代码处理逻辑。

回到顶部