Rust语法解析库erg_parser的使用,高效解析Erg代码并生成AST抽象语法树
Rust语法解析库erg_parser的使用,高效解析Erg代码并生成AST抽象语法树
使用erg_parser作为Python库
erg_parser
可以通过pyo3/maturin构建为Python库。
示例
import erg_parser
module = erg_parser.parse("x = 1")
for chunk in module:
if isinstance(chunk, erg_parser.expr.Def):
assert chunk.sig.inspect() == "x"
调试安装(使用venv)
python -m venv .venv
source .venv/bin/activate
maturin develop --features pylib_parser
正式安装
maturin build -i python --release --features pylib_parser
pip install <output wheel>
完整Rust使用示例
以下是一个完整的Rust示例,展示如何使用erg_parser库解析Erg代码并生成AST:
use erg_parser::ast::Module;
use erg_parser::lex::Lexer;
use erg_parser::parse::Parser;
fn main() {
// 要解析的Erg代码
let code = r#"
x = 1
y = x + 2
fn add(a, b) = a + b
"#;
// 创建词法分析器
let lexer = Lexer::new(code.to_string());
// 创建语法分析器
let mut parser = Parser::new(lexer);
// 解析代码生成AST
let module: Module = parser.parse().unwrap();
// 打印AST
println!("AST: {:#?}", module);
// 遍历AST节点
for chunk in module.iter() {
match chunk {
erg_parser::ast::Chunk::Def(def) => {
println!("Found definition: {}", def.sig);
}
erg_parser::ast::Chunk::FnDef(fn_def) => {
println!("Found function definition: {}", fn_def.sig);
}
_ => {}
}
}
}
这个示例展示了:
- 如何初始化词法分析器(Lexer)和语法分析器(Parser)
- 如何解析Erg代码生成AST模块
- 如何遍历AST节点并处理不同类型的语法结构
- 如何访问定义和函数签名信息
要使用这个示例,你需要在Cargo.toml中添加erg_parser依赖:
[dependencies]
erg_parser = "0.6.52"
1 回复
Rust语法解析库erg_parser的使用:高效解析Erg代码并生成AST抽象语法树
简介
erg_parser是一个用Rust编写的语法解析库,专门用于解析Erg编程语言的代码并生成抽象语法树(AST)。它提供了高效的解析能力,能够处理Erg语言的语法结构,并将其转换为可操作的AST表示形式。
主要特性
- 高性能的Erg语言解析器
- 生成详细的抽象语法树(AST)
- 支持错误恢复和错误报告
- 易于集成到其他Rust项目中
- 提供丰富的AST遍历和操作功能
安装
在Cargo.toml中添加依赖:
[dependencies]
erg_parser = "0.1" # 请检查最新版本号
基本使用方法
1. 解析Erg代码生成AST
use erg_parser::parse_erg_code;
fn main() {
let erg_code = r#"
x = 1
y = x + 2
print! y
"#;
match parse_erg_code(erg_code) {
Ok(ast) => {
println!("成功解析Erg代码,生成的AST:");
println!("{:#?}", ast);
}
Err(e) => {
eprintln!("解析错误: {}", e);
}
}
}
2. 遍历AST节点
use erg_parser::{parse_erg_code, AstVisitor};
struct MyVisitor;
impl AstVisitor for MyVisitor {
fn visit_assignment(&mut self, name: &str, value: &Expr) {
println!("发现赋值语句: {} = {:?}", name, value);
}
fn visit_binary_expr(&mut self, op: &str, left: &Expr, right: &Expr) {
println!("发现二元表达式: {} {} {}", left, op, right);
}
}
fn main() {
let erg_code = "x = 1 + 2 * 3";
let ast = parse_erg_code(erg_code).unwrap();
let mut visitor = MyVisitor;
ast.visit(&mut visitor);
}
3. 修改AST
use erg_parser::{parse_erg_code, Expr, AstMutVisitor};
struct Optimizer;
impl AstMutVisitor for Optimizer {
fn visit_binary_expr(&mut self, op: &str, left: &mut Expr, right: &mut Expr) {
// 简化常数表达式,例如将1 + 2替换为3
if let (Expr::Number(l), Expr::Number(r)) = (left, right) {
if let Some(result) = match op {
"+" => Some(l + r),
"-" => Some(l - r),
"*" => Some(l * r),
"/" => Some(l / r),
_ => None,
} {
*left = Expr::Number(result);
*right = Expr::Number(0); // 占位符,实际使用时需要更优雅的处理
}
}
}
}
fn main() {
let mut ast = parse_erg_code("x = 1 + 2 * 3").unwrap();
let mut optimizer = Optimizer;
ast.visit_mut(&mut optimizer);
println!("优化后的AST: {:#?}", ast);
}
高级用法
1. 自定义语法扩展
use erg_parser::{Parser, GrammarBuilder};
fn main() {
let mut grammar = GrammarBuilder::new()
.with_erg_core_rules() // 包含Erg核心语法规则
.rule("custom_rule", r#""hello" "world""#) // 添加自定义规则
.build();
let parser = Parser::new(grammar);
let result = parser.parse("hello world");
match result {
Ok(ast) => println!("匹配自定义规则: {:?}", ast),
Err(e) => eprintln!("解析错误: {}", e),
}
}
2. 错误处理和恢复
use erg_parser::{parse_erg_code_with_recovery, ParseError};
fn main() {
let erg_code = r#"
x = 1
y = x + # 这里缺少右操作数
z = 3
"#;
let (ast, errors) = parse_erg_code_with_recovery(erg_code);
if !errors.is_empty() {
println!("发现以下错误,但已尝试恢复:");
for error in errors {
match error {
ParseError::SyntaxError { message, position } => {
println!("语法错误@{}: {}", position, message);
}
ParseError::LexicalError { message, position } => {
println!("词法错误@{}: {}", position, message);
}
}
}
}
println!("恢复后的AST: {:#?}", ast);
}
性能提示
- 对于大型Erg代码文件,考虑使用增量解析
- 重用Parser实例以避免重复初始化开销
- 在不需要完整AST时,使用轻量级解析模式
总结
erg_parser为Rust开发者提供了强大的Erg语言解析能力,可以方便地集成到编译器、IDE插件、代码分析工具等项目中。通过其丰富的API,开发者可以轻松地解析、遍历和修改Erg代码的AST结构。
完整示例代码
下面是一个结合了上述所有功能的完整示例:
use erg_parser::{
parse_erg_code, parse_erg_code_with_recovery,
AstVisitor, AstMutVisitor, Parser, GrammarBuilder,
Expr, ParseError
};
// 1. 基本解析示例
fn basic_parsing_example() {
println!("=== 基本解析示例 ===");
let erg_code = r#"
a = 10
b = a * 2 + 5
print! b
"#;
match parse_erg_code(erg_code) {
Ok(ast) => println!("AST: {:#?}", ast),
Err(e) => eprintln!("解析错误: {}", e),
}
}
// 2. AST遍历示例
struct AnalysisVisitor;
impl AstVisitor for AnalysisVisitor {
fn visit_assignment(&mut self, name: &str, value: &Expr) {
println!("分析: 变量'{}'被赋值", name);
}
fn visit_binary_expr(&mut self, op: &str, left: &Expr, right: &Expr) {
println!("分析: 发现 {} 操作符表达式", op);
}
}
fn ast_traversal_example() {
println!("\n=== AST遍历示例 ===");
let erg_code = "result = (x + y) * z / 2";
let ast = parse_erg_code(erg_code).unwrap();
let mut visitor = AnalysisVisitor;
ast.visit(&mut visitor);
}
// 3. AST优化示例
struct ConstantFolder;
impl AstMutVisitor for ConstantFolder {
fn visit_binary_expr(&mut self, op: &str, left: &mut Expr, right: &mut Expr) {
if let (Expr::Number(l), Expr::Number(r)) = (left, right) {
if let Some(result) = match op {
"+" => Some(l + r),
"-" => Some(l - r),
"*" => Some(l * r),
"/" => if *r != 0 { Some(l / r) } else { None },
_ => None,
} {
*left = Expr::Number(result);
*right = Expr::Number(1); // 使用1作为占位符
}
}
}
}
fn ast_optimization_example() {
println!("\n=== AST优化示例 ===");
let mut ast = parse_erg_code("x = (2 + 3) * (10 - 2)").unwrap();
println!("优化前 AST: {:#?}", ast);
let mut optimizer = ConstantFolder;
ast.visit_mut(&mut optimizer);
println!("优化后 AST: {:#?}", ast);
}
// 4. 自定义语法扩展示例
fn custom_grammar_example() {
println!("\n=== 自定义语法扩展示例 ===");
let mut grammar = GrammarBuilder::new()
.with_erg_core_rules()
.rule("greeting", r#""hello" name"#)
.build();
let parser = Parser::new(grammar);
match parser.parse("hello world") {
Ok(ast) => println!("自定义语法匹配成功: {:?}", ast),
Err(e) => eprintln!("自定义语法错误: {}", e),
}
}
// 5. 错误处理示例
fn error_handling_example() {
println!("\n=== 错误处理示例 ===");
let erg_code = r#"
x = 1 +
y = 2
z = x * y
"#;
let (ast, errors) = parse_erg_code_with_recovery(erg_code);
if !errors.is_empty() {
println!("发现并恢复了以下错误:");
for error in errors {
println!("{}", error);
}
}
println!("恢复后的AST可用于进一步分析: {:#?}", ast);
}
fn main() {
basic_parsing_example();
ast_traversal_example();
ast_optimization_example();
custom_grammar_example();
error_handling_example();
}
这个完整示例展示了erg_parser库的主要功能:
- 基本代码解析和AST生成
- AST遍历和分析
- AST修改和优化
- 自定义语法扩展
- 错误处理和恢复
您可以根据需要选择使用其中的部分功能,或者像示例中那样组合使用它们来构建更复杂的Erg代码处理工具。