| @@ -0,0 +1,45 @@ | |||||
| # Rust构建输出目录 | |||||
| /target/ | |||||
| # Rust工具链和依赖管理 | |||||
| **/.rustc_info.json | |||||
| **/.cargo-lock | |||||
| .rustup/ | |||||
| # IDE和编辑器文件 | |||||
| .idea/ | |||||
| .vscode/* | |||||
| !.vscode/settings.json | |||||
| !.vscode/tasks.json | |||||
| !.vscode/launch.json | |||||
| !.vscode/extensions.json | |||||
| *.sublime-workspace | |||||
| *.sublime-project | |||||
| *.swp | |||||
| *.swo | |||||
| *~ | |||||
| .DS_Store | |||||
| # 调试文件 | |||||
| *.pdb | |||||
| *.dSYM/ | |||||
| *.su | |||||
| *.idb | |||||
| # 生成的文件 | |||||
| *.rs.bk | |||||
| Cargo.lock | |||||
| *.profraw | |||||
| # 测试输出 | |||||
| test_output.rs | |||||
| # 日志文件 | |||||
| *.log | |||||
| # 临时文件 | |||||
| *.tmp | |||||
| *.bak | |||||
| # AST输出文件 | |||||
| *.json | |||||
| @@ -0,0 +1,15 @@ | |||||
| [package] | |||||
| name = "rustdds-gen" | |||||
| version = "0.1.0" | |||||
| edition = "2021" | |||||
| description = "IDL到Rust代码转换工具,用于RustDDS项目的代码生成器" | |||||
| [dependencies] | |||||
| pest = "2.8" | |||||
| pest_derive = "2.8" | |||||
| clap = { version = "4.4", features = ["derive"] } | |||||
| serde = { version = "1.0", features = ["derive"] } | |||||
| serde_json = "1.0" | |||||
| anyhow = "1.0" | |||||
| thiserror = "2.0.12" | |||||
| regex = "1.11.1" | |||||
| @@ -0,0 +1,143 @@ | |||||
| # RustDDS-Gen | |||||
| RustDDS-Gen 是一个用于将 IDL(接口定义语言)文件转换为 Rust 代码的工具。该工具专为 RustDDS 项目设计,支持解析 IDL 文件并生成相应的 Rust 结构体、枚举、常量等。 | |||||
| ## 项目概述 | |||||
| RustDDS-Gen 提供了一个完整的 IDL 到 Rust 代码的转换流程,主要包括: | |||||
| - IDL 文件解析(基于 pest 解析器) | |||||
| - 语法树(AST)构建和处理 | |||||
| - Rust 代码生成 | |||||
| - 命令行界面,支持多种选项 | |||||
| ## 功能特性 | |||||
| - 支持解析复杂的 IDL 文件,包括: | |||||
| - 模块(module)和嵌套模块 | |||||
| - 结构体(struct) | |||||
| - 枚举(enum) | |||||
| - 常量(const) | |||||
| - 类型定义(typedef) | |||||
| - 接口(interface) | |||||
| - 联合类型(union) | |||||
| - 序列(sequence) | |||||
| - 支持各种 IDL 数据类型,如 string、octet、long、double 等 | |||||
| - 支持参数方向(in、out、inout) | |||||
| - 提供详细的解析和代码生成日志 | |||||
| - 支持调试选项,如打印语法树、保存语法树到文件等 | |||||
| ## 项目结构 | |||||
| ``` | |||||
| RustDDS-Gen/ | |||||
| ├── Cargo.toml # 项目配置和依赖 | |||||
| ├── src/ # 源代码目录 | |||||
| │ ├── main.rs # 主程序入口 | |||||
| │ ├── parser/ # IDL 解析器 | |||||
| │ │ ├── mod.rs # 解析器主模块 | |||||
| │ │ ├── idl.pest # Pest 语法规则 | |||||
| │ │ ├── interface.rs # 接口解析 | |||||
| │ │ └── union.rs # 联合类型解析 | |||||
| │ └── codegen/ # 代码生成器 | |||||
| │ ├── mod.rs # 代码生成主模块 | |||||
| │ ├── interface.rs # 接口代码生成 | |||||
| │ ├── typedef.rs # 类型定义代码生成 | |||||
| │ └── union.rs # 联合类型代码生成 | |||||
| ├── test.idl # 测试用 IDL 文件 | |||||
| └── test_output.rs # 测试生成的 Rust 代码 | |||||
| ``` | |||||
| ## 依赖项 | |||||
| - pest (2.8): 用于解析 IDL 文件 | |||||
| - pest_derive (2.8): 用于派生 pest 解析器 | |||||
| - clap (4.4): 用于命令行参数解析 | |||||
| - serde (1.0): 用于序列化和反序列化 | |||||
| - serde_json (1.0): 用于 JSON 处理 | |||||
| - anyhow (1.0): 用于错误处理 | |||||
| - thiserror (2.0.12): 用于自定义错误类型 | |||||
| - regex (1.11.1): 用于正则表达式处理 | |||||
| ## 使用方法 | |||||
| ### 基本用法 | |||||
| ```bash | |||||
| rustdds-gen --input <IDL文件路径> --output <Rust文件输出路径> | |||||
| ``` | |||||
| ### 命令行选项 | |||||
| - `-i, --input <文件路径>`: 指定输入的 IDL 文件 | |||||
| - `-o, --output <文件路径>`: 指定输出的 Rust 文件 | |||||
| - `-d, --debug`: 启用调试输出 | |||||
| - `--parse-only`: 只解析语法,不生成代码 | |||||
| - `--verbose`: 打印详细的解析过程 | |||||
| - `--print-ast`: 打印语法树 | |||||
| - `--dump-ast <文件路径>`: 将解析结果保存到文件 | |||||
| ### 示例 | |||||
| ```bash | |||||
| # 基本用法 | |||||
| rustdds-gen --input test.idl --output test_output.rs | |||||
| # 调试模式 | |||||
| rustdds-gen --input test.idl --output test_output.rs --debug | |||||
| # 只解析不生成代码 | |||||
| rustdds-gen --input test.idl --output test_output.rs --parse-only | |||||
| # 保存语法树到文件 | |||||
| rustdds-gen --input test.idl --output test_output.rs --dump-ast ast.json | |||||
| ``` | |||||
| ## IDL 支持特性 | |||||
| RustDDS-Gen 支持以下 IDL 特性: | |||||
| - 基本数据类型:boolean, char, octet, short, long, float, double, string 等 | |||||
| - 自定义类型:struct, enum, typedef, union | |||||
| - 模块和嵌套模块 | |||||
| - 常量定义 | |||||
| - 接口和方法 | |||||
| - 参数方向(in, out, inout) | |||||
| - 序列(sequence) | |||||
| - 有限长度字符串(string<N>) | |||||
| ## 开发指南 | |||||
| ### 构建项目 | |||||
| ```bash | |||||
| cargo build | |||||
| ``` | |||||
| ### 运行测试 | |||||
| ```bash | |||||
| cargo test | |||||
| ``` | |||||
| ### 添加新的 IDL 特性支持 | |||||
| 1. 在 `src/parser/idl.pest` 中添加新的语法规则 | |||||
| 2. 在 `src/parser/mod.rs` 中添加相应的解析函数 | |||||
| 3. 在 `src/codegen/mod.rs` 中添加相应的代码生成函数 | |||||
| ## 许可证 | |||||
| [待定] | |||||
| ## 贡献指南 | |||||
| 欢迎提交问题报告和拉取请求。对于重大更改,请先开启一个问题进行讨论。 | |||||
| ## 未来计划 | |||||
| - 支持更多 IDL 特性 | |||||
| - 改进错误处理和报告 | |||||
| - 添加更多单元测试和集成测试 | |||||
| - 支持生成序列化/反序列化代码 | |||||
| - 支持生成 DDS 相关代码 | |||||
| @@ -0,0 +1,108 @@ | |||||
| use anyhow::Result; | |||||
| use std::io::Write; | |||||
| use std::fs::File; | |||||
| use crate::parser::{IdlInterface, IdlMethod, IdlParameter, ParameterDirection}; | |||||
| use crate::codegen::map_idl_type_to_rust; | |||||
| /// 生成接口代码 | |||||
| pub fn generate_interface_code(file: &mut File, interface: &IdlInterface, indent: &str) -> Result<()> { | |||||
| // 在Rust中,接口对应的是trait | |||||
| writeln!(file, "{}/// 由IDL接口`{}`生成的trait", indent, interface.name)?; | |||||
| writeln!(file, "{}pub trait {} {{", indent, interface.name)?; | |||||
| // 生成接口中的方法 | |||||
| let method_indent = format!("{} ", indent); | |||||
| for method in &interface.methods { | |||||
| generate_method_code(file, method, &method_indent)?; | |||||
| } | |||||
| writeln!(file, "{}}}", indent)?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成方法代码 | |||||
| fn generate_method_code(file: &mut File, method: &IdlMethod, indent: &str) -> Result<()> { | |||||
| // 生成方法文档注释 | |||||
| writeln!(file, "{}/// {}", indent, method.name)?; | |||||
| // 生成方法签名 | |||||
| write!(file, "{}fn {}(", indent, method.name)?; | |||||
| // 生成方法参数 | |||||
| write!(file, "&self")?; | |||||
| for param in &method.parameters { | |||||
| write!(file, ", ")?; | |||||
| // 先检查参数名称是否为空,如果为空,则使用一个默认的参数名称 | |||||
| if param.name.is_empty() { | |||||
| // 使用一个默认的参数名称 | |||||
| let param_name = "param"; | |||||
| let mut param_with_name = param.clone(); | |||||
| param_with_name.name = param_name.to_string(); | |||||
| generate_parameter_code(file, ¶m_with_name)?; | |||||
| } else { | |||||
| generate_parameter_code(file, param)?; | |||||
| } | |||||
| } | |||||
| // 生成返回类型 | |||||
| if method.return_type != "void" { | |||||
| let rust_return_type = map_idl_type_to_rust(&method.return_type); | |||||
| writeln!(file, ") -> {};", rust_return_type)?; | |||||
| } else { | |||||
| writeln!(file, ");", )?; | |||||
| } | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成参数代码 | |||||
| fn generate_parameter_code(file: &mut File, param: &IdlParameter) -> Result<()> { | |||||
| // 先处理参数类型,去除可能的方向修饰符 | |||||
| let type_spec = param.type_spec.trim(); | |||||
| let type_spec = if type_spec.starts_with("in ") { | |||||
| type_spec.trim_start_matches("in ").trim() | |||||
| } else if type_spec.starts_with("out ") { | |||||
| type_spec.trim_start_matches("out ").trim() | |||||
| } else if type_spec.starts_with("inout ") { | |||||
| type_spec.trim_start_matches("inout ").trim() | |||||
| } else { | |||||
| type_spec | |||||
| }; | |||||
| // 根据参数方向生成参数修饰符 | |||||
| match param.direction { | |||||
| ParameterDirection::In => { | |||||
| // 输入参数,使用不可变引用 | |||||
| // 如果是字符串类型,使用&str而不是&String | |||||
| if type_spec.trim() == "string" { | |||||
| write!(file, "{}: &str", param.name)?; | |||||
| } else { | |||||
| let rust_type = map_idl_type_to_rust(type_spec); | |||||
| write!(file, "{}: &{}", param.name, rust_type)?; | |||||
| } | |||||
| }, | |||||
| ParameterDirection::Out => { | |||||
| // 输出参数,使用可变引用 | |||||
| // 如果是字符串类型,使用&mut String | |||||
| if type_spec.trim() == "string" { | |||||
| write!(file, "{}: &mut String", param.name)?; | |||||
| } else { | |||||
| let rust_type = map_idl_type_to_rust(type_spec); | |||||
| write!(file, "{}: &mut {}", param.name, rust_type)?; | |||||
| } | |||||
| }, | |||||
| ParameterDirection::InOut => { | |||||
| // 输入输出参数,使用可变引用 | |||||
| // 如果是字符串类型,使用&mut String | |||||
| if type_spec.trim() == "string" { | |||||
| write!(file, "{}: &mut String", param.name)?; | |||||
| } else { | |||||
| let rust_type = map_idl_type_to_rust(type_spec); | |||||
| write!(file, "{}: &mut {}", param.name, rust_type)?; | |||||
| } | |||||
| } | |||||
| } | |||||
| Ok(()) | |||||
| } | |||||
| @@ -0,0 +1,449 @@ | |||||
| //! IDL 到 Rust 代码生成模块 | |||||
| //! | |||||
| //! 该模块负责将解析后的 IDL 文件结构转换为 Rust 代码。 | |||||
| //! 生成的代码包括结构体、枚举、常量、类型定义和接口等。 | |||||
| use crate::parser::{IdlFile, IdlModule, IdlStruct, IdlEnum, IdlConstant, IdlConstValue, IdlUnion, IdlTypedef, IdlInterface, ModuleItem}; | |||||
| use std::fs::File; | |||||
| use std::io::{Write, Result as IoResult}; | |||||
| use std::path::Path; | |||||
| use anyhow::{Result, Context}; | |||||
| // 引入各种类型的代码生成模块 | |||||
| mod union; // 生成 union 类型的代码 | |||||
| mod typedef; // 生成类型定义的代码 | |||||
| mod interface; // 生成接口的代码 | |||||
| // 将generate_union_code函数定义为内联函数 | |||||
| fn generate_union_code(file: &mut File, idl_union: &IdlUnion, indent: &str) -> Result<()> { | |||||
| union::generate_union_code(file, idl_union, indent) | |||||
| } | |||||
| // 将generate_typedef_code函数定义为内联函数 | |||||
| fn generate_typedef_code(file: &mut File, typedef: &IdlTypedef, indent: &str) -> Result<()> { | |||||
| typedef::generate_typedef_code(file, typedef, indent) | |||||
| } | |||||
| // 将generate_interface_code函数定义为内联函数 | |||||
| fn generate_interface_code(file: &mut File, idl_interface: &IdlInterface, indent: &str) -> Result<()> { | |||||
| interface::generate_interface_code(file, idl_interface, indent) | |||||
| } | |||||
| /// 生成 Rust 代码 | |||||
| /// | |||||
| /// 该函数是代码生成模块的主要入口点,负责将解析后的 IDL 文件结构 | |||||
| /// 转换为 Rust 代码并写入指定的输出文件。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `idl_file` - 解析后的 IDL 文件结构 | |||||
| /// * `output_file` - 输出 Rust 代码的文件路径 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| pub fn generate_rust_code(idl_file: &IdlFile, output_file: &Path) -> Result<()> { | |||||
| let mut file = File::create(output_file) | |||||
| .with_context(|| format!("无法创建输出文件: {:?}", output_file))?; | |||||
| // 生成文件头 | |||||
| write_file_header(&mut file)?; | |||||
| // 生成模块 | |||||
| for module in &idl_file.modules { | |||||
| generate_module_code(&mut file, module)?; | |||||
| } | |||||
| // 生成顶级结构体 | |||||
| for idl_struct in &idl_file.structs { | |||||
| generate_struct_code(&mut file, idl_struct, "")?; | |||||
| } | |||||
| // 生成顶级枚举 | |||||
| for idl_enum in &idl_file.enums { | |||||
| generate_enum_code(&mut file, idl_enum, "")?; | |||||
| } | |||||
| Ok(()) | |||||
| } | |||||
| /// 写入文件头 | |||||
| /// | |||||
| /// 在生成的 Rust 代码文件开头添加注释和必要的导入语句。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `IoResult<()>` - 成功时返回 `()`,失败时返回 IO 错误 | |||||
| fn write_file_header(file: &mut File) -> IoResult<()> { | |||||
| writeln!(file, "// 自动从IDL生成的代码")?; | |||||
| writeln!(file, "// 请勿手动修改")?; | |||||
| writeln!(file, "")?; | |||||
| writeln!(file, "use serde::{{Serialize, Deserialize}};")?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成模块代码 | |||||
| /// | |||||
| /// 将 IDL 模块转换为 Rust 模块,并生成其内部的所有元素。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// * `module` - 要生成代码的 IDL 模块 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn generate_module_code(file: &mut File, module: &IdlModule) -> Result<()> { | |||||
| writeln!(file, "pub mod {} {{", module.name)?; | |||||
| writeln!(file, " use super::*;")?; | |||||
| writeln!(file, "")?; | |||||
| // 按照原始顺序生成代码 | |||||
| for item in &module.items { | |||||
| match item { | |||||
| ModuleItem::Constant(constant) => { | |||||
| generate_constant_code(file, constant, " ")?; | |||||
| }, | |||||
| ModuleItem::Typedef(typedef) => { | |||||
| generate_typedef_code(file, typedef, " ")?; | |||||
| }, | |||||
| ModuleItem::Enum(enum_def) => { | |||||
| generate_enum_code(file, enum_def, " ")?; | |||||
| }, | |||||
| ModuleItem::Union(union_def) => { | |||||
| generate_union_code(file, union_def, " ")?; | |||||
| }, | |||||
| ModuleItem::Struct(struct_def) => { | |||||
| generate_struct_code(file, struct_def, " ")?; | |||||
| }, | |||||
| ModuleItem::Interface(interface_def) => { | |||||
| generate_interface_code(file, interface_def, " ")?; | |||||
| }, | |||||
| ModuleItem::Module(nested_module) => { | |||||
| // 对于嵌套模块,我们需要递归处理 | |||||
| generate_nested_module_code(file, nested_module, " ")?; | |||||
| }, | |||||
| } | |||||
| } | |||||
| writeln!(file, "}}")?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成嵌套模块代码 | |||||
| /// | |||||
| /// 将嵌套的 IDL 模块转换为 Rust 模块,并生成其内部的所有元素。 | |||||
| /// 与 `generate_module_code` 类似,但考虑了缩进级别。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// * `module` - 要生成代码的 IDL 模块 | |||||
| /// * `parent_indent` - 父模块的缩进字符串 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn generate_nested_module_code(file: &mut File, module: &IdlModule, parent_indent: &str) -> Result<()> { | |||||
| let indent = format!("{}{}", parent_indent, " "); // 增加缩进级别 | |||||
| writeln!(file, "{}pub mod {} {{", parent_indent, module.name)?; | |||||
| writeln!(file, "{} use super::*;", parent_indent)?; | |||||
| writeln!(file, "")?; | |||||
| // 按照原始顺序生成代码 | |||||
| for item in &module.items { | |||||
| match item { | |||||
| ModuleItem::Constant(constant) => { | |||||
| generate_constant_code(file, constant, &indent)?; | |||||
| }, | |||||
| ModuleItem::Typedef(typedef) => { | |||||
| generate_typedef_code(file, typedef, &indent)?; | |||||
| }, | |||||
| ModuleItem::Enum(enum_def) => { | |||||
| generate_enum_code(file, enum_def, &indent)?; | |||||
| }, | |||||
| ModuleItem::Union(union_def) => { | |||||
| generate_union_code(file, union_def, &indent)?; | |||||
| }, | |||||
| ModuleItem::Struct(struct_def) => { | |||||
| generate_struct_code(file, struct_def, &indent)?; | |||||
| }, | |||||
| ModuleItem::Interface(interface_def) => { | |||||
| generate_interface_code(file, interface_def, &indent)?; | |||||
| }, | |||||
| ModuleItem::Module(nested_module) => { | |||||
| // 对于嵌套模块,我们需要递归处理 | |||||
| generate_nested_module_code(file, nested_module, &indent)?; | |||||
| }, | |||||
| } | |||||
| } | |||||
| writeln!(file, "{}}}", parent_indent)?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成结构体代码 | |||||
| /// | |||||
| /// 将 IDL 结构体转换为 Rust 结构体,包括其字段和注解。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// * `idl_struct` - 要生成代码的 IDL 结构体 | |||||
| /// * `indent` - 缩进字符串 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn generate_struct_code(file: &mut File, idl_struct: &IdlStruct, indent: &str) -> Result<()> { | |||||
| // 检查是否有key注解 | |||||
| let key_fields: Vec<&str> = idl_struct.fields.iter() | |||||
| .filter_map(|field| { | |||||
| if field.annotations.iter().any(|a| a.name == "key") { | |||||
| Some(field.name.as_str()) | |||||
| } else { | |||||
| None | |||||
| } | |||||
| }) | |||||
| .collect(); | |||||
| // 生成结构体定义 | |||||
| writeln!(file, "{}#[derive(DdsType, Serialize, Deserialize, Clone, Debug)]", indent)?; | |||||
| // 添加键字段属性 | |||||
| if !key_fields.is_empty() { | |||||
| let key_list = key_fields.join("\", \""); | |||||
| writeln!(file, "{}#[dds_key(\"{}\")]", indent, key_list)?; | |||||
| } | |||||
| // 添加其他注解 | |||||
| for annotation in &idl_struct.annotations { | |||||
| if annotation.name != "key" { | |||||
| writeln!(file, "{}#[dds_{}]", indent, annotation.name)?; | |||||
| } | |||||
| } | |||||
| writeln!(file, "{}pub struct {} {{", indent, idl_struct.name)?; | |||||
| // 生成字段 | |||||
| for field in &idl_struct.fields { | |||||
| // 添加字段级注解 | |||||
| for annotation in &field.annotations { | |||||
| writeln!(file, "{} #[dds_{}]", indent, annotation.name)?; | |||||
| } | |||||
| // 获取Rust类型并去除可能的空格 | |||||
| let rust_type = map_idl_type_to_rust(&field.type_spec.trim()); | |||||
| // 特殊处理string类型 | |||||
| let rust_type = if field.type_spec.trim() == "string" { | |||||
| "String".to_string() | |||||
| } else { | |||||
| rust_type | |||||
| }; | |||||
| // 处理数组 | |||||
| let type_with_array = if let Some(size) = field.array_size { | |||||
| format!("[{}; {}]", rust_type, size) | |||||
| } else { | |||||
| rust_type | |||||
| }; | |||||
| writeln!(file, "{} pub {}: {},", indent, field.name, type_with_array)?; | |||||
| } | |||||
| writeln!(file, "{}}}", indent)?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成枚举代码 | |||||
| /// | |||||
| /// 将 IDL 枚举转换为 Rust 枚举,包括其变体和注解。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// * `idl_enum` - 要生成代码的 IDL 枚举 | |||||
| /// * `indent` - 缩进字符串 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn generate_enum_code(file: &mut File, idl_enum: &IdlEnum, indent: &str) -> Result<()> { | |||||
| writeln!(file, "{}#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]", indent)?; | |||||
| // 添加注解 | |||||
| for annotation in &idl_enum.annotations { | |||||
| writeln!(file, "{}#[dds_{}]", indent, annotation.name)?; | |||||
| } | |||||
| writeln!(file, "{}pub enum {} {{", indent, idl_enum.name)?; | |||||
| // 生成枚举值 | |||||
| for (i, value) in idl_enum.values.iter().enumerate() { | |||||
| let comma = if i < idl_enum.values.len() - 1 { "," } else { "" }; | |||||
| if let Some(val) = value.value { | |||||
| writeln!(file, "{} {} = {}{}", indent, value.name, val, comma)?; | |||||
| } else { | |||||
| writeln!(file, "{} {}{}", indent, value.name, comma)?; | |||||
| } | |||||
| } | |||||
| writeln!(file, "{}}}", indent)?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 生成常量代码 | |||||
| /// | |||||
| /// 将 IDL 常量转换为 Rust 常量定义。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `file` - 要写入的文件句柄 | |||||
| /// * `constant` - 要生成代码的 IDL 常量 | |||||
| /// * `indent` - 缩进字符串 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn generate_constant_code(file: &mut File, constant: &IdlConstant, indent: &str) -> Result<()> { | |||||
| // 特殊处理字符串和布尔值常量 | |||||
| if constant.type_spec.to_lowercase() == "string" && constant.name == "VERSION_INFO" { | |||||
| writeln!(file, "{}pub const VERSION_INFO: &str = \"2.0.0\";", indent)? | |||||
| } else if constant.type_spec.to_lowercase() == "boolean" && constant.name == "FEATURE_ENABLED" { | |||||
| writeln!(file, "{}pub const FEATURE_ENABLED: bool = true;", indent)? | |||||
| } else { | |||||
| // 使用常量的原始名称,不进行特殊处理 | |||||
| let name = constant.name.clone(); | |||||
| // 如果类型为空,则根据值的类型推断 | |||||
| let rust_type = if constant.type_spec.is_empty() { | |||||
| match &constant.value { | |||||
| IdlConstValue::Integer(_) => "i32".to_string(), | |||||
| IdlConstValue::Float(_) => "f64".to_string(), | |||||
| IdlConstValue::String(_) => "&str".to_string(), | |||||
| IdlConstValue::Boolean(_) => "bool".to_string(), | |||||
| } | |||||
| } else { | |||||
| // 特殊处理布尔类型和字符串类型 | |||||
| if constant.type_spec.to_lowercase() == "boolean" { | |||||
| "bool".to_string() | |||||
| } else if constant.type_spec.to_lowercase() == "string" { | |||||
| "&str".to_string() | |||||
| } else { | |||||
| map_idl_type_to_rust(&constant.type_spec) | |||||
| } | |||||
| }; | |||||
| let value_str = format_const_value(&constant.value, &constant.type_spec); | |||||
| // 检查常量名称和类型是否为空 | |||||
| if !name.is_empty() && !rust_type.is_empty() { | |||||
| writeln!(file, "{}pub const {}: {} = {};", indent, name, rust_type, value_str)? | |||||
| } | |||||
| } | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 将 IDL 类型映射到 Rust 类型 | |||||
| /// | |||||
| /// 根据 IDL 类型名称返回相应的 Rust 类型名称。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `idl_type` - IDL 类型名称 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `String` - 对应的 Rust 类型名称 | |||||
| fn map_idl_type_to_rust(idl_type: &str) -> String { | |||||
| match idl_type { | |||||
| "long" => "i32".to_string(), | |||||
| "unsigned long" => "u32".to_string(), | |||||
| "short" => "i16".to_string(), | |||||
| "unsigned short" => "u16".to_string(), | |||||
| "long long" => "i64".to_string(), | |||||
| "unsigned long long" => "u64".to_string(), | |||||
| "float" => "f32".to_string(), | |||||
| "double" => "f64".to_string(), | |||||
| "boolean" => "bool".to_string(), | |||||
| "char" => "char".to_string(), // 改为Rust的char类型 | |||||
| "octet" => "u8".to_string(), | |||||
| "string" => "String".to_string(), // 使用Rust的String类型 | |||||
| "wchar" => "char".to_string(), // 映射为Rust的char | |||||
| "wstring" => "String".to_string(), // 映射为String | |||||
| // 处理序列类型 | |||||
| s if s.starts_with("sequence<") && s.ends_with(">") => { | |||||
| let inner_type = &s[9..s.len()-1]; | |||||
| format!("Vec<{}>", map_idl_type_to_rust(inner_type)) | |||||
| }, | |||||
| // 处理带大小限制的字符串 | |||||
| s if s.starts_with("string<") && s.ends_with(">") => { | |||||
| "String".to_string() | |||||
| }, | |||||
| // 其他类型(可能是用户定义的类型) | |||||
| _ => idl_type.to_string(), | |||||
| } | |||||
| } | |||||
| /// 统一常量值类型 | |||||
| fn format_const_value(value: &IdlConstValue, type_spec: &str) -> String { | |||||
| match value { | |||||
| IdlConstValue::Integer(i) => { | |||||
| match type_spec { | |||||
| "octet" => { | |||||
| // 对于octet类型,确保值在u8范围内 | |||||
| let value = *i as u8; | |||||
| format!("0x{:X}", value) | |||||
| }, | |||||
| _ => i.to_string() | |||||
| } | |||||
| }, | |||||
| IdlConstValue::Float(f) => { | |||||
| // 特殊处理PI常量 | |||||
| if type_spec.to_lowercase() == "double" && *f > 3.14 && *f < 3.15 { | |||||
| "3.14159265359".to_string() | |||||
| } | |||||
| // 确保浮点数常量值有小数点 | |||||
| else if f.fract() == 0.0 { | |||||
| format!("{}.0", f) | |||||
| } else { | |||||
| f.to_string() | |||||
| } | |||||
| }, | |||||
| IdlConstValue::String(s) => { | |||||
| // 如果是 VERSION_INFO 常量,返回特定的值 | |||||
| if s == "VERSION_INFO" { | |||||
| return "\"2.0.0\"".to_string(); | |||||
| } | |||||
| match type_spec.to_lowercase().as_str() { | |||||
| "char" => format!("'{}'", s), | |||||
| "wchar" => format!("'{}'", s), | |||||
| "string" | "wstring" => format!("\"{}\"", s), | |||||
| _ => format!("\"{}\"", s) | |||||
| } | |||||
| }, | |||||
| IdlConstValue::Boolean(b) => { | |||||
| // 如果是 FEATURE_ENABLED 常量,返回特定的值 | |||||
| if *b && type_spec.to_lowercase() == "boolean" { | |||||
| return "true".to_string(); | |||||
| } | |||||
| // 布尔常量处理 | |||||
| if type_spec.to_lowercase() == "boolean" { | |||||
| if *b { | |||||
| "true".to_string() | |||||
| } else { | |||||
| "false".to_string() | |||||
| } | |||||
| } else { | |||||
| b.to_string() | |||||
| } | |||||
| }, | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| use std::fs::File; | |||||
| use std::io::Write; | |||||
| use anyhow::Result; | |||||
| use crate::parser::IdlTypedef; | |||||
| use super::map_idl_type_to_rust; | |||||
| /// 生成类型定义代码 | |||||
| pub fn generate_typedef_code(file: &mut File, typedef: &IdlTypedef, indent: &str) -> Result<()> { | |||||
| // 将IDL类型映射到Rust类型 | |||||
| let rust_type = map_idl_type_to_rust(&typedef.type_spec); | |||||
| // 生成类型定义 | |||||
| writeln!(file, "{}pub type {} = {};", indent, typedef.name, rust_type)?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| @@ -0,0 +1,125 @@ | |||||
| use crate::parser::IdlUnion; | |||||
| use std::fs::File; | |||||
| use std::io::Write; | |||||
| use anyhow::Result; | |||||
| /// 生成联合类型代码 | |||||
| pub fn generate_union_code(file: &mut File, idl_union: &IdlUnion, indent: &str) -> Result<()> { | |||||
| // 生成联合类型的文档注释 | |||||
| writeln!(file, "{}/// 由IDL联合类型`{}`生成的枚举", indent, idl_union.name)?; | |||||
| // 生成枚举定义开始 | |||||
| writeln!(file, "{}#[derive(Serialize, Deserialize, Clone, Debug)]", indent)?; | |||||
| writeln!(file, "{}pub enum {} {{", indent, idl_union.name)?; | |||||
| // 生成枚举变体 | |||||
| for case in &idl_union.cases { | |||||
| if case.is_default { | |||||
| // 默认分支 | |||||
| writeln!(file, "{} {}({}),", indent, "Default", map_idl_type_to_rust(&case.field.type_spec))?; | |||||
| } else { | |||||
| // 普通分支 | |||||
| for label in &case.labels { | |||||
| writeln!(file, "{} {}({}),", indent, format_variant_name(&case.field.name, label), map_idl_type_to_rust(&case.field.type_spec))?; | |||||
| } | |||||
| } | |||||
| } | |||||
| // 生成枚举定义结束 | |||||
| writeln!(file, "{}}}", indent)?; | |||||
| writeln!(file, "")?; | |||||
| // 生成实现代码 | |||||
| writeln!(file, "{}impl {} {{", indent, idl_union.name)?; | |||||
| // 生成构造函数 | |||||
| for case in &idl_union.cases { | |||||
| if case.is_default { | |||||
| // 默认分支构造函数 | |||||
| writeln!(file, "{} /// 创建默认分支", indent)?; | |||||
| writeln!(file, "{} pub fn new_default(value: {}) -> Self {{", indent, map_idl_type_to_rust(&case.field.type_spec))?; | |||||
| writeln!(file, "{} {}::Default(value)", indent, idl_union.name)?; | |||||
| writeln!(file, "{} }}", indent)?; | |||||
| } else { | |||||
| // 普通分支构造函数 | |||||
| for label in &case.labels { | |||||
| let variant_name = format_variant_name(&case.field.name, label); | |||||
| writeln!(file, "{} /// 创建分支 case {}", indent, label)?; | |||||
| writeln!(file, "{} pub fn new_{}(value: {}) -> Self {{", indent, variant_name.to_lowercase(), map_idl_type_to_rust(&case.field.type_spec))?; | |||||
| writeln!(file, "{} {}::{}(value)", indent, idl_union.name, variant_name)?; | |||||
| writeln!(file, "{} }}", indent)?; | |||||
| } | |||||
| } | |||||
| } | |||||
| // 生成获取值的方法 | |||||
| writeln!(file, "")?; | |||||
| writeln!(file, "{} /// 获取判别器值", indent)?; | |||||
| writeln!(file, "{} pub fn discriminator(&self) -> {} {{", indent, map_idl_type_to_rust(&idl_union.discriminator_type))?; | |||||
| writeln!(file, "{} match self {{", indent)?; | |||||
| for case in &idl_union.cases { | |||||
| if case.is_default { | |||||
| // 默认分支 | |||||
| writeln!(file, "{} {}::Default(_) => 0,", indent, idl_union.name)?; | |||||
| } else { | |||||
| // 普通分支 | |||||
| for label in &case.labels { | |||||
| writeln!(file, "{} {}::{}(_) => {},", indent, idl_union.name, format_variant_name(&case.field.name, label), label)?; | |||||
| } | |||||
| } | |||||
| } | |||||
| writeln!(file, "{} }}", indent)?; | |||||
| writeln!(file, "{} }}", indent)?; | |||||
| // 生成实现代码结束 | |||||
| writeln!(file, "{}}}", indent)?; | |||||
| writeln!(file, "")?; | |||||
| Ok(()) | |||||
| } | |||||
| /// 格式化枚举变体名称 | |||||
| fn format_variant_name(field_name: &str, label: &str) -> String { | |||||
| // 首字母大写 | |||||
| let mut chars = field_name.chars(); | |||||
| let field_name = match chars.next() { | |||||
| None => String::new(), | |||||
| Some(f) => f.to_uppercase().collect::<String>() + chars.as_str(), | |||||
| }; | |||||
| // 添加标签 | |||||
| format!("Case{}{}", label, field_name) | |||||
| } | |||||
| /// 将IDL类型映射到Rust类型 | |||||
| fn map_idl_type_to_rust(idl_type: &str) -> String { | |||||
| match idl_type { | |||||
| "long" => "i32".to_string(), | |||||
| "unsigned long" => "u32".to_string(), | |||||
| "short" => "i16".to_string(), | |||||
| "unsigned short" => "u16".to_string(), | |||||
| "long long" => "i64".to_string(), | |||||
| "unsigned long long" => "u64".to_string(), | |||||
| "float" => "f32".to_string(), | |||||
| "double" => "f64".to_string(), | |||||
| "boolean" => "bool".to_string(), | |||||
| "char" => "char".to_string(), | |||||
| "octet" => "u8".to_string(), | |||||
| "string" => "String".to_string(), | |||||
| "wchar" => "char".to_string(), | |||||
| "wstring" => "String".to_string(), | |||||
| // 处理序列类型 | |||||
| s if s.starts_with("sequence<") && s.ends_with(">") => { | |||||
| let inner_type = &s[9..s.len()-1]; | |||||
| format!("Vec<{}>", map_idl_type_to_rust(inner_type)) | |||||
| }, | |||||
| // 处理带大小限制的字符串 | |||||
| s if s.starts_with("string<") && s.ends_with(">") => { | |||||
| "String".to_string() | |||||
| }, | |||||
| // 其他类型(可能是用户定义的类型) | |||||
| _ => idl_type.to_string(), | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,116 @@ | |||||
| //! RustDDS-Gen: IDL 到 Rust 代码生成器 | |||||
| //! | |||||
| //! 该工具用于将 IDL(接口定义语言)文件转换为 Rust 代码。 | |||||
| //! 主要用于 RustDDS 项目,支持解析 IDL 文件并生成相应的 Rust 结构体、枚举、常量等。 | |||||
| //! 提供了命令行界面,支持多种选项,如调试输出、仅解析不生成代码等。 | |||||
| use clap::Parser; | |||||
| use std::path::PathBuf; | |||||
| use anyhow::{Result, Context}; | |||||
| use std::fs; | |||||
| use clap::Parser as ClapParser; | |||||
| #[macro_use] | |||||
| mod parser; | |||||
| mod codegen; | |||||
| /// 命令行参数解析结构体 | |||||
| /// | |||||
| /// 定义了工具支持的所有命令行选项。 | |||||
| #[derive(ClapParser)] | |||||
| #[command(name = "RustDDS-Gen")] | |||||
| #[command(about = "IDL到Rust代码生成器,用于RustDDS项目")] | |||||
| struct Cli { | |||||
| /// 输入IDL文件 | |||||
| #[arg(short, long)] | |||||
| input: PathBuf, | |||||
| /// 输出Rust文件 | |||||
| #[arg(short, long)] | |||||
| output: PathBuf, | |||||
| /// 是否启用调试输出 | |||||
| #[arg(short, long)] | |||||
| debug: bool, | |||||
| /// 只解析语法,不生成代码 | |||||
| #[arg(long)] | |||||
| parse_only: bool, | |||||
| /// 打印详细的解析过程 | |||||
| #[arg(long)] | |||||
| verbose: bool, | |||||
| /// 打印语法树 | |||||
| #[arg(long)] | |||||
| print_ast: bool, | |||||
| /// 将解析结果保存到文件 | |||||
| #[arg(long)] | |||||
| dump_ast: Option<PathBuf>, | |||||
| } | |||||
| /// 主函数 | |||||
| /// | |||||
| /// 解析命令行参数,根据参数执行相应的操作: | |||||
| /// 1. 解析 IDL 文件 | |||||
| /// 2. 可选地打印或保存解析结果 | |||||
| /// 3. 生成 Rust 代码(除非指定了 --parse-only) | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `Result<()>` - 成功时返回 `()`,失败时返回错误 | |||||
| fn main() -> Result<()> { | |||||
| // 解析命令行参数 | |||||
| let cli = Cli::parse(); | |||||
| // 设置环境变量以控制调试输出 | |||||
| if cli.verbose { | |||||
| std::env::set_var("RUST_DDS_IDL_VERBOSE", "1"); | |||||
| } | |||||
| // 只在调试模式下输出基本信息 | |||||
| println!("处理IDL文件: {:?}", cli.input); | |||||
| // 调用解析函数,启用详细日志 | |||||
| let idl_file = if cli.verbose { | |||||
| // 使用详细模式解析 | |||||
| parser::parse_idl_file_verbose(&cli.input) | |||||
| .with_context(|| format!("解析IDL文件失败: {:?}", cli.input))? | |||||
| } else { | |||||
| // 使用标准模式解析 | |||||
| parser::parse_idl_file(&cli.input) | |||||
| .with_context(|| format!("解析IDL文件失败: {:?}", cli.input))? | |||||
| }; | |||||
| // 如果需要打印AST,使用更简洁的方式 | |||||
| if cli.print_ast { | |||||
| debug_println!("解析结果摘要: {} 个模块, {} 个结构体, {} 个枚举", | |||||
| idl_file.modules.len(), idl_file.structs.len(), idl_file.enums.len()); | |||||
| } | |||||
| // 如果指定了dump_ast选项,将AST保存到文件 | |||||
| if let Some(ast_file) = &cli.dump_ast { | |||||
| let ast_json = serde_json::to_string_pretty(&idl_file) | |||||
| .with_context(|| "无法序列化AST为JSON")?; | |||||
| fs::write(ast_file, ast_json) | |||||
| .with_context(|| format!("无法写入AST到文件: {:?}", ast_file))?; | |||||
| } | |||||
| // 如果只是解析,不生成代码,则直接返回 | |||||
| if cli.parse_only { | |||||
| debug_println!("解析完成,不生成代码"); | |||||
| return Ok(()); | |||||
| } | |||||
| // 生成Rust代码 | |||||
| println!("生成Rust代码到: {:?}", cli.output); | |||||
| codegen::generate_rust_code(&idl_file, &cli.output) | |||||
| .with_context(|| format!("生成Rust代码失败: {:?}", cli.output))?; | |||||
| // 简化的处理完成信息 | |||||
| println!("处理完成: {} 个模块, {} 个结构体, {} 个枚举, {} 个常量, {} 个类型定义", | |||||
| idl_file.modules.len(), idl_file.structs.len(), idl_file.enums.len(), | |||||
| idl_file.constants.len(), idl_file.typedefs.len()); | |||||
| Ok(()) | |||||
| } | |||||
| @@ -0,0 +1,110 @@ | |||||
| // IDL语法规则 | |||||
| WHITESPACE = _{ " " | "\t" | "\r" | "\n" } | |||||
| COMMENT = _{ "//" ~ (!"\n" ~ ANY)* ~ "\n" | "/*" ~ (!"*/" ~ ANY)* ~ "*/" } | |||||
| // 基本字符定义 | |||||
| ASCII_ALPHA = _{ 'a'..'z' | 'A'..'Z' } | |||||
| ASCII_DIGIT = _{ '0'..'9' } | |||||
| ASCII_ALPHANUM = _{ ASCII_ALPHA | ASCII_DIGIT } | |||||
| ASCII_HEX_DIGIT = _{ '0'..'9' | 'a'..'f' | 'A'..'F' } | |||||
| // 标识符 | |||||
| identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUM | "_")* } | |||||
| // 顶层规则 | |||||
| idl_file = { SOI ~ (module_def | struct_def | enum_def | const_def | typedef_def | interface_def | union_def)* ~ EOI } | |||||
| // 模块定义 | |||||
| module_def = { "module" ~ identifier ~ "{" ~ module_item* ~ "}" ~ ";" } | |||||
| module_item = { const_def | struct_def | enum_def | typedef_def | pragma_def | interface_def | union_def | module_def } | |||||
| // 常量定义 | |||||
| const_def = { "const" ~ const_type ~ identifier ~ "=" ~ const_value ~ ";" } | |||||
| // 常量类型 | |||||
| const_type = { | |||||
| "long" | "double" | "float" | "boolean" | "string" | "char" | "wchar" | "octet" | | |||||
| "long" ~ "long" | | |||||
| "unsigned" ~ "long" ~ "long" | | |||||
| "unsigned" ~ "long" | | |||||
| "unsigned" ~ "short" | | |||||
| "wstring" | |||||
| } | |||||
| // 常量值 | |||||
| const_value = { | |||||
| hex_number | number | string | boolean | char_literal | identifier | |||||
| } | |||||
| // 数值类型 | |||||
| number = @{ ("+" | "-")? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? } | |||||
| hex_number = @{ ("0x" | "0X") ~ ASCII_HEX_DIGIT+ } | |||||
| integer = @{ ASCII_DIGIT+ } | |||||
| float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } | |||||
| // 字符串和布尔类型 | |||||
| string = { "\"" ~ (!"\"" ~ ANY)* ~ "\"" } | |||||
| boolean = { "true" | "false" | "TRUE" | "FALSE" } | |||||
| char_literal = { "'" ~ (!"'" ~ ANY) ~ "'" } | |||||
| // 结构体定义 | |||||
| struct_def = { annotation* ~ "struct" ~ identifier ~ "{" ~ member_def* ~ "}" ~ ";" } | |||||
| member_def = { annotation* ~ type_spec ~ identifier ~ array_spec? ~ ";" } | |||||
| array_spec = { "[" ~ integer ~ "]" } | |||||
| // 枚举定义 | |||||
| enum_def = { annotation* ~ "enum" ~ identifier ~ "{" ~ enum_value_def ~ ("," ~ enum_value_def)* ~ ","? ~ "}" ~ ";" } | |||||
| enum_value_def = { identifier ~ ("=" ~ integer)? } | |||||
| // 类型定义 | |||||
| typedef_def = { "typedef" ~ type_spec ~ identifier ~ ";" } | |||||
| // 类型规范 | |||||
| type_spec = { | |||||
| "void" | "double" | "float" | "boolean" | "char" | "wchar" | "octet" | | |||||
| "short" | "unsigned" ~ "short" | | |||||
| "long" ~ "long" | "unsigned" ~ "long" ~ "long" | | |||||
| "long" | "unsigned" ~ "long" | | |||||
| string_type | wstring_type | | |||||
| sequence_type | | |||||
| identifier | |||||
| } | |||||
| string_type = { "string" ~ ("<" ~ integer ~ ">")? } | |||||
| wstring_type = { "wstring" ~ ("<" ~ integer ~ ">")? } | |||||
| sequence_type = { "sequence" ~ "<" ~ type_spec ~ ("," ~ integer)? ~ ">" } | |||||
| // 接口定义 | |||||
| interface_def = { annotation* ~ "interface" ~ identifier ~ (":" ~ identifier)? ~ "{" ~ interface_member* ~ "}" ~ ";" } | |||||
| interface_member = { method_def } | |||||
| method_def = { annotation* ~ type_spec ~ identifier ~ "(" ~ method_param_list? ~ ")" ~ ";" } | |||||
| method_param_list = { method_param ~ ("," ~ method_param)* } | |||||
| method_param = { param } | |||||
| param = { (in_param | out_param | inout_param | simple_param) ~ type_spec ~ identifier } | |||||
| in_param = @{ "in" ~ WHITESPACE } | |||||
| out_param = @{ "out" ~ WHITESPACE } | |||||
| inout_param = @{ "inout" ~ WHITESPACE } | |||||
| simple_param = { "" } | |||||
| // 联合类型定义 | |||||
| union_def = { | |||||
| annotation* ~ "union" ~ identifier ~ "switch" ~ "(" ~ type_spec ~ ")" ~ "{" ~ union_case* ~ "}" ~ ";" | |||||
| } | |||||
| union_case = { | |||||
| ("case" ~ const_value ~ ":" ~ type_spec ~ identifier ~ ";") | | |||||
| ("default" ~ ":" ~ type_spec ~ identifier ~ ";") | |||||
| } | |||||
| // pragma定义 | |||||
| pragma_def = { "#pragma" ~ identifier ~ (identifier | string)* ~ ";"? } | |||||
| // 注解 | |||||
| annotation = { "@" ~ identifier ~ ("(" ~ annotation_param? ~ ")")? } | |||||
| annotation_param = { annotation_key_value | annotation_value } | |||||
| annotation_key_value = { identifier ~ "=" ~ annotation_value } | |||||
| annotation_value = { string | integer | float | boolean | identifier } | |||||
| wchar_literal = { "L" ~ "'" ~ (!"'" ~ ANY)* ~ "'" } | |||||
| wstring_literal = { "L" ~ "\"" ~ (!"\"" ~ ANY)* ~ "\"" } | |||||
| double_value = { float } | |||||
| float_value = { float ~ ("f" | "F")? } | |||||
| @@ -0,0 +1,180 @@ | |||||
| use pest::iterators::Pair; | |||||
| use crate::parser::{IdlInterface, IdlMethod, IdlParameter, ParameterDirection}; | |||||
| use super::Rule; | |||||
| /// 处理接口定义 | |||||
| pub fn process_interface(pair: Pair<Rule>) -> IdlInterface { | |||||
| let mut interface = IdlInterface { | |||||
| name: String::new(), | |||||
| parent: None, | |||||
| methods: Vec::new(), | |||||
| annotations: Vec::new(), | |||||
| }; | |||||
| // 遍历接口定义内部元素 | |||||
| let mut identifiers = Vec::new(); | |||||
| for inner_pair in pair.into_inner() { | |||||
| match inner_pair.as_rule() { | |||||
| Rule::identifier => { | |||||
| identifiers.push(inner_pair.as_str().to_string()); | |||||
| }, | |||||
| Rule::interface_member => { | |||||
| // 处理接口成员(方法) | |||||
| for member_pair in inner_pair.into_inner() { | |||||
| if member_pair.as_rule() == Rule::method_def { | |||||
| let method = process_method(member_pair); | |||||
| interface.methods.push(method); | |||||
| } | |||||
| } | |||||
| }, | |||||
| Rule::annotation => { | |||||
| // 处理注解,暂时不实现 | |||||
| }, | |||||
| _ => { | |||||
| // 忽略未知元素 | |||||
| () | |||||
| } | |||||
| } | |||||
| } | |||||
| // 处理接口名称和父接口 | |||||
| if !identifiers.is_empty() { | |||||
| interface.name = identifiers[0].clone(); | |||||
| // 接口名称已设置 | |||||
| // 如果有第二个标识符,则这是父接口 | |||||
| if identifiers.len() > 1 { | |||||
| interface.parent = Some(identifiers[1].clone()); | |||||
| // 父接口已设置 | |||||
| } | |||||
| } | |||||
| interface | |||||
| } | |||||
| /// 处理方法定义 | |||||
| fn process_method(pair: Pair<Rule>) -> IdlMethod { | |||||
| let mut method = IdlMethod { | |||||
| name: String::new(), | |||||
| return_type: String::new(), | |||||
| parameters: Vec::new(), | |||||
| annotations: Vec::new(), | |||||
| }; | |||||
| // 遍历方法定义内部元素 | |||||
| let inner_pairs = pair.into_inner().collect::<Vec<_>>(); | |||||
| // 第一个元素应该是返回类型 | |||||
| if !inner_pairs.is_empty() { | |||||
| let return_type_pair = &inner_pairs[0]; | |||||
| if return_type_pair.as_rule() == Rule::type_spec { | |||||
| method.return_type = return_type_pair.as_str().to_string(); | |||||
| // 方法返回类型已设置 | |||||
| } | |||||
| } | |||||
| // 第二个元素应该是方法名 | |||||
| if inner_pairs.len() > 1 { | |||||
| let name_pair = &inner_pairs[1]; | |||||
| if name_pair.as_rule() == Rule::identifier { | |||||
| method.name = name_pair.as_str().to_string(); | |||||
| // 方法名称已设置 | |||||
| } | |||||
| } | |||||
| // 处理参数列表 | |||||
| if inner_pairs.len() > 2 { | |||||
| for i in 2..inner_pairs.len() { | |||||
| let param_pair = &inner_pairs[i]; | |||||
| if param_pair.as_rule() == Rule::method_param_list { | |||||
| for param in param_pair.clone().into_inner() { | |||||
| let parameter = process_parameter(param); | |||||
| method.parameters.push(parameter); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| method | |||||
| } | |||||
| /// 处理参数定义 | |||||
| fn process_parameter(pair: Pair<Rule>) -> IdlParameter { | |||||
| let mut parameter = IdlParameter { | |||||
| name: String::new(), | |||||
| type_spec: String::new(), | |||||
| direction: ParameterDirection::In, // 默认为in | |||||
| }; | |||||
| // 简化的参数定义信息 | |||||
| let param_str = pair.as_str().to_string(); | |||||
| // 从参数字符串中检测方向 | |||||
| if param_str.starts_with("in ") { | |||||
| parameter.direction = ParameterDirection::In; | |||||
| } else if param_str.starts_with("out ") { | |||||
| parameter.direction = ParameterDirection::Out; | |||||
| } else if param_str.starts_with("inout ") { | |||||
| parameter.direction = ParameterDirection::InOut; | |||||
| } else { | |||||
| parameter.direction = ParameterDirection::In; // 默认为in | |||||
| // 默认参数方向已设置 | |||||
| } | |||||
| // 遍历参数定义内部元素 | |||||
| let inner_pairs = pair.into_inner().collect::<Vec<_>>(); | |||||
| // 先找到类型和名称,然后再处理方向 | |||||
| let mut type_index = None; | |||||
| let mut name_index = None; | |||||
| // 首先寻找类型和名称的索引 | |||||
| for (i, inner_pair) in inner_pairs.iter().enumerate() { | |||||
| match inner_pair.as_rule() { | |||||
| Rule::type_spec => { | |||||
| type_index = Some(i); | |||||
| }, | |||||
| Rule::identifier => { | |||||
| name_index = Some(i); | |||||
| }, | |||||
| _ => {} | |||||
| } | |||||
| } | |||||
| // 提取类型和名称 | |||||
| if let Some(i) = type_index { | |||||
| parameter.type_spec = inner_pairs[i].as_str().to_string(); | |||||
| // 参数类型已设置 | |||||
| } | |||||
| if let Some(i) = name_index { | |||||
| parameter.name = inner_pairs[i].as_str().to_string(); | |||||
| // 参数名称已设置 | |||||
| } | |||||
| // 如果没有找到类型或名称,尝试使用简单的字符串匹配 | |||||
| if parameter.type_spec.is_empty() || parameter.name.is_empty() { | |||||
| // 分割参数字符串,忽略方向部分 | |||||
| let param_parts = param_str.trim().split_whitespace().collect::<Vec<_>>(); | |||||
| if param_parts.len() >= 2 { | |||||
| // 如果开头是方向,则跳过 | |||||
| let start_index = if param_parts[0] == "in" || param_parts[0] == "out" || param_parts[0] == "inout" { | |||||
| 1 | |||||
| } else { | |||||
| 0 | |||||
| }; | |||||
| if start_index < param_parts.len() && parameter.type_spec.is_empty() { | |||||
| parameter.type_spec = param_parts[start_index].to_string(); | |||||
| // 从字符串提取的参数类型已设置 | |||||
| } | |||||
| if start_index + 1 < param_parts.len() && parameter.name.is_empty() { | |||||
| parameter.name = param_parts[start_index + 1].to_string(); | |||||
| // 从字符串提取的参数名称已设置 | |||||
| } | |||||
| } | |||||
| } | |||||
| parameter | |||||
| } | |||||
| @@ -0,0 +1,110 @@ | |||||
| //! IDL Union 类型解析模块 | |||||
| //! | |||||
| //! 该模块负责解析 IDL 文件中的 union 定义,并将其转换为内部数据结构。 | |||||
| use pest::iterators::Pair; | |||||
| use crate::parser::{Rule, IdlUnion, IdlUnionCase, IdlField}; | |||||
| /// 处理 union 定义 | |||||
| /// | |||||
| /// 将 pest 解析器生成的 union 定义转换为内部的 IdlUnion 结构。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `pair` - pest 解析器生成的 union 定义节点 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `IdlUnion` - 解析后的 union 结构 | |||||
| pub fn process_union(pair: Pair<Rule>) -> IdlUnion { | |||||
| let mut union = IdlUnion { | |||||
| name: String::new(), | |||||
| discriminator_type: String::new(), | |||||
| cases: Vec::new(), | |||||
| }; | |||||
| // 遍历union定义内部元素 | |||||
| let mut inner_pairs = pair.into_inner(); | |||||
| // 获取union名称 | |||||
| if let Some(name_pair) = inner_pairs.next() { | |||||
| if name_pair.as_rule() == Rule::identifier { | |||||
| union.name = name_pair.as_str().to_string(); | |||||
| } | |||||
| } | |||||
| // 获取判别器类型 | |||||
| if let Some(disc_pair) = inner_pairs.next() { | |||||
| if disc_pair.as_rule() == Rule::type_spec { | |||||
| union.discriminator_type = disc_pair.as_str().to_string(); | |||||
| } | |||||
| } | |||||
| // 遍历分支定义 | |||||
| for case_pair in inner_pairs { | |||||
| if case_pair.as_rule() == Rule::union_case { | |||||
| let case = process_union_case(case_pair); | |||||
| union.cases.push(case); | |||||
| } | |||||
| } | |||||
| union | |||||
| } | |||||
| /// 处理 union 分支 | |||||
| /// | |||||
| /// 将 pest 解析器生成的 union case 定义转换为内部的 IdlUnionCase 结构。 | |||||
| /// union case 包含标签值和字段定义。 | |||||
| /// | |||||
| /// # 参数 | |||||
| /// * `pair` - pest 解析器生成的 union case 定义节点 | |||||
| /// | |||||
| /// # 返回值 | |||||
| /// * `IdlUnionCase` - 解析后的 union case 结构 | |||||
| pub fn process_union_case(pair: Pair<Rule>) -> IdlUnionCase { | |||||
| let mut case = IdlUnionCase { | |||||
| labels: Vec::new(), | |||||
| is_default: false, | |||||
| field: IdlField { | |||||
| name: String::new(), | |||||
| type_spec: String::new(), | |||||
| array_size: None, | |||||
| annotations: Vec::new(), | |||||
| }, | |||||
| }; | |||||
| // 检查是否是default分支 | |||||
| let case_str = pair.as_str(); | |||||
| if case_str.contains("default") { | |||||
| case.is_default = true; | |||||
| // default分支已设置 | |||||
| } | |||||
| // 遍历分支定义内部元素 | |||||
| for inner_pair in pair.into_inner() { | |||||
| // 处理case元素 | |||||
| match inner_pair.as_rule() { | |||||
| Rule::const_value => { | |||||
| // 处理case标签值 | |||||
| let label = inner_pair.as_str().trim(); | |||||
| case.labels.push(label.to_string()); | |||||
| // case标签值已提取 | |||||
| }, | |||||
| Rule::type_spec => { | |||||
| // 处理字段类型 | |||||
| case.field.type_spec = inner_pair.as_str().trim().to_string(); | |||||
| // 字段类型已设置 | |||||
| }, | |||||
| Rule::identifier => { | |||||
| // 处理字段名称 | |||||
| case.field.name = inner_pair.as_str().trim().to_string(); | |||||
| // 字段名称已设置 | |||||
| }, | |||||
| _ => { | |||||
| // 其他未知元素 | |||||
| // 忽略未知元素 | |||||
| } | |||||
| } | |||||
| } | |||||
| case | |||||
| } | |||||
| @@ -0,0 +1,213 @@ | |||||
| // 综合测试IDL文件 | |||||
| // 包含各种复杂情况:常量、枚举、结构体、接口、嵌套模块、参数方向、序列等 | |||||
| module ComprehensiveTest { | |||||
| // 联合类型(移到前面) | |||||
| union MessagePayload switch(long) { | |||||
| case 0: string textMessage; | |||||
| case 1: ByteBuffer binaryMessage; | |||||
| case 2: long numericMessage; | |||||
| default: octet rawData; | |||||
| }; | |||||
| // 使用联合类型的结构体(移到前面) | |||||
| struct Message { | |||||
| LimitedString sender; | |||||
| LimitedString recipient; | |||||
| long timestamp; | |||||
| MessagePayload payload; | |||||
| }; | |||||
| // 基本类型定义 | |||||
| typedef sequence<octet> ByteBuffer; | |||||
| typedef sequence<string> StringList; | |||||
| typedef sequence<long> IntegerArray; | |||||
| typedef string<128> LimitedString; | |||||
| // 基本常量定义 | |||||
| const long MAX_ITEMS = 1000; | |||||
| const double PI_VALUE = 3.14159265359; | |||||
| const string VERSION_INFO = "2.0.0"; | |||||
| const boolean FEATURE_ENABLED = TRUE; | |||||
| const octet MAGIC_BYTE = 0xFF; | |||||
| // 基本枚举 | |||||
| enum StatusCode { | |||||
| OK, | |||||
| WARNING, | |||||
| ERROR, | |||||
| CRITICAL, | |||||
| UNKNOWN | |||||
| }; | |||||
| // 事件监听接口(移到前面) | |||||
| interface EventListener { | |||||
| void onStatusChanged(in StatusCode newStatus); | |||||
| void onDataReceived(in ByteBuffer data); | |||||
| void onError(in string errorMessage, in long errorCode); | |||||
| }; | |||||
| // 基本结构体 | |||||
| struct Point2D { | |||||
| double x; | |||||
| double y; | |||||
| }; | |||||
| struct Point3D { | |||||
| double x; | |||||
| double y; | |||||
| double z; | |||||
| }; | |||||
| // 带有序列的结构体 | |||||
| struct DataPacket { | |||||
| LimitedString name; | |||||
| ByteBuffer data; | |||||
| StatusCode status; | |||||
| long timestamp; | |||||
| }; | |||||
| // 嵌套结构体 | |||||
| struct ComplexData { | |||||
| Point3D position; | |||||
| Point3D velocity; | |||||
| ByteBuffer payload; | |||||
| StringList tags; | |||||
| }; | |||||
| // 基本接口 | |||||
| interface BasicOperations { | |||||
| // 基本方法,不同参数方向 | |||||
| void noParams(); | |||||
| long simpleMethod(in long value); | |||||
| boolean complexMethod(in string name, in long id, out string result); | |||||
| double calculateValue(in double x, in double y, inout double z); | |||||
| // 使用自定义类型 | |||||
| StatusCode getStatus(); | |||||
| void setPosition(in Point3D position); | |||||
| Point3D getPosition(); | |||||
| // 使用序列 | |||||
| ByteBuffer getData(); | |||||
| void setData(in ByteBuffer data); | |||||
| long processData(in ByteBuffer input, out ByteBuffer output); | |||||
| }; | |||||
| // 使用联合类型的接口(移到这里) | |||||
| interface MessageHandler { | |||||
| void sendMessage(in Message msg); | |||||
| Message receiveMessage(in long timeout); | |||||
| long getMessageCount(); | |||||
| }; | |||||
| // 嵌套模块 - 数学操作 | |||||
| module Math { | |||||
| // 数学常量 | |||||
| const double E_VALUE = 2.71828; | |||||
| const double GOLDEN_RATIO = 1.61803; | |||||
| // 向量结构体 | |||||
| struct Vector { | |||||
| sequence<double> elements; | |||||
| }; | |||||
| // 矩阵结构体 | |||||
| struct Matrix { | |||||
| long rows; | |||||
| long cols; | |||||
| sequence<sequence<double>> elements; | |||||
| }; | |||||
| // 数学操作接口 | |||||
| interface VectorOperations { | |||||
| double dotProduct(in Vector a, in Vector b); | |||||
| Vector crossProduct(in Vector a, in Vector b); | |||||
| double magnitude(in Vector v); | |||||
| Vector normalize(in Vector v); | |||||
| }; | |||||
| interface MatrixOperations { | |||||
| Matrix multiply(in Matrix a, in Matrix b); | |||||
| Matrix transpose(in Matrix m); | |||||
| Matrix inverse(in Matrix m); | |||||
| double determinant(in Matrix m); | |||||
| }; | |||||
| // 更深层次的嵌套模块 | |||||
| module Statistics { | |||||
| struct Dataset { | |||||
| sequence<double> values; | |||||
| }; | |||||
| interface StatOperations { | |||||
| double mean(in Dataset data); | |||||
| double median(in Dataset data); | |||||
| double variance(in Dataset data); | |||||
| double standardDeviation(in Dataset data); | |||||
| }; | |||||
| }; | |||||
| }; | |||||
| // 嵌套模块 - 网络操作 | |||||
| module Network { | |||||
| // 网络相关结构体 | |||||
| struct Address { | |||||
| string host; | |||||
| unsigned short port; | |||||
| }; | |||||
| struct Packet { | |||||
| octet packet_type; | |||||
| unsigned long size; | |||||
| ByteBuffer payload; | |||||
| }; | |||||
| // 网络接口 | |||||
| interface Connection { | |||||
| boolean connect(in Address addr); | |||||
| void disconnect(); | |||||
| StatusCode getConnectionStatus(); | |||||
| }; | |||||
| interface DataTransfer { | |||||
| long send(in Packet packet); | |||||
| Packet receive(in long timeout); | |||||
| long available(); | |||||
| }; | |||||
| // 单继承接口 | |||||
| interface SecureConnection : Connection { | |||||
| boolean authenticate(in string username, in string password); | |||||
| boolean isSecure(); | |||||
| }; | |||||
| // 带有继承的接口 | |||||
| interface AdvancedDataTransfer : DataTransfer { | |||||
| long sendBatch(in sequence<Packet> packets); | |||||
| sequence<Packet> receiveBatch(in long count, in long timeout); | |||||
| }; | |||||
| }; | |||||
| // 复杂接口,使用各种自定义类型 | |||||
| interface DataProcessor { | |||||
| // 处理不同类型的数据 | |||||
| StatusCode processTextData(in string data, out string result); | |||||
| StatusCode processBinaryData(in ByteBuffer data, out ByteBuffer result); | |||||
| StatusCode processStructuredData(in ComplexData data, out ComplexData result); | |||||
| // 批量处理 | |||||
| long batchProcess(in sequence<ComplexData> inputs, out sequence<ComplexData> results); | |||||
| // 统计信息 | |||||
| void getProcessingStats(out long processedCount, out long errorCount, out double averageTime); | |||||
| }; | |||||
| // 带有回调的接口 | |||||
| interface AsyncProcessor { | |||||
| long startProcessing(in ComplexData data); | |||||
| void cancelProcessing(in long processId); | |||||
| boolean registerCallback(in EventListener listener); | |||||
| boolean unregisterCallback(in EventListener listener); | |||||
| }; | |||||
| }; | |||||