From f831b739a4722e4ae10ea7e183036df9e7adadc7 Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Wed, 18 Oct 2023 15:01:35 -0300 Subject: [PATCH 01/11] Generically using IR instead of symbols --- Cargo.toml | 2 - ecosystem/python/parser/src/identifier.rs | 2 +- .../python/parser/src/symbols/interface.rs | 4 +- ecosystem/python/parser/src/symbols/module.rs | 6 +-- ecosystem/python/parser/src/symbols/scope.rs | 31 +++++++------ .../parser/src/symbols/scope/scope_type.rs | 11 +++-- ligen/Cargo.toml | 1 - ligen/ir/src/interface.rs | 11 ++++- ligen/ir/src/module/mod.rs | 32 +++++++++++++ ligen/ir/src/types/type_definition/mod.rs | 10 +++++ ligen/src/lib.rs | 1 - ligen/symbols/Cargo.toml | 9 ---- ligen/symbols/src/identifier.rs | 1 - ligen/symbols/src/interface.rs | 17 ------- ligen/symbols/src/lib.rs | 7 --- ligen/symbols/src/module.rs | 45 ------------------- tools/editor/Cargo.toml | 1 - .../gui/ui/layout/editor/symbols/interface.rs | 8 ++-- .../src/gui/ui/layout/editor/symbols/mod.rs | 4 +- .../gui/ui/layout/editor/symbols/module.rs | 8 ++-- .../gui/ui/layout/editor/symbols/project.rs | 2 +- 21 files changed, 89 insertions(+), 124 deletions(-) delete mode 100644 ligen/symbols/Cargo.toml delete mode 100644 ligen/symbols/src/identifier.rs delete mode 100644 ligen/symbols/src/interface.rs delete mode 100644 ligen/symbols/src/lib.rs delete mode 100644 ligen/symbols/src/module.rs diff --git a/Cargo.toml b/Cargo.toml index fc4ec372..4f895609 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "ligen", "ligen/common", "ligen/ir", - "ligen/symbols", "ligen/parsing", "ligen/utils", "ligen/traits", @@ -37,7 +36,6 @@ ligen-macro = { path = "ligen/macro" } ligen-parsing = { path = "ligen/parsing" } ligen-traits = { path = "ligen/traits" } ligen-utils = { path = "ligen/utils" } -ligen-symbols = { path = "ligen/symbols" } #ligen-c = { path = "ecosystem/c/generator" } #ligen-cmake = { path = "ecosystem/c/cmake" } ligen-python-parser = { path = "ecosystem/python/parser" } diff --git a/ecosystem/python/parser/src/identifier.rs b/ecosystem/python/parser/src/identifier.rs index 0748365e..369af0ef 100644 --- a/ecosystem/python/parser/src/identifier.rs +++ b/ecosystem/python/parser/src/identifier.rs @@ -1,4 +1,4 @@ -use ligen::symbols::Identifier; +use ligen::ir::Identifier; use ligen::parsing::parser::Parser; use ligen::parsing::parser::universal::identifier::IdentifierParser as InternalParser; use crate::prelude::*; diff --git a/ecosystem/python/parser/src/symbols/interface.rs b/ecosystem/python/parser/src/symbols/interface.rs index eb9ddec9..799516c3 100644 --- a/ecosystem/python/parser/src/symbols/interface.rs +++ b/ecosystem/python/parser/src/symbols/interface.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use rustpython_parser::ast::StmtClassDef; -use ligen::symbols::Interface; +use ligen::ir::Interface; use crate::identifier::IdentifierParser; use crate::symbols::scope::ScopeParser; @@ -21,6 +21,6 @@ impl Parser> for InterfaceParser { let constants = scope.constants; let functions = scope.functions; let methods = scope.methods; - Ok(Interface { identifier, constants, functions, methods }) + Ok(Interface { identifier, constants, functions, methods, .. Default::default() }) } } \ No newline at end of file diff --git a/ecosystem/python/parser/src/symbols/module.rs b/ecosystem/python/parser/src/symbols/module.rs index c7e088f4..5bbd5a9a 100644 --- a/ecosystem/python/parser/src/symbols/module.rs +++ b/ecosystem/python/parser/src/symbols/module.rs @@ -1,7 +1,7 @@ use rustpython_parser::ast::ModModule; use rustpython_parser::parse; -use ligen::symbols::Identifier; -use ligen::symbols::Module; +use ligen::ir::Identifier; +use ligen::ir::Module; use crate::identifier::IdentifierParser; use crate::prelude::*; use crate::symbols::scope::ScopeParser; @@ -36,7 +36,7 @@ impl Parser> for ModuleParser { let types = scope.types; let functions = scope.functions; let interfaces = scope.interfaces; - Ok(Module { identifier, constants, types, functions, interfaces, modules }) + Ok(Module { identifier, constants, types, functions, interfaces, modules, .. Default::default() }) } } diff --git a/ecosystem/python/parser/src/symbols/scope.rs b/ecosystem/python/parser/src/symbols/scope.rs index a14d354b..f0e34684 100644 --- a/ecosystem/python/parser/src/symbols/scope.rs +++ b/ecosystem/python/parser/src/symbols/scope.rs @@ -1,6 +1,5 @@ use rustpython_parser::ast::{Arguments, Expr, Stmt}; -use ligen::symbols::Identifier; -use ligen::symbols::Interface; +use ligen::ir::{Identifier, Interface, Constant, Function, Method, TypeDefinition, Structure}; use crate::identifier::IdentifierParser; use crate::prelude::*; use crate::symbols::interface::InterfaceParser; @@ -87,19 +86,19 @@ impl ScopeParser { } } - fn parse_functions(&self, statements: &WithSource<&[Stmt]>) -> Result> { + fn parse_functions(&self, statements: &WithSource<&[Stmt]>) -> Result> { let mut functions = Vec::new(); for statement in statements.ast { if self.is_static_method(statements.sub(statement)) { match statement { Stmt::FunctionDef(function) => { if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - functions.push(identifier) + functions.push(Function { identifier, ..Default::default() }) } }, Stmt::AsyncFunctionDef(function) => { if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - functions.push(identifier) + functions.push(Function { identifier, ..Default::default() }) } }, @@ -110,19 +109,19 @@ impl ScopeParser { Ok(functions) } - fn parse_methods(&self, statements: &WithSource<&[Stmt]>) -> Result> { + fn parse_methods(&self, statements: &WithSource<&[Stmt]>) -> Result> { let mut methods = Vec::new(); for statement in statements.ast { if !self.is_static_method(statements.sub(statement)) { match statement { Stmt::FunctionDef(function) => { if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - methods.push(identifier) + methods.push(Method { identifier, ..Default::default() }) } }, Stmt::AsyncFunctionDef(function) => { if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - methods.push(identifier) + methods.push(Method { identifier, ..Default::default() }) } }, _ => (), @@ -132,16 +131,16 @@ impl ScopeParser { Ok(methods) } - fn parse_types(&self, statements: &WithSource<&[Stmt]>) -> Result> { - let mut interfaces = Vec::new(); + fn parse_types(&self, statements: &WithSource<&[Stmt]>) -> Result> { + let mut types = Vec::new(); for statement in statements.ast { if let Stmt::ClassDef(class) = statement { if let Ok(identifier) = IdentifierParser::new().parse(class.name.as_str()) { - interfaces.push(identifier) + types.push(Structure { identifier, .. Default::default() }.into()) } } } - Ok(interfaces) + Ok(types) } fn parse_interfaces(&self, statements: &WithSource<&[Stmt]>) -> Result> { @@ -160,7 +159,7 @@ impl ScopeParser { identifier.name.to_uppercase() == identifier.name } - fn parse_constants(&self, statements: &WithSource<&[Stmt]>) -> Result> { + fn parse_constants(&self, statements: &WithSource<&[Stmt]>) -> Result> { let mut constants = Vec::new(); for statement in statements.ast { match statement { @@ -168,7 +167,7 @@ impl ScopeParser { for target in &assign.targets { if let Ok(identifier) = self.parse_expr(target) { if self.is_constant(&identifier) { - constants.push(identifier) + constants.push(Constant { identifier, .. Default::default() }) } } } @@ -176,14 +175,14 @@ impl ScopeParser { Stmt::AnnAssign(assign) => { if let Ok(identifier) = self.parse_expr(&assign.target) { if self.is_constant(&identifier) { - constants.push(identifier) + constants.push(Constant { identifier, .. Default::default() }) } } }, Stmt::AugAssign(assign) => { if let Ok(identifier) = self.parse_expr(&assign.target) { if self.is_constant(&identifier) { - constants.push(identifier) + constants.push(Constant { identifier, .. Default::default() }) } } }, diff --git a/ecosystem/python/parser/src/symbols/scope/scope_type.rs b/ecosystem/python/parser/src/symbols/scope/scope_type.rs index fbfe5c65..bddba105 100644 --- a/ecosystem/python/parser/src/symbols/scope/scope_type.rs +++ b/ecosystem/python/parser/src/symbols/scope/scope_type.rs @@ -1,11 +1,10 @@ -use ligen::symbols::Interface; -use ligen::symbols::Identifier; +use ligen::ir::{Interface, Constant, Function, Method, TypeDefinition}; pub struct Scope { - pub constants: Vec, - pub types: Vec, - pub functions: Vec, - pub methods: Vec, + pub constants: Vec, + pub types: Vec, + pub functions: Vec, + pub methods: Vec, pub interfaces: Vec, } diff --git a/ligen/Cargo.toml b/ligen/Cargo.toml index 6e166267..600dd058 100644 --- a/ligen/Cargo.toml +++ b/ligen/Cargo.toml @@ -11,7 +11,6 @@ readme.workspace = true [dependencies] ligen-macro.workspace = true ligen-ir.workspace = true -ligen-symbols.workspace = true ligen-utils.workspace = true ligen-traits.workspace = true ligen-parsing.workspace = true diff --git a/ligen/ir/src/interface.rs b/ligen/ir/src/interface.rs index ec7c7f24..0c37714b 100644 --- a/ligen/ir/src/interface.rs +++ b/ligen/ir/src/interface.rs @@ -1,7 +1,7 @@ use crate::{Attributes, Constant, Function, Identifier, Method, Path, Visibility}; use crate::prelude::*; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Interface { /// Interface attributes. pub attributes: Attributes, @@ -18,3 +18,12 @@ pub struct Interface { /// Interfaces that this interface extends. pub interfaces: Vec } + +impl Interface { + /// Count the number of symbols in this interface. + pub fn count_symbols(&self) -> usize { + self.constants.len() + + self.functions.len() + + self.methods.len() + } +} \ No newline at end of file diff --git a/ligen/ir/src/module/mod.rs b/ligen/ir/src/module/mod.rs index d590e9d9..3c81ac75 100644 --- a/ligen/ir/src/module/mod.rs +++ b/ligen/ir/src/module/mod.rs @@ -52,4 +52,36 @@ impl Module { None } } + + pub fn join(&mut self, other: Self) { + self.interfaces.extend(other.interfaces); + self.functions.extend(other.functions); + self.types.extend(other.types); + self.constants.extend(other.constants); + self.modules.extend(other.modules); + self.imports.extend(other.imports); + } + + pub fn count_symbols_in_interfaces(&self) -> usize { + self.interfaces.iter().fold(0, |acc, interface| acc + interface.count_symbols()) + } + + pub fn count_symbols_in_modules(&self) -> usize { + self.modules.iter().fold(0, |acc, module| acc + module.count_symbols()) + } + pub fn count_symbols(&self) -> usize { + self.constants.len() + + self.functions.len() + + self.types.len() + + self.count_symbols_in_interfaces() + + self.count_symbols_in_modules() + } + + pub fn is_empty(&self) -> bool { + self.constants.is_empty() + && self.functions.is_empty() + && self.interfaces.is_empty() + && self.types.is_empty() + && self.modules.is_empty() + } } diff --git a/ligen/ir/src/types/type_definition/mod.rs b/ligen/ir/src/types/type_definition/mod.rs index 6aaf73c9..c2f8880c 100644 --- a/ligen/ir/src/types/type_definition/mod.rs +++ b/ligen/ir/src/types/type_definition/mod.rs @@ -6,6 +6,7 @@ pub mod enumeration; use crate::prelude::*; pub use structure::{Structure, Field}; pub use enumeration::{Enumeration, Variant}; +use crate::Identifier; /// All the possible ways to define a type. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -15,6 +16,15 @@ pub enum TypeDefinition { Enumeration(Enumeration) } +impl TypeDefinition { + pub fn identifier_mut(&mut self) -> &mut Identifier { + match self { + Self::Structure(structure) => &mut structure.identifier, + Self::Enumeration(enumeration) => &mut enumeration.identifier + } + } +} + impl Default for TypeDefinition { fn default() -> Self { Self::Structure(Default::default()) diff --git a/ligen/src/lib.rs b/ligen/src/lib.rs index 1b29473d..2e975832 100644 --- a/ligen/src/lib.rs +++ b/ligen/src/lib.rs @@ -65,4 +65,3 @@ pub use ligen_utils as utils; pub use ligen_traits as traits; pub use ligen_parsing as parsing; pub use ligen_common as common; -pub use ligen_symbols as symbols; diff --git a/ligen/symbols/Cargo.toml b/ligen/symbols/Cargo.toml deleted file mode 100644 index 2ed40c10..00000000 --- a/ligen/symbols/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "ligen-symbols" -version.workspace = true -edition.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -ligen-ir.workspace = true \ No newline at end of file diff --git a/ligen/symbols/src/identifier.rs b/ligen/symbols/src/identifier.rs deleted file mode 100644 index 813ee69e..00000000 --- a/ligen/symbols/src/identifier.rs +++ /dev/null @@ -1 +0,0 @@ -pub type Identifier = ligen_ir::Identifier; \ No newline at end of file diff --git a/ligen/symbols/src/interface.rs b/ligen/symbols/src/interface.rs deleted file mode 100644 index 3ceb3e5d..00000000 --- a/ligen/symbols/src/interface.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::identifier::Identifier; - -#[derive(Default)] -pub struct Interface { - pub identifier: Identifier, - pub constants: Vec, - pub functions: Vec, - pub methods: Vec -} - -impl Interface { - pub fn count_symbols(&self) -> usize { - self.constants.len() - + self.functions.len() - + self.methods.len() - } -} \ No newline at end of file diff --git a/ligen/symbols/src/lib.rs b/ligen/symbols/src/lib.rs deleted file mode 100644 index 51d04c75..00000000 --- a/ligen/symbols/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod module; -mod identifier; -mod interface; - -pub use module::*; -pub use identifier::*; -pub use interface::*; \ No newline at end of file diff --git a/ligen/symbols/src/module.rs b/ligen/symbols/src/module.rs deleted file mode 100644 index 9bf40e14..00000000 --- a/ligen/symbols/src/module.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::identifier::Identifier; -use crate::interface::Interface; - -#[derive(Default)] -pub struct Module { - pub identifier: Identifier, - pub constants: Vec, - pub functions: Vec, - pub interfaces: Vec, - pub types: Vec, - pub modules: Vec -} - -impl Module { - pub fn count_symbols_in_interfaces(&self) -> usize { - self.interfaces.iter().fold(0, |acc, interface| acc + interface.count_symbols()) - } - - pub fn count_symbols_in_modules(&self) -> usize { - self.modules.iter().fold(0, |acc, module| acc + module.count_symbols()) - } - pub fn count_symbols(&self) -> usize { - self.constants.len() - + self.functions.len() - + self.types.len() - + self.count_symbols_in_interfaces() - + self.count_symbols_in_modules() - } - - pub fn is_empty(&self) -> bool { - self.constants.is_empty() - && self.functions.is_empty() - && self.interfaces.is_empty() - && self.types.is_empty() - && self.modules.is_empty() - } - - pub fn join(&mut self, other: Self) { - self.constants.extend(other.constants); - self.functions.extend(other.functions); - self.interfaces.extend(other.interfaces); - self.types.extend(other.types); - self.modules.extend(other.modules); - } -} \ No newline at end of file diff --git a/tools/editor/Cargo.toml b/tools/editor/Cargo.toml index 7942d4de..6969a984 100644 --- a/tools/editor/Cargo.toml +++ b/tools/editor/Cargo.toml @@ -11,7 +11,6 @@ readme.workspace = true [dependencies] ligen-gui-runtime.workspace = true ligen-ir.workspace = true -ligen-symbols.workspace = true serde.workspace = true ligen-parsing.workspace = true ligen-cargo.workspace = true diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/interface.rs b/tools/editor/src/gui/ui/layout/editor/symbols/interface.rs index 3b766d6a..1e812cd1 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/interface.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/interface.rs @@ -9,17 +9,17 @@ impl Interface { Self } - pub fn show(&mut self, ui: &mut egui::Ui, interface: &mut ligen_symbols::Interface) { + pub fn show(&mut self, ui: &mut egui::Ui, interface: &mut ligen_ir::Interface) { ui.vertical(|ui| { Identifier::new().show(ui, &mut interface.identifier); EditableList::new("Constants", "Add constant").show(ui, &mut interface.constants, |ui, constant| { - Identifier::new().show(ui, constant); + Identifier::new().show(ui, &mut constant.identifier); }); EditableList::new("Functions", "Add function").show(ui, &mut interface.functions, |ui, function| { - Identifier::new().show(ui, function); + Identifier::new().show(ui, &mut function.identifier); }); EditableList::new("Methods", "Add method").show(ui, &mut interface.methods, |ui, method| { - Identifier::new().show(ui, method); + Identifier::new().show(ui, &mut method.identifier); }); }); } diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/mod.rs b/tools/editor/src/gui/ui/layout/editor/symbols/mod.rs index d3242748..f230d523 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/mod.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/mod.rs @@ -11,11 +11,11 @@ use crate::gui::ui::panes::Pane; #[derive(Default)] pub struct Editor { - module: ligen_symbols::Module + module: ligen_ir::Module } impl Editor { - pub fn new(module: ligen_symbols::Module) -> Self { + pub fn new(module: ligen_ir::Module) -> Self { Self { module } } } diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/module.rs b/tools/editor/src/gui/ui/layout/editor/symbols/module.rs index 3ff366a7..0b21361c 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/module.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/module.rs @@ -11,18 +11,18 @@ impl Module { Self } - pub fn show(&mut self, ui: &mut egui::Ui, module: &mut ligen_symbols::Module) { + pub fn show(&mut self, ui: &mut egui::Ui, module: &mut ligen_ir::Module) { CollapsingHeader::new(format!("{} - Symbols: {}", module.identifier, module.count_symbols())) .id_source("module") .show(ui, |ui| { EditableList::new(format!("Constants - Symbols: {}", module.constants.len()), "Add constant").show(ui, &mut module.constants, |ui, constant| { - Identifier::new().show(ui, constant); + Identifier::new().show(ui, &mut constant.identifier); }); EditableList::new(format!("Functions - Symbols: {}", module.functions.len()), "Add function").show(ui, &mut module.functions, |ui, function| { - Identifier::new().show(ui, function); + Identifier::new().show(ui, &mut function.identifier); }); EditableList::new(format!("Types - Symbols: {}", module.types.len()), "Add type").show(ui, &mut module.types, |ui, type_| { - Identifier::new().show(ui, type_); + Identifier::new().show(ui, type_.identifier_mut()); }); EditableList::new(format!("Interfaces - Symbols: {}", module.count_symbols_in_interfaces()), "Add interface").show(ui, &mut module.interfaces, |ui, interface| { Interface::new().show(ui, interface); diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/project.rs b/tools/editor/src/gui/ui/layout/editor/symbols/project.rs index 700c79b0..84120c5a 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/project.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/project.rs @@ -9,7 +9,7 @@ impl Project { Self } - pub fn show(&mut self, ui: &mut egui::Ui, module: &mut ligen_symbols::Module) { + pub fn show(&mut self, ui: &mut egui::Ui, module: &mut ligen_ir::Module) { egui::ScrollArea::both() .auto_shrink([false, true]) .show(ui, |ui| { From c9ea10a7d19918e7f3b0d49b713c19c09e5fb73a Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Wed, 18 Oct 2023 15:53:09 -0300 Subject: [PATCH 02/11] Adding 'parse_symbols' to Parser trait --- .../python/parser/src/symbols/interface.rs | 3 +++ ecosystem/python/parser/src/symbols/module.rs | 20 +++++++++++++++++-- ecosystem/python/parser/src/symbols/scope.rs | 3 +++ ligen/parsing/src/parser/mod.rs | 5 ++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/ecosystem/python/parser/src/symbols/interface.rs b/ecosystem/python/parser/src/symbols/interface.rs index 799516c3..59bb1357 100644 --- a/ecosystem/python/parser/src/symbols/interface.rs +++ b/ecosystem/python/parser/src/symbols/interface.rs @@ -16,6 +16,9 @@ impl InterfaceParser { impl Parser> for InterfaceParser { type Output = Interface; fn parse(&self, input: WithSource<&StmtClassDef>) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: WithSource<&StmtClassDef>) -> Result { let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; let constants = scope.constants; diff --git a/ecosystem/python/parser/src/symbols/module.rs b/ecosystem/python/parser/src/symbols/module.rs index 5bbd5a9a..35f38a14 100644 --- a/ecosystem/python/parser/src/symbols/module.rs +++ b/ecosystem/python/parser/src/symbols/module.rs @@ -18,6 +18,9 @@ impl ModuleParser { impl Parser<&str> for ModuleParser { type Output = Module; fn parse(&self, input: &str) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: &str) -> Result { let module = parse(input, Mode::Module, "") .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? .module() @@ -29,6 +32,9 @@ impl Parser<&str> for ModuleParser { impl Parser> for ModuleParser { type Output = Module; fn parse(&self, input: WithSource) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: WithSource) -> Result { let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; let identifier = Default::default(); let modules = Default::default(); @@ -45,7 +51,11 @@ struct File<'a>(pub &'a std::path::Path); impl Parser> for ModuleParser { type Output = Module; - fn parse(&self, File(input): File<'_>) -> Result { + fn parse(&self, input: File<'_>) -> Result { + self.parse_symbols(input) + } + + fn parse_symbols(&self, File(input): File<'_>) -> Result { let content = std::fs::read_to_string(input)?; let mut module = self.parse(content.as_str())?; module.identifier = self.parse_identifier(input)?; @@ -55,7 +65,10 @@ impl Parser> for ModuleParser { impl Parser> for ModuleParser { type Output = Module; - fn parse(&self, Directory(input): Directory<'_>) -> Result { + fn parse(&self, input: Directory<'_>) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, Directory(input): Directory<'_>) -> Result { let identifier = self.parse_identifier(input)?; let mut module = Module { identifier, .. Default::default() }; let mut modules: Vec = Vec::new(); @@ -97,6 +110,9 @@ impl Parser> for ModuleParser { impl Parser<&std::path::Path> for ModuleParser { type Output = Module; fn parse(&self, input: &std::path::Path) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: &std::path::Path) -> Result { if input.is_dir() { self.parse(Directory(input)) } else { diff --git a/ecosystem/python/parser/src/symbols/scope.rs b/ecosystem/python/parser/src/symbols/scope.rs index f0e34684..c7070666 100644 --- a/ecosystem/python/parser/src/symbols/scope.rs +++ b/ecosystem/python/parser/src/symbols/scope.rs @@ -20,6 +20,9 @@ impl ScopeParser { impl Parser> for ScopeParser { type Output = Scope; fn parse(&self, input: WithSource<&[Stmt]>) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: WithSource<&[Stmt]>) -> Result { let constants = self.parse_constants(&input)?; let types = self.parse_types(&input)?; let functions = self.parse_functions(&input)?; diff --git a/ligen/parsing/src/parser/mod.rs b/ligen/parsing/src/parser/mod.rs index c6a4d4dd..8a875729 100644 --- a/ligen/parsing/src/parser/mod.rs +++ b/ligen/parsing/src/parser/mod.rs @@ -1,8 +1,11 @@ pub mod universal; -use ligen_common::Result; +use ligen_common::{Error, Result}; pub trait Parser { type Output; fn parse(&self, input: Input) -> Result; + fn parse_symbols(&self, _input: Input) -> Result { + Err(Error::Message("Not implemented".to_string())) + } } \ No newline at end of file From 86faa343a5d0c90c3909a8c93e06e6a5db818780 Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Wed, 18 Oct 2023 16:10:55 -0300 Subject: [PATCH 03/11] Unifying scope and IR parsers --- .../parser/src/{symbols => }/interface.rs | 2 +- ecosystem/python/parser/src/lib.rs | 3 +- ecosystem/python/parser/src/module/mod.rs | 140 ++++++++++++++---- .../src/{symbols/scope.rs => scope/mod.rs} | 2 +- .../src/{symbols => }/scope/scope_type.rs | 0 ecosystem/python/parser/src/symbols/mod.rs | 3 - ecosystem/python/parser/src/symbols/module.rs | 133 ----------------- .../ui/layout/editor/symbols/menu_button.rs | 4 +- 8 files changed, 117 insertions(+), 170 deletions(-) rename ecosystem/python/parser/src/{symbols => }/interface.rs (95%) rename ecosystem/python/parser/src/{symbols/scope.rs => scope/mod.rs} (99%) rename ecosystem/python/parser/src/{symbols => }/scope/scope_type.rs (100%) delete mode 100644 ecosystem/python/parser/src/symbols/mod.rs delete mode 100644 ecosystem/python/parser/src/symbols/module.rs diff --git a/ecosystem/python/parser/src/symbols/interface.rs b/ecosystem/python/parser/src/interface.rs similarity index 95% rename from ecosystem/python/parser/src/symbols/interface.rs rename to ecosystem/python/parser/src/interface.rs index 59bb1357..16ce6634 100644 --- a/ecosystem/python/parser/src/symbols/interface.rs +++ b/ecosystem/python/parser/src/interface.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use rustpython_parser::ast::StmtClassDef; use ligen::ir::Interface; use crate::identifier::IdentifierParser; -use crate::symbols::scope::ScopeParser; +use crate::scope::ScopeParser; #[derive(Default)] pub struct InterfaceParser; diff --git a/ecosystem/python/parser/src/lib.rs b/ecosystem/python/parser/src/lib.rs index d3fc4f72..9a73cb53 100644 --- a/ecosystem/python/parser/src/lib.rs +++ b/ecosystem/python/parser/src/lib.rs @@ -5,4 +5,5 @@ pub mod identifier; pub mod macro_attributes; pub mod types; pub mod literal; -pub mod symbols; \ No newline at end of file +pub mod scope; +pub mod interface; diff --git a/ecosystem/python/parser/src/module/mod.rs b/ecosystem/python/parser/src/module/mod.rs index 3750bff2..fc830858 100644 --- a/ecosystem/python/parser/src/module/mod.rs +++ b/ecosystem/python/parser/src/module/mod.rs @@ -1,18 +1,30 @@ use crate::prelude::*; -use ligen::ir::{Constant, Function, Import, Module, TypeDefinition, Interface}; +use ligen::ir::{Constant, Function, Import, Module, TypeDefinition, Interface, Identifier}; use rustpython_parser::ast::{ModModule, Stmt}; use crate::function::FunctionParser; +use crate::identifier::IdentifierParser; +use crate::scope::ScopeParser; +#[derive(Default)] pub struct ModuleParser; +impl ModuleParser { + pub fn new() -> Self { + Default::default() + } +} + impl Parser<&str> for ModuleParser { type Output = Module; fn parse(&self, input: &str) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: &str) -> Result { let module = parse(input, Mode::Module, "") .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? .module() .ok_or(Error::Message("No module found".into()))?; - self.parse(WithSource::new(input, module)) + self.parse_symbols(WithSource::new(input, module)) } } @@ -30,6 +42,103 @@ impl Parser> for ModuleParser { let interfaces = self.extract_interfaces(&input)?; Ok(Module { attributes, visibility, identifier, modules, imports, constants, functions, types, interfaces }) } + + fn parse_symbols(&self, input: WithSource) -> Result { + let scope = ScopeParser::new().parse_symbols(input.sub(&input.ast.body))?; + let identifier = Default::default(); + let modules = Default::default(); + let constants = scope.constants; + let types = scope.types; + let functions = scope.functions; + let interfaces = scope.interfaces; + Ok(Module { identifier, constants, types, functions, interfaces, modules, .. Default::default() }) + } +} + +struct Directory<'a>(pub &'a std::path::Path); +struct File<'a>(pub &'a std::path::Path); + +impl Parser> for ModuleParser { + type Output = Module; + fn parse(&self, input: File<'_>) -> Result { + self.parse_symbols(input) + } + + fn parse_symbols(&self, File(input): File<'_>) -> Result { + let content = std::fs::read_to_string(input)?; + let mut module = self.parse_symbols(content.as_str())?; + module.identifier = self.parse_identifier(input)?; + Ok(module) + } +} + +impl Parser> for ModuleParser { + type Output = Module; + fn parse(&self, input: Directory<'_>) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, Directory(input): Directory<'_>) -> Result { + let identifier = self.parse_identifier(input)?; + let mut module = Module { identifier, .. Default::default() }; + let mut modules: Vec = Vec::new(); + for entry in input.read_dir()? { + let entry = entry?; + let path = entry.path(); + let extension = path + .extension() + .and_then(|extension| extension.to_str()) + .map(String::from) + .unwrap_or_default(); + if extension == "py" || path.is_dir() { + if let Ok(module) = self.parse_symbols(path.as_path()) { + if let Some(existing) = modules + .iter_mut() + .find(|existing| existing.identifier == module.identifier) + { + existing.join(module) + } else { + modules.push(module); + } + } + } + } + if let Some((index, _)) = modules + .iter() + .enumerate() + .find(|(_, sub_module)| sub_module.identifier.name == "__init__") + { + let identifier = module.identifier; + module = modules.remove(index); + module.identifier = identifier; + } + module.modules = modules; + Ok(module) + } +} + +impl Parser<&std::path::Path> for ModuleParser { + type Output = Module; + fn parse(&self, input: &std::path::Path) -> Result { + self.parse_symbols(input) + } + fn parse_symbols(&self, input: &std::path::Path) -> Result { + if input.is_dir() { + self.parse_symbols(Directory(input)) + } else { + self.parse_symbols(File(input)).map_err(|error| Error::Message(format!("Failed to read {}. Cause: {:?}", input.display(), error))) + } + } +} + +impl ModuleParser { + fn parse_identifier(&self, input: &std::path::Path) -> Result { + let identifier = input + .file_stem() + .ok_or(Error::Message(format!("Failed to parse file stem from path: {}", input.display())))? + .to_str() + .ok_or(Error::Message(format!("Failed to parse file stem to string: {}", input.display())))?; + IdentifierParser::new().parse(identifier) + } } impl ModuleParser { @@ -61,30 +170,3 @@ impl ModuleParser { Ok(Default::default()) } } - -#[cfg(test)] -mod test { - - // #[test] - // fn sub_modules() -> Result<()> { - // assert_eq(ModuleParser, mock::sub_modules(), quote! { - // pub mod root { - // pub mod branch { - // pub mod leaf {} - // } - // } - // }) - // } - - // #[test] - // fn module_objects() -> Result<()> { - // assert_eq(ModuleParser, mock::module_objects(), quote! { - // pub mod objects { - // pub struct Structure; - // pub enum Enumeration {} - // pub const CONSTANT: bool = false; - // pub fn function() {} - // } - // }) - // } -} diff --git a/ecosystem/python/parser/src/symbols/scope.rs b/ecosystem/python/parser/src/scope/mod.rs similarity index 99% rename from ecosystem/python/parser/src/symbols/scope.rs rename to ecosystem/python/parser/src/scope/mod.rs index c7070666..bf7f2b74 100644 --- a/ecosystem/python/parser/src/symbols/scope.rs +++ b/ecosystem/python/parser/src/scope/mod.rs @@ -2,7 +2,7 @@ use rustpython_parser::ast::{Arguments, Expr, Stmt}; use ligen::ir::{Identifier, Interface, Constant, Function, Method, TypeDefinition, Structure}; use crate::identifier::IdentifierParser; use crate::prelude::*; -use crate::symbols::interface::InterfaceParser; +use crate::interface::InterfaceParser; mod scope_type; diff --git a/ecosystem/python/parser/src/symbols/scope/scope_type.rs b/ecosystem/python/parser/src/scope/scope_type.rs similarity index 100% rename from ecosystem/python/parser/src/symbols/scope/scope_type.rs rename to ecosystem/python/parser/src/scope/scope_type.rs diff --git a/ecosystem/python/parser/src/symbols/mod.rs b/ecosystem/python/parser/src/symbols/mod.rs deleted file mode 100644 index c62c003c..00000000 --- a/ecosystem/python/parser/src/symbols/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod module; -pub mod interface; -pub(crate) mod scope; \ No newline at end of file diff --git a/ecosystem/python/parser/src/symbols/module.rs b/ecosystem/python/parser/src/symbols/module.rs deleted file mode 100644 index 35f38a14..00000000 --- a/ecosystem/python/parser/src/symbols/module.rs +++ /dev/null @@ -1,133 +0,0 @@ -use rustpython_parser::ast::ModModule; -use rustpython_parser::parse; -use ligen::ir::Identifier; -use ligen::ir::Module; -use crate::identifier::IdentifierParser; -use crate::prelude::*; -use crate::symbols::scope::ScopeParser; - -#[derive(Default)] -pub struct ModuleParser; - -impl ModuleParser { - pub fn new() -> Self { - Default::default() - } -} - -impl Parser<&str> for ModuleParser { - type Output = Module; - fn parse(&self, input: &str) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: &str) -> Result { - let module = parse(input, Mode::Module, "") - .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? - .module() - .ok_or(Error::Message("No module found".into()))?; - self.parse(WithSource::new(input, module)) - } -} - -impl Parser> for ModuleParser { - type Output = Module; - fn parse(&self, input: WithSource) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: WithSource) -> Result { - let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; - let identifier = Default::default(); - let modules = Default::default(); - let constants = scope.constants; - let types = scope.types; - let functions = scope.functions; - let interfaces = scope.interfaces; - Ok(Module { identifier, constants, types, functions, interfaces, modules, .. Default::default() }) - } -} - -struct Directory<'a>(pub &'a std::path::Path); -struct File<'a>(pub &'a std::path::Path); - -impl Parser> for ModuleParser { - type Output = Module; - fn parse(&self, input: File<'_>) -> Result { - self.parse_symbols(input) - } - - fn parse_symbols(&self, File(input): File<'_>) -> Result { - let content = std::fs::read_to_string(input)?; - let mut module = self.parse(content.as_str())?; - module.identifier = self.parse_identifier(input)?; - Ok(module) - } -} - -impl Parser> for ModuleParser { - type Output = Module; - fn parse(&self, input: Directory<'_>) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, Directory(input): Directory<'_>) -> Result { - let identifier = self.parse_identifier(input)?; - let mut module = Module { identifier, .. Default::default() }; - let mut modules: Vec = Vec::new(); - for entry in input.read_dir()? { - let entry = entry?; - let path = entry.path(); - let extension = path - .extension() - .and_then(|extension| extension.to_str()) - .map(String::from) - .unwrap_or_default(); - if extension == "py" || path.is_dir() { - if let Ok(module) = self.parse(path.as_path()) { - if let Some(existing) = modules - .iter_mut() - .find(|existing| existing.identifier == module.identifier) - { - existing.join(module) - } else { - modules.push(module); - } - } - } - } - if let Some((index, _)) = modules - .iter() - .enumerate() - .find(|(_, sub_module)| sub_module.identifier.name == "__init__") - { - let identifier = module.identifier; - module = modules.remove(index); - module.identifier = identifier; - } - module.modules = modules; - Ok(module) - } -} - -impl Parser<&std::path::Path> for ModuleParser { - type Output = Module; - fn parse(&self, input: &std::path::Path) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: &std::path::Path) -> Result { - if input.is_dir() { - self.parse(Directory(input)) - } else { - self.parse(File(input)).map_err(|error| Error::Message(format!("Failed to read {}. Cause: {:?}", input.display(), error))) - } - } -} - -impl ModuleParser { - fn parse_identifier(&self, input: &std::path::Path) -> Result { - let identifier = input - .file_stem() - .ok_or(Error::Message(format!("Failed to parse file stem from path: {}", input.display())))? - .to_str() - .ok_or(Error::Message(format!("Failed to parse file stem to string: {}", input.display())))?; - IdentifierParser::new().parse(identifier) - } -} \ No newline at end of file diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs index 22421790..18d1ac61 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs @@ -1,5 +1,5 @@ -use ligen_python_parser::symbols::module::ModuleParser; use ligen_parsing::parser::Parser; +use ligen_python_parser::module::ModuleParser; use crate::prelude::*; use crate::gui::ui::editor::symbols::Editor; use crate::gui::ui::menu::MenuButton; @@ -17,7 +17,7 @@ impl MenuButton for EditorMenuButton { if let Some(entry) = entry { stacker::grow(1024 * 1024 * 10, || { - let module = ModuleParser.parse(entry.as_path()).unwrap(); + let module = ModuleParser::new().parse_symbols(entry.as_path()).unwrap(); panes.new_pane(Box::new(Editor::new(module))); }); } From fa1ac196b233fd59069f08ae9653302bef624c89 Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Wed, 18 Oct 2023 16:35:30 -0300 Subject: [PATCH 04/11] Simplifying parser --- ecosystem/python/parser/src/module/mod.rs | 68 +++++++---------------- 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/ecosystem/python/parser/src/module/mod.rs b/ecosystem/python/parser/src/module/mod.rs index fc830858..5d639c92 100644 --- a/ecosystem/python/parser/src/module/mod.rs +++ b/ecosystem/python/parser/src/module/mod.rs @@ -1,7 +1,6 @@ use crate::prelude::*; -use ligen::ir::{Constant, Function, Import, Module, TypeDefinition, Interface, Identifier}; -use rustpython_parser::ast::{ModModule, Stmt}; -use crate::function::FunctionParser; +use ligen::ir::{Module, Identifier}; +use rustpython_parser::ast::ModModule; use crate::identifier::IdentifierParser; use crate::scope::ScopeParser; @@ -17,7 +16,11 @@ impl ModuleParser { impl Parser<&str> for ModuleParser { type Output = Module; fn parse(&self, input: &str) -> Result { - self.parse_symbols(input) + let module = parse(input, Mode::Module, "") + .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? + .module() + .ok_or(Error::Message("No module found".into()))?; + self.parse(WithSource::new(input, module)) } fn parse_symbols(&self, input: &str) -> Result { let module = parse(input, Mode::Module, "") @@ -31,27 +34,21 @@ impl Parser<&str> for ModuleParser { impl Parser> for ModuleParser { type Output = Module; fn parse(&self, input: WithSource) -> Result { - let attributes = Default::default(); - let visibility = Default::default(); - let identifier = Default::default(); - let modules = Default::default(); - let imports = self.extract_imports(&input)?; - let constants = self.extract_constants(&input)?; - let functions = self.extract_functions(&input)?; - let types = self.extract_types(&input)?; - let interfaces = self.extract_interfaces(&input)?; - Ok(Module { attributes, visibility, identifier, modules, imports, constants, functions, types, interfaces }) + let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; + let constants = scope.constants; + let types = scope.types; + let functions = scope.functions; + let interfaces = scope.interfaces; + Ok(Module { constants, functions, types, interfaces, ..Default::default() }) } fn parse_symbols(&self, input: WithSource) -> Result { let scope = ScopeParser::new().parse_symbols(input.sub(&input.ast.body))?; - let identifier = Default::default(); - let modules = Default::default(); let constants = scope.constants; let types = scope.types; let functions = scope.functions; let interfaces = scope.interfaces; - Ok(Module { identifier, constants, types, functions, interfaces, modules, .. Default::default() }) + Ok(Module { constants, types, functions, interfaces, ..Default::default() }) } } @@ -60,8 +57,11 @@ struct File<'a>(pub &'a std::path::Path); impl Parser> for ModuleParser { type Output = Module; - fn parse(&self, input: File<'_>) -> Result { - self.parse_symbols(input) + fn parse(&self, File(input): File<'_>) -> Result { + let content = std::fs::read_to_string(input)?; + let mut module = self.parse(content.as_str())?; + module.identifier = self.parse_identifier(input)?; + Ok(module) } fn parse_symbols(&self, File(input): File<'_>) -> Result { @@ -140,33 +140,3 @@ impl ModuleParser { IdentifierParser::new().parse(identifier) } } - -impl ModuleParser { - fn extract_imports(&self, _input: &WithSource) -> Result> { - Ok(Default::default()) - } - - fn extract_constants(&self, _input: &WithSource) -> Result> { - Ok(Default::default()) - } - - fn extract_functions(&self, input: &WithSource) -> Result> { - let mut functions = Vec::new(); - for statement in &input.ast.body { - match statement { - Stmt::FunctionDef(function) => functions.push(FunctionParser.parse(input.sub(function.clone()))?), - Stmt::AsyncFunctionDef(function) => functions.push(FunctionParser.parse(input.sub(function.clone()))?), - _ => () - } - } - Ok(functions) - } - - fn extract_types(&self, _input: &WithSource) -> Result> { - Ok(Default::default()) - } - - fn extract_interfaces(&self, _input: &WithSource) -> Result> { - Ok(Default::default()) - } -} From 052577b435a65e1cf7844540ddcfc14d1d5abd3e Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Fri, 20 Oct 2023 16:05:29 -0300 Subject: [PATCH 05/11] Improving parser structure --- ecosystem/python/parser/src/constant.rs | 67 ++++++++++++++ .../python/parser/src/function/method.rs | 50 +++++++++++ ecosystem/python/parser/src/function/mod.rs | 12 +++ ecosystem/python/parser/src/interface.rs | 7 +- ecosystem/python/parser/src/lib.rs | 1 + ecosystem/python/parser/src/module/mod.rs | 51 ++++------- ecosystem/python/parser/src/scope/mod.rs | 88 +++++++++---------- ecosystem/python/parser/src/types/mod.rs | 3 +- .../parser/src/types/type_definition.rs | 26 ++++++ ecosystem/rust/parser/src/function/method.rs | 6 +- ligen/ir/src/function/method.rs | 2 - ligen/parsing/src/parser/mod.rs | 12 +-- .../ui/layout/editor/ir/function/method.rs | 1 - .../ui/layout/editor/symbols/menu_button.rs | 2 +- 14 files changed, 226 insertions(+), 102 deletions(-) create mode 100644 ecosystem/python/parser/src/constant.rs create mode 100644 ecosystem/python/parser/src/function/method.rs create mode 100644 ecosystem/python/parser/src/types/type_definition.rs diff --git a/ecosystem/python/parser/src/constant.rs b/ecosystem/python/parser/src/constant.rs new file mode 100644 index 00000000..48e7c45e --- /dev/null +++ b/ecosystem/python/parser/src/constant.rs @@ -0,0 +1,67 @@ +use rustpython_parser::ast::{Expr, StmtAnnAssign, StmtAssign, StmtAugAssign}; +use ligen::ir::{Constant, Identifier}; +use crate::identifier::IdentifierParser; +use crate::prelude::*; + +#[derive(Default)] +pub struct ConstantParser; + +impl ConstantParser { + pub fn new() -> Self { + Self::default() + } + + pub fn symbols() -> Self { + Self + } +} + +impl Parser<&StmtAnnAssign> for ConstantParser { + type Output = Constant; + fn parse(&self, input: &StmtAnnAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&StmtAugAssign> for ConstantParser { + type Output = Constant; + fn parse(&self, input: &StmtAugAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&Expr> for ConstantParser { + type Output = Constant; + fn parse(&self, expr: &Expr) -> Result { + let identifier = expr + .as_name_expr() + .ok_or(Error::Message("Expected identifier".into()))? + .id + .as_str(); + let identifier = IdentifierParser::new().parse(identifier)?; + if self.is_constant(&identifier) { + Ok(Constant { identifier, ..Default::default() }) + } else { + Err(Error::Message("Expected constant".into())) + } + } +} + +impl Parser<&StmtAssign> for ConstantParser { + type Output = Vec; + fn parse(&self, input: &StmtAssign) -> Result { + let mut constants = Vec::new(); + for target in &input.targets { + if let Ok(constant) = self.parse(target) { + constants.push(constant); + } + } + Ok(constants) + } +} + +impl ConstantParser { + fn is_constant(&self, identifier: &Identifier) -> bool { + identifier.name.to_uppercase() == identifier.name + } +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/function/method.rs b/ecosystem/python/parser/src/function/method.rs new file mode 100644 index 00000000..1e8dd839 --- /dev/null +++ b/ecosystem/python/parser/src/function/method.rs @@ -0,0 +1,50 @@ +use rustpython_parser::ast::{StmtAsyncFunctionDef, StmtFunctionDef}; +use ligen::ir::{Method, Mutability}; +use crate::function::FunctionParser; +use crate::prelude::*; + +#[derive(Default)] +pub struct MethodParser { + function_parser: FunctionParser +} + +impl MethodParser { + pub fn new() -> Self { + Default::default() + } + + pub fn symbols() -> Self { + let function_parser = FunctionParser::symbols(); + Self { function_parser } + } +} + +impl Parser> for MethodParser { + type Output = Method; + fn parse(&self, input: WithSource) -> Result { + let function = self.function_parser.parse(input)?; + let attributes = function.attributes; + let visibility = function.visibility; + let synchrony = function.synchrony; + let identifier = function.identifier; + let inputs = function.inputs; + let output = function.output; + let mutability = Mutability::Mutable; + Ok(Self::Output { attributes, visibility, synchrony, mutability, identifier, inputs, output }) + } +} + +impl Parser> for MethodParser { + type Output = Method; + fn parse(&self, input: WithSource) -> Result { + let function = self.function_parser.parse(input)?; + let attributes = function.attributes; + let visibility = function.visibility; + let synchrony = function.synchrony; + let identifier = function.identifier; + let inputs = function.inputs; + let output = function.output; + let mutability = Mutability::Mutable; + Ok(Self::Output { attributes, visibility, synchrony, mutability, identifier, inputs, output }) + } +} diff --git a/ecosystem/python/parser/src/function/mod.rs b/ecosystem/python/parser/src/function/mod.rs index 8dda21b7..f671fff9 100644 --- a/ecosystem/python/parser/src/function/mod.rs +++ b/ecosystem/python/parser/src/function/mod.rs @@ -1,4 +1,5 @@ pub mod parameter; +pub mod method; use crate::prelude::*; use rustpython_parser::ast::{Arguments, Expr, Ranged, Stmt, StmtAsyncFunctionDef, StmtFunctionDef}; @@ -8,8 +9,19 @@ use crate::identifier::IdentifierParser; use crate::macro_attributes::attributes::AttributesParser; use crate::types::type_::TypeParser; +#[derive(Default)] pub struct FunctionParser; +impl FunctionParser { + pub fn new() -> Self { + Self::default() + } + + pub fn symbols() -> Self { + Self::default() + } +} + impl Parser<&str> for FunctionParser { type Output = Function; fn parse(&self, input: &str) -> Result { diff --git a/ecosystem/python/parser/src/interface.rs b/ecosystem/python/parser/src/interface.rs index 16ce6634..7a427c54 100644 --- a/ecosystem/python/parser/src/interface.rs +++ b/ecosystem/python/parser/src/interface.rs @@ -11,14 +11,15 @@ impl InterfaceParser { pub fn new() -> Self { Default::default() } + + pub fn symbols() -> Self { + Default::default() + } } impl Parser> for InterfaceParser { type Output = Interface; fn parse(&self, input: WithSource<&StmtClassDef>) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: WithSource<&StmtClassDef>) -> Result { let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; let constants = scope.constants; diff --git a/ecosystem/python/parser/src/lib.rs b/ecosystem/python/parser/src/lib.rs index 9a73cb53..e4a574d5 100644 --- a/ecosystem/python/parser/src/lib.rs +++ b/ecosystem/python/parser/src/lib.rs @@ -7,3 +7,4 @@ pub mod types; pub mod literal; pub mod scope; pub mod interface; +pub mod constant; \ No newline at end of file diff --git a/ecosystem/python/parser/src/module/mod.rs b/ecosystem/python/parser/src/module/mod.rs index 5d639c92..c2169931 100644 --- a/ecosystem/python/parser/src/module/mod.rs +++ b/ecosystem/python/parser/src/module/mod.rs @@ -5,11 +5,19 @@ use crate::identifier::IdentifierParser; use crate::scope::ScopeParser; #[derive(Default)] -pub struct ModuleParser; +pub struct ModuleParser { + scope_parser: ScopeParser, +} impl ModuleParser { pub fn new() -> Self { - Default::default() + let scope_parser = ScopeParser::new(); + Self { scope_parser } + } + + pub fn symbols() -> Self { + let scope_parser = ScopeParser::symbols(); + Self { scope_parser } } } @@ -22,34 +30,18 @@ impl Parser<&str> for ModuleParser { .ok_or(Error::Message("No module found".into()))?; self.parse(WithSource::new(input, module)) } - fn parse_symbols(&self, input: &str) -> Result { - let module = parse(input, Mode::Module, "") - .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? - .module() - .ok_or(Error::Message("No module found".into()))?; - self.parse_symbols(WithSource::new(input, module)) - } } impl Parser> for ModuleParser { type Output = Module; fn parse(&self, input: WithSource) -> Result { - let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; + let scope = self.scope_parser.parse(input.sub(&input.ast.body))?; let constants = scope.constants; let types = scope.types; let functions = scope.functions; let interfaces = scope.interfaces; Ok(Module { constants, functions, types, interfaces, ..Default::default() }) } - - fn parse_symbols(&self, input: WithSource) -> Result { - let scope = ScopeParser::new().parse_symbols(input.sub(&input.ast.body))?; - let constants = scope.constants; - let types = scope.types; - let functions = scope.functions; - let interfaces = scope.interfaces; - Ok(Module { constants, types, functions, interfaces, ..Default::default() }) - } } struct Directory<'a>(pub &'a std::path::Path); @@ -63,21 +55,11 @@ impl Parser> for ModuleParser { module.identifier = self.parse_identifier(input)?; Ok(module) } - - fn parse_symbols(&self, File(input): File<'_>) -> Result { - let content = std::fs::read_to_string(input)?; - let mut module = self.parse_symbols(content.as_str())?; - module.identifier = self.parse_identifier(input)?; - Ok(module) - } } impl Parser> for ModuleParser { type Output = Module; - fn parse(&self, input: Directory<'_>) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, Directory(input): Directory<'_>) -> Result { + fn parse(&self, Directory(input): Directory<'_>) -> Result { let identifier = self.parse_identifier(input)?; let mut module = Module { identifier, .. Default::default() }; let mut modules: Vec = Vec::new(); @@ -90,7 +72,7 @@ impl Parser> for ModuleParser { .map(String::from) .unwrap_or_default(); if extension == "py" || path.is_dir() { - if let Ok(module) = self.parse_symbols(path.as_path()) { + if let Ok(module) = self.parse(path.as_path()) { if let Some(existing) = modules .iter_mut() .find(|existing| existing.identifier == module.identifier) @@ -119,13 +101,10 @@ impl Parser> for ModuleParser { impl Parser<&std::path::Path> for ModuleParser { type Output = Module; fn parse(&self, input: &std::path::Path) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: &std::path::Path) -> Result { if input.is_dir() { - self.parse_symbols(Directory(input)) + self.parse(Directory(input)) } else { - self.parse_symbols(File(input)).map_err(|error| Error::Message(format!("Failed to read {}. Cause: {:?}", input.display(), error))) + self.parse(File(input)).map_err(|error| Error::Message(format!("Failed to read {}. Cause: {:?}", input.display(), error))) } } } diff --git a/ecosystem/python/parser/src/scope/mod.rs b/ecosystem/python/parser/src/scope/mod.rs index bf7f2b74..e766369e 100644 --- a/ecosystem/python/parser/src/scope/mod.rs +++ b/ecosystem/python/parser/src/scope/mod.rs @@ -1,28 +1,43 @@ +mod scope_type; + use rustpython_parser::ast::{Arguments, Expr, Stmt}; -use ligen::ir::{Identifier, Interface, Constant, Function, Method, TypeDefinition, Structure}; -use crate::identifier::IdentifierParser; +use ligen::ir::{Interface, Constant, Function, Method, TypeDefinition}; use crate::prelude::*; use crate::interface::InterfaceParser; -mod scope_type; - pub use scope_type::*; +use crate::constant::ConstantParser; +use crate::function::FunctionParser; +use crate::function::method::MethodParser; +use crate::types::type_definition::TypeDefinitionParser; #[derive(Default)] -pub struct ScopeParser; +pub struct ScopeParser { + function_parser: FunctionParser, + method_parser: MethodParser, + interface_parser: InterfaceParser, + type_definition_parser: TypeDefinitionParser, + constant_parser: ConstantParser +} impl ScopeParser { pub fn new() -> Self { Default::default() } + + pub fn symbols() -> Self { + let function_parser = FunctionParser::symbols(); + let method_parser = MethodParser::symbols(); + let interface_parser = InterfaceParser::symbols(); + let type_definition_parser = TypeDefinitionParser::symbols(); + let constant_parser = ConstantParser::symbols(); + Self { function_parser, method_parser, interface_parser, type_definition_parser, constant_parser } + } } impl Parser> for ScopeParser { type Output = Scope; fn parse(&self, input: WithSource<&[Stmt]>) -> Result { - self.parse_symbols(input) - } - fn parse_symbols(&self, input: WithSource<&[Stmt]>) -> Result { let constants = self.parse_constants(&input)?; let types = self.parse_types(&input)?; let functions = self.parse_functions(&input)?; @@ -95,15 +110,14 @@ impl ScopeParser { if self.is_static_method(statements.sub(statement)) { match statement { Stmt::FunctionDef(function) => { - if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - functions.push(Function { identifier, ..Default::default() }) + if let Ok(function) = self.function_parser.parse(statements.sub(function.clone())) { + functions.push(function) } }, Stmt::AsyncFunctionDef(function) => { - if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - functions.push(Function { identifier, ..Default::default() }) + if let Ok(function) = self.function_parser.parse(statements.sub(function.clone())) { + functions.push(function) } - }, _ => (), } @@ -118,13 +132,13 @@ impl ScopeParser { if !self.is_static_method(statements.sub(statement)) { match statement { Stmt::FunctionDef(function) => { - if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - methods.push(Method { identifier, ..Default::default() }) + if let Ok(function) = self.method_parser.parse(statements.sub(function.clone())) { + methods.push(function) } }, Stmt::AsyncFunctionDef(function) => { - if let Ok(identifier) = IdentifierParser::new().parse(function.name.as_str()) { - methods.push(Method { identifier, ..Default::default() }) + if let Ok(function) = self.method_parser.parse(statements.sub(function.clone())) { + methods.push(function) } }, _ => (), @@ -138,8 +152,8 @@ impl ScopeParser { let mut types = Vec::new(); for statement in statements.ast { if let Stmt::ClassDef(class) = statement { - if let Ok(identifier) = IdentifierParser::new().parse(class.name.as_str()) { - types.push(Structure { identifier, .. Default::default() }.into()) + if let Ok(type_definition) = self.type_definition_parser.parse(statements.sub(class.clone())) { + types.push(type_definition) } } } @@ -150,7 +164,7 @@ impl ScopeParser { let mut interfaces = Vec::new(); for statement in statements.ast { if let Stmt::ClassDef(class) = statement { - if let Ok(interface) = InterfaceParser::new().parse(WithSource::new(&statements.source, class)) { + if let Ok(interface) = self.interface_parser.parse(WithSource::new(&statements.source, class)) { interfaces.push(interface) } } @@ -158,35 +172,23 @@ impl ScopeParser { Ok(interfaces) } - fn is_constant(&self, identifier: &Identifier) -> bool { - identifier.name.to_uppercase() == identifier.name - } - fn parse_constants(&self, statements: &WithSource<&[Stmt]>) -> Result> { let mut constants = Vec::new(); for statement in statements.ast { match statement { Stmt::Assign(assign) => { - for target in &assign.targets { - if let Ok(identifier) = self.parse_expr(target) { - if self.is_constant(&identifier) { - constants.push(Constant { identifier, .. Default::default() }) - } - } + if let Ok(more_constants) = self.constant_parser.parse(assign) { + constants.extend(more_constants) } }, Stmt::AnnAssign(assign) => { - if let Ok(identifier) = self.parse_expr(&assign.target) { - if self.is_constant(&identifier) { - constants.push(Constant { identifier, .. Default::default() }) - } + if let Ok(constant) = self.constant_parser.parse(assign) { + constants.push(constant) } }, Stmt::AugAssign(assign) => { - if let Ok(identifier) = self.parse_expr(&assign.target) { - if self.is_constant(&identifier) { - constants.push(Constant { identifier, .. Default::default() }) - } + if let Ok(constant) = self.constant_parser.parse(assign) { + constants.push(constant) } }, _ => () @@ -194,14 +196,4 @@ impl ScopeParser { } Ok(constants) } - - fn parse_expr(&self, expr: &Expr) -> Result { - let identifier = expr - .as_name_expr() - .ok_or(Error::Message("Expected identifier".into()))? - .id - .as_str(); - let identifier = IdentifierParser::new().parse(identifier)?; - Ok(identifier) - } } \ No newline at end of file diff --git a/ecosystem/python/parser/src/types/mod.rs b/ecosystem/python/parser/src/types/mod.rs index 3e91048b..a912e752 100644 --- a/ecosystem/python/parser/src/types/mod.rs +++ b/ecosystem/python/parser/src/types/mod.rs @@ -1 +1,2 @@ -pub mod type_; \ No newline at end of file +pub mod type_; +pub mod type_definition; \ No newline at end of file diff --git a/ecosystem/python/parser/src/types/type_definition.rs b/ecosystem/python/parser/src/types/type_definition.rs new file mode 100644 index 00000000..cd5c0eb3 --- /dev/null +++ b/ecosystem/python/parser/src/types/type_definition.rs @@ -0,0 +1,26 @@ +use rustpython_parser::ast::StmtClassDef; +use ligen::ir::{TypeDefinition, Structure}; +use crate::identifier::IdentifierParser; +use crate::prelude::*; + +#[derive(Default)] +pub struct TypeDefinitionParser; + +impl TypeDefinitionParser { + pub fn new() -> Self { + Default::default() + } + + pub fn symbols() -> Self { + Self + } +} + +impl Parser> for TypeDefinitionParser { + type Output = TypeDefinition; + fn parse(&self, input: WithSource) -> Result { + let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; + let structure = Structure { identifier, ..Default::default() }; + Ok(structure.into()) + } +} \ No newline at end of file diff --git a/ecosystem/rust/parser/src/function/method.rs b/ecosystem/rust/parser/src/function/method.rs index ceebbedd..cff6ff27 100644 --- a/ecosystem/rust/parser/src/function/method.rs +++ b/ecosystem/rust/parser/src/function/method.rs @@ -1,4 +1,4 @@ -use ligen::ir::{Mutability, Path}; +use ligen::ir::Mutability; use crate::prelude::*; use ligen::ir::{Attributes, Method, Parameter, Type}; @@ -40,11 +40,7 @@ impl Parser for MethodParser { Some(TypeParser.parse(*y)?) } }; - // FIXME: Hardcoded. - let path = Path::default(); - let owner = Type::Composite(path, Default::default()); Ok(Self::Output { - owner, mutability, attributes: Attributes { attributes: method diff --git a/ligen/ir/src/function/method.rs b/ligen/ir/src/function/method.rs index d290641a..f00744ea 100644 --- a/ligen/ir/src/function/method.rs +++ b/ligen/ir/src/function/method.rs @@ -6,8 +6,6 @@ use crate::{Synchrony, Attributes, Mutability, Parameter, Type, Visibility, Iden pub struct Method { /// Attributes field. pub attributes: Attributes, - /// The owner of the method. - pub owner: Type, /// The owner mutability. pub mutability: Mutability, /// Visibility field. diff --git a/ligen/parsing/src/parser/mod.rs b/ligen/parsing/src/parser/mod.rs index 8a875729..a8878cfe 100644 --- a/ligen/parsing/src/parser/mod.rs +++ b/ligen/parsing/src/parser/mod.rs @@ -1,11 +1,13 @@ pub mod universal; -use ligen_common::{Error, Result}; +use ligen_common::Result; pub trait Parser { type Output; fn parse(&self, input: Input) -> Result; - fn parse_symbols(&self, _input: Input) -> Result { - Err(Error::Message("Not implemented".to_string())) - } -} \ No newline at end of file +} + +pub trait DynamicParser { + type Output; + fn get_parser(&self) -> &dyn Parser; +} diff --git a/tools/editor/src/gui/ui/layout/editor/ir/function/method.rs b/tools/editor/src/gui/ui/layout/editor/ir/function/method.rs index 2ab9a159..0771c240 100644 --- a/tools/editor/src/gui/ui/layout/editor/ir/function/method.rs +++ b/tools/editor/src/gui/ui/layout/editor/ir/function/method.rs @@ -13,7 +13,6 @@ impl Method { pub fn show(&mut self, ui: &mut egui::Ui, method: &mut ligen_ir::Method) { ui.horizontal_top(|ui| { - Type::new().set_enabled(false).show(ui, &mut method.owner); Visibility::new().show(ui, &mut method.visibility); Synchrony::new().show(ui, &mut method.synchrony); Identifier::new().show(ui, &mut method.identifier); diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs index 18d1ac61..739191b9 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs @@ -17,7 +17,7 @@ impl MenuButton for EditorMenuButton { if let Some(entry) = entry { stacker::grow(1024 * 1024 * 10, || { - let module = ModuleParser::new().parse_symbols(entry.as_path()).unwrap(); + let module = ModuleParser::symbols().parse(entry.as_path()).unwrap(); panes.new_pane(Box::new(Editor::new(module))); }); } From f677f97e4b39ff1556a7233be0f0aef6e7bf5fe4 Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 11:16:37 -0300 Subject: [PATCH 06/11] Keeping track of parser instances --- ecosystem/python/parser/src/constant.rs | 4 +- .../python/parser/src/function/full_parser.rs | 82 +++++++++++++ .../python/parser/src/function/method.rs | 6 +- ecosystem/python/parser/src/function/mod.rs | 109 +++++++----------- .../parser/src/function/symbol_parser.rs | 40 +++++++ ecosystem/python/parser/src/interface.rs | 12 +- ecosystem/python/parser/src/module/mod.rs | 4 +- ecosystem/python/parser/src/scope/mod.rs | 21 ++-- .../parser/src/types/type_definition.rs | 4 +- ligen/parsing/src/parser/mod.rs | 5 - 10 files changed, 191 insertions(+), 96 deletions(-) create mode 100644 ecosystem/python/parser/src/function/full_parser.rs create mode 100644 ecosystem/python/parser/src/function/symbol_parser.rs diff --git a/ecosystem/python/parser/src/constant.rs b/ecosystem/python/parser/src/constant.rs index 48e7c45e..63c5f720 100644 --- a/ecosystem/python/parser/src/constant.rs +++ b/ecosystem/python/parser/src/constant.rs @@ -7,11 +7,11 @@ use crate::prelude::*; pub struct ConstantParser; impl ConstantParser { - pub fn new() -> Self { + pub fn full() -> Self { Self::default() } - pub fn symbols() -> Self { + pub fn symbol() -> Self { Self } } diff --git a/ecosystem/python/parser/src/function/full_parser.rs b/ecosystem/python/parser/src/function/full_parser.rs new file mode 100644 index 00000000..17b58d01 --- /dev/null +++ b/ecosystem/python/parser/src/function/full_parser.rs @@ -0,0 +1,82 @@ +use crate::prelude::*; +use rustpython_parser::ast::{Arguments, Expr, Ranged, Stmt, StmtAsyncFunctionDef, StmtFunctionDef}; +use ligen::ir::{Function, Synchrony, Visibility, Parameter, Type, Attributes}; +use crate::function::DynamicParser; +use crate::function::parameter::ParameterParser; +use crate::identifier::IdentifierParser; +use crate::macro_attributes::attributes::AttributesParser; +use crate::types::type_::TypeParser; + + +#[derive(Default)] +pub struct FullParser; + +impl DynamicParser<'_> for FullParser {} + +impl Parser<&str> for FullParser { + type Output = Function; + fn parse(&self, input: &str) -> Result { + let statement = Stmt::parse(input, "") + .map_err(|error| Error::Message(format!("Failed to parse statement: {}", error)))?; + match statement { + Stmt::FunctionDef(function) => self.parse(WithSource::new(input, function)), + Stmt::AsyncFunctionDef(function) => self.parse(WithSource::new(input, function)), + _ => Err(Error::Message("No function found".into())) + } + } +} + +impl Parser> for FullParser { + type Output = Function; + fn parse(&self, input: WithSource) -> Result { + let attributes = self.parse_attributes(input.sub(input.ast.decorator_list.clone()))?; + let visibility = Visibility::Public; + let synchrony = Synchrony::Synchronous; + let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; + let inputs = self.parse_inputs(*input.ast.args)?; + let output = self.parse_output(input.ast.returns)?; + + Ok(Self::Output { attributes, visibility, synchrony, identifier, inputs, output }) + } +} + +impl Parser> for FullParser { + type Output = Function; + fn parse(&self, input: WithSource) -> Result { + let source = input.source; + let input = input.ast; + let attributes = self.parse_attributes(WithSource::new(source, input.decorator_list))?; + let visibility = Visibility::Public; + let synchrony = Synchrony::Asynchronous; + let identifier = IdentifierParser::new().parse(input.name.as_str())?; + let inputs = self.parse_inputs(*input.args)?; + let output = self.parse_output(input.returns)?; + Ok(Self::Output { attributes, visibility, synchrony, identifier, inputs, output }) + } +} + +impl FullParser { + fn parse_attributes(&self, attributes: WithSource>) -> Result { + let source = if attributes.ast.is_empty() { + Default::default() + } else { + attributes.source[attributes.ast.first().unwrap().start().to_usize()..attributes.ast.last().unwrap().end().to_usize()].to_string() + }; + AttributesParser::default().parse(source) + } + fn parse_inputs(&self, args: Arguments) -> Result> { + let mut parameters = Vec::new(); + for arg in args.args { + parameters.push(ParameterParser.parse(arg)?); + } + Ok(parameters) + } + + fn parse_output(&self, output: Option>) -> Result> { + if let Some(expr) = output.and_then(|expr| expr.name_expr()) { + Ok(Some(TypeParser.parse(expr)?)) + } else { + Ok(None) + } + } +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/function/method.rs b/ecosystem/python/parser/src/function/method.rs index 1e8dd839..905873ba 100644 --- a/ecosystem/python/parser/src/function/method.rs +++ b/ecosystem/python/parser/src/function/method.rs @@ -9,12 +9,12 @@ pub struct MethodParser { } impl MethodParser { - pub fn new() -> Self { + pub fn full() -> Self { Default::default() } - pub fn symbols() -> Self { - let function_parser = FunctionParser::symbols(); + pub fn symbol() -> Self { + let function_parser = FunctionParser::symbol(); Self { function_parser } } } diff --git a/ecosystem/python/parser/src/function/mod.rs b/ecosystem/python/parser/src/function/mod.rs index f671fff9..540d4066 100644 --- a/ecosystem/python/parser/src/function/mod.rs +++ b/ecosystem/python/parser/src/function/mod.rs @@ -1,92 +1,61 @@ +use rustpython_parser::ast::{StmtAsyncFunctionDef, StmtFunctionDef}; +use ligen::ir::Function; +use crate::function::full_parser::FullParser; +use crate::function::symbol_parser::SymbolParser; +use crate::prelude::*; + pub mod parameter; pub mod method; -use crate::prelude::*; -use rustpython_parser::ast::{Arguments, Expr, Ranged, Stmt, StmtAsyncFunctionDef, StmtFunctionDef}; -use ligen::ir::{Function, Synchrony, Visibility, Parameter, Type, Attributes}; -use crate::function::parameter::ParameterParser; -use crate::identifier::IdentifierParser; -use crate::macro_attributes::attributes::AttributesParser; -use crate::types::type_::TypeParser; +mod symbol_parser; +mod full_parser; -#[derive(Default)] -pub struct FunctionParser; - -impl FunctionParser { - pub fn new() -> Self { - Self::default() - } +trait DynamicParser<'a>: + Parser, Output = Function> ++ Parser, Output = Function> ++ Parser<&'a str, Output = Function> +{} - pub fn symbols() -> Self { - Self::default() - } +pub struct FunctionParser { + parser: Box DynamicParser<'a>> } -impl Parser<&str> for FunctionParser { - type Output = Function; - fn parse(&self, input: &str) -> Result { - let statement = Stmt::parse(input, "") - .map_err(|error| Error::Message(format!("Failed to parse statement: {}", error)))?; - match statement { - Stmt::FunctionDef(function) => self.parse(WithSource::new(input, function)), - Stmt::AsyncFunctionDef(function) => self.parse(WithSource::new(input, function)), - _ => Err(Error::Message("No function found".into())) - } +impl Default for FunctionParser { + fn default() -> Self { + let parser = Box::new(FullParser::default()); + Self { parser } } } impl Parser> for FunctionParser { type Output = Function; fn parse(&self, input: WithSource) -> Result { - let attributes = self.parse_attributes(input.sub(input.ast.decorator_list.clone()))?; - let visibility = Visibility::Public; - let synchrony = Synchrony::Synchronous; - let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; - let inputs = self.parse_inputs(*input.ast.args)?; - let output = self.parse_output(input.ast.returns)?; - - Ok(Self::Output { attributes, visibility, synchrony, identifier, inputs, output }) + self.parser.parse(input) } } impl Parser> for FunctionParser { type Output = Function; fn parse(&self, input: WithSource) -> Result { - let source = input.source; - let input = input.ast; - let attributes = self.parse_attributes(WithSource::new(source, input.decorator_list))?; - let visibility = Visibility::Public; - let synchrony = Synchrony::Asynchronous; - let identifier = IdentifierParser::new().parse(input.name.as_str())?; - let inputs = self.parse_inputs(*input.args)?; - let output = self.parse_output(input.returns)?; - Ok(Self::Output { attributes, visibility, synchrony, identifier, inputs, output }) + self.parser.parse(input) } } -impl FunctionParser { - fn parse_attributes(&self, attributes: WithSource>) -> Result { - let source = if attributes.ast.is_empty() { - Default::default() - } else { - attributes.source[attributes.ast.first().unwrap().start().to_usize()..attributes.ast.last().unwrap().end().to_usize()].to_string() - }; - AttributesParser::default().parse(source) +impl Parser<&str> for FunctionParser { + type Output = Function; + fn parse(&self, input: &str) -> Result { + self.parser.parse(input) } - fn parse_inputs(&self, args: Arguments) -> Result> { - let mut parameters = Vec::new(); - for arg in args.args { - parameters.push(ParameterParser.parse(arg)?); - } - Ok(parameters) +} + +impl FunctionParser { + pub fn full() -> Self { + Self::default() } - fn parse_output(&self, output: Option>) -> Result> { - if let Some(expr) = output.and_then(|expr| expr.name_expr()) { - Ok(Some(TypeParser.parse(expr)?)) - } else { - Ok(None) - } + pub fn symbol() -> Self { + let parser = Box::new(SymbolParser::default()); + Self { parser } } } @@ -99,27 +68,27 @@ mod test { #[test] fn function() -> Result<()> { - assert_eq(FunctionParser, mock::function(), "def test(): pass") + assert_eq(FunctionParser::default(), mock::function(), "def test(): pass") } #[test] fn function_async() -> Result<()> { - assert_eq(FunctionParser, mock::function_async(), "async def test(): pass") + assert_eq(FunctionParser::default(), mock::function_async(), "async def test(): pass") } #[test] fn function_input() -> Result<()> { - assert_eq(FunctionParser, mock::function_input(), "def test(a: int, b: int): pass") + assert_eq(FunctionParser::default(), mock::function_input(), "def test(a: int, b: int): pass") } #[test] fn function_input_output() -> Result<()> { - assert_eq(FunctionParser, mock::function_input_output(), "def test(a: int, b: int) -> int: pass") + assert_eq(FunctionParser::default(), mock::function_input_output(), "def test(a: int, b: int) -> int: pass") } #[test] fn function_attribute() -> Result<()> { - assert_eq(FunctionParser, mock::function_attribute(), "@test(a = 'b')\ndef test(): pass")?; - assert_eq(FunctionParser, mock::function_attribute(), "@test(a = \"b\")\ndef test(): pass") + assert_eq(FunctionParser::default(), mock::function_attribute(), "@test(a = 'b')\ndef test(): pass")?; + assert_eq(FunctionParser::default(), mock::function_attribute(), "@test(a = \"b\")\ndef test(): pass") } } \ No newline at end of file diff --git a/ecosystem/python/parser/src/function/symbol_parser.rs b/ecosystem/python/parser/src/function/symbol_parser.rs new file mode 100644 index 00000000..5d709245 --- /dev/null +++ b/ecosystem/python/parser/src/function/symbol_parser.rs @@ -0,0 +1,40 @@ +use crate::prelude::*; +use rustpython_parser::ast::{Stmt, StmtAsyncFunctionDef, StmtFunctionDef}; +use ligen::ir::Function; +use crate::function::DynamicParser; +use crate::identifier::IdentifierParser; + + +#[derive(Default)] +pub struct SymbolParser; + +impl DynamicParser<'_> for SymbolParser {} + +impl Parser> for SymbolParser { + type Output = Function; + fn parse(&self, input: WithSource) -> Result { + let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; + Ok(Self::Output { identifier, ..Default::default() }) + } +} + +impl Parser> for SymbolParser { + type Output = Function; + fn parse(&self, input: WithSource) -> Result { + let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; + Ok(Self::Output { identifier, ..Default::default() }) + } +} + +impl Parser<&str> for SymbolParser { + type Output = Function; + fn parse(&self, input: &str) -> Result { + let statement = Stmt::parse(input, "") + .map_err(|error| Error::Message(format!("Failed to parse statement: {}", error)))?; + match statement { + Stmt::FunctionDef(function) => self.parse(WithSource::new(input, function)), + Stmt::AsyncFunctionDef(function) => self.parse(WithSource::new(input, function)), + _ => Err(Error::Message("No function found".into())) + } + } +} diff --git a/ecosystem/python/parser/src/interface.rs b/ecosystem/python/parser/src/interface.rs index 7a427c54..d395f384 100644 --- a/ecosystem/python/parser/src/interface.rs +++ b/ecosystem/python/parser/src/interface.rs @@ -5,14 +5,18 @@ use crate::identifier::IdentifierParser; use crate::scope::ScopeParser; #[derive(Default)] -pub struct InterfaceParser; +pub struct InterfaceParser { + // scope_parser: Box +} impl InterfaceParser { - pub fn new() -> Self { + pub fn full() -> Self { Default::default() } - pub fn symbols() -> Self { + pub fn symbol() -> Self { + // let scope_parser = Box::new(ScopeParser::symbol()); + // Self { scope_parser } Default::default() } } @@ -20,7 +24,7 @@ impl InterfaceParser { impl Parser> for InterfaceParser { type Output = Interface; fn parse(&self, input: WithSource<&StmtClassDef>) -> Result { - let scope = ScopeParser::new().parse(input.sub(&input.ast.body))?; + let scope = ScopeParser::symbol().parse(input.sub(&input.ast.body))?; let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; let constants = scope.constants; let functions = scope.functions; diff --git a/ecosystem/python/parser/src/module/mod.rs b/ecosystem/python/parser/src/module/mod.rs index c2169931..63a15ad5 100644 --- a/ecosystem/python/parser/src/module/mod.rs +++ b/ecosystem/python/parser/src/module/mod.rs @@ -11,12 +11,12 @@ pub struct ModuleParser { impl ModuleParser { pub fn new() -> Self { - let scope_parser = ScopeParser::new(); + let scope_parser = ScopeParser::full(); Self { scope_parser } } pub fn symbols() -> Self { - let scope_parser = ScopeParser::symbols(); + let scope_parser = ScopeParser::symbol(); Self { scope_parser } } } diff --git a/ecosystem/python/parser/src/scope/mod.rs b/ecosystem/python/parser/src/scope/mod.rs index e766369e..70ef7275 100644 --- a/ecosystem/python/parser/src/scope/mod.rs +++ b/ecosystem/python/parser/src/scope/mod.rs @@ -21,16 +21,21 @@ pub struct ScopeParser { } impl ScopeParser { - pub fn new() -> Self { - Default::default() + pub fn full() -> Self { + let function_parser = FunctionParser::full(); + let method_parser = MethodParser::full(); + let type_definition_parser = TypeDefinitionParser::full(); + let constant_parser = ConstantParser::full(); + let interface_parser = InterfaceParser::full(); + Self { function_parser, method_parser, interface_parser, type_definition_parser, constant_parser } } - pub fn symbols() -> Self { - let function_parser = FunctionParser::symbols(); - let method_parser = MethodParser::symbols(); - let interface_parser = InterfaceParser::symbols(); - let type_definition_parser = TypeDefinitionParser::symbols(); - let constant_parser = ConstantParser::symbols(); + pub fn symbol() -> Self { + let function_parser = FunctionParser::symbol(); + let method_parser = MethodParser::symbol(); + let interface_parser = InterfaceParser::symbol(); + let type_definition_parser = TypeDefinitionParser::symbol(); + let constant_parser = ConstantParser::symbol(); Self { function_parser, method_parser, interface_parser, type_definition_parser, constant_parser } } } diff --git a/ecosystem/python/parser/src/types/type_definition.rs b/ecosystem/python/parser/src/types/type_definition.rs index cd5c0eb3..cde2041e 100644 --- a/ecosystem/python/parser/src/types/type_definition.rs +++ b/ecosystem/python/parser/src/types/type_definition.rs @@ -7,11 +7,11 @@ use crate::prelude::*; pub struct TypeDefinitionParser; impl TypeDefinitionParser { - pub fn new() -> Self { + pub fn full() -> Self { Default::default() } - pub fn symbols() -> Self { + pub fn symbol() -> Self { Self } } diff --git a/ligen/parsing/src/parser/mod.rs b/ligen/parsing/src/parser/mod.rs index a8878cfe..f8b88149 100644 --- a/ligen/parsing/src/parser/mod.rs +++ b/ligen/parsing/src/parser/mod.rs @@ -6,8 +6,3 @@ pub trait Parser { type Output; fn parse(&self, input: Input) -> Result; } - -pub trait DynamicParser { - type Output; - fn get_parser(&self) -> &dyn Parser; -} From a356e45c9a0eb3cc204ecd3d600019289309d87e Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 13:30:54 -0300 Subject: [PATCH 07/11] Dynamic parser helper macro --- .../python/parser/src/constant/full_parser.rs | 0 .../src/{constant.rs => constant/mod.rs} | 0 .../parser/src/constant/symbol_parser.rs | 61 ++++++++++++++++++ ecosystem/python/parser/src/function/mod.rs | 57 +++-------------- ecosystem/python/parser/src/interface.rs | 25 ++------ ecosystem/python/parser/src/lib.rs | 3 +- ecosystem/python/parser/src/module/mod.rs | 55 +++++----------- ecosystem/python/parser/src/parser.rs | 29 +++++++++ ecosystem/python/parser/src/scope/mod.rs | 51 +++------------ ligen/parsing/src/lib.rs | 2 +- ligen/parsing/src/parser/dynamic_parser.rs | 64 +++++++++++++++++++ ligen/parsing/src/parser/mod.rs | 1 + .../src/parser/universal/identifier.rs | 13 ++++ .../ui/layout/editor/symbols/menu_button.rs | 3 +- 14 files changed, 209 insertions(+), 155 deletions(-) create mode 100644 ecosystem/python/parser/src/constant/full_parser.rs rename ecosystem/python/parser/src/{constant.rs => constant/mod.rs} (100%) create mode 100644 ecosystem/python/parser/src/constant/symbol_parser.rs create mode 100644 ecosystem/python/parser/src/parser.rs create mode 100644 ligen/parsing/src/parser/dynamic_parser.rs diff --git a/ecosystem/python/parser/src/constant/full_parser.rs b/ecosystem/python/parser/src/constant/full_parser.rs new file mode 100644 index 00000000..e69de29b diff --git a/ecosystem/python/parser/src/constant.rs b/ecosystem/python/parser/src/constant/mod.rs similarity index 100% rename from ecosystem/python/parser/src/constant.rs rename to ecosystem/python/parser/src/constant/mod.rs diff --git a/ecosystem/python/parser/src/constant/symbol_parser.rs b/ecosystem/python/parser/src/constant/symbol_parser.rs new file mode 100644 index 00000000..60964192 --- /dev/null +++ b/ecosystem/python/parser/src/constant/symbol_parser.rs @@ -0,0 +1,61 @@ +use rustpython_parser::ast::{Expr, StmtAnnAssign, StmtAssign, StmtAugAssign}; +use ligen::ir::{Constant, Identifier}; +use crate::identifier::IdentifierParser; +use crate::prelude::*; + +use super::DynamicParser; + +impl<'a> DynamicParser<'a> for SymbolParser {} + +#[derive(Default)] +pub struct SymbolParser; + +impl Parser<&StmtAnnAssign> for SymbolParser { + type Output = Constant; + fn parse(&self, input: &StmtAnnAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&StmtAugAssign> for SymbolParser { + type Output = Constant; + fn parse(&self, input: &StmtAugAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&Expr> for SymbolParser { + type Output = Constant; + fn parse(&self, expr: &Expr) -> Result { + let identifier = expr + .as_name_expr() + .ok_or(Error::Message("Expected identifier".into()))? + .id + .as_str(); + let identifier = IdentifierParser::new().parse(identifier)?; + if self.is_constant(&identifier) { + Ok(Constant { identifier, ..Default::default() }) + } else { + Err(Error::Message("Expected constant".into())) + } + } +} + +impl Parser<&StmtAssign> for SymbolParser { + type Output = Vec; + fn parse(&self, input: &StmtAssign) -> Result { + let mut constants = Vec::new(); + for target in &input.targets { + if let Ok(constant) = self.parse(target) { + constants.push(constant); + } + } + Ok(constants) + } +} + +impl SymbolParser { + fn is_constant(&self, identifier: &Identifier) -> bool { + identifier.name.to_uppercase() == identifier.name + } +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/function/mod.rs b/ecosystem/python/parser/src/function/mod.rs index 540d4066..adef82a2 100644 --- a/ecosystem/python/parser/src/function/mod.rs +++ b/ecosystem/python/parser/src/function/mod.rs @@ -1,7 +1,6 @@ +use ligen::parsing::dynamic_parser; use rustpython_parser::ast::{StmtAsyncFunctionDef, StmtFunctionDef}; use ligen::ir::Function; -use crate::function::full_parser::FullParser; -use crate::function::symbol_parser::SymbolParser; use crate::prelude::*; pub mod parameter; @@ -10,53 +9,13 @@ pub mod method; mod symbol_parser; mod full_parser; -trait DynamicParser<'a>: - Parser, Output = Function> -+ Parser, Output = Function> -+ Parser<&'a str, Output = Function> -{} - -pub struct FunctionParser { - parser: Box DynamicParser<'a>> -} - -impl Default for FunctionParser { - fn default() -> Self { - let parser = Box::new(FullParser::default()); - Self { parser } - } -} - -impl Parser> for FunctionParser { - type Output = Function; - fn parse(&self, input: WithSource) -> Result { - self.parser.parse(input) - } -} - -impl Parser> for FunctionParser { - type Output = Function; - fn parse(&self, input: WithSource) -> Result { - self.parser.parse(input) - } -} - -impl Parser<&str> for FunctionParser { - type Output = Function; - fn parse(&self, input: &str) -> Result { - self.parser.parse(input) - } -} - -impl FunctionParser { - pub fn full() -> Self { - Self::default() - } - - pub fn symbol() -> Self { - let parser = Box::new(SymbolParser::default()); - Self { parser } - } +dynamic_parser!{ + FunctionParser, + full_parser::FullParser, + symbol_parser::SymbolParser, + Function, + WithSource, + WithSource } #[cfg(test)] diff --git a/ecosystem/python/parser/src/interface.rs b/ecosystem/python/parser/src/interface.rs index d395f384..f244f0de 100644 --- a/ecosystem/python/parser/src/interface.rs +++ b/ecosystem/python/parser/src/interface.rs @@ -1,30 +1,13 @@ use crate::prelude::*; -use rustpython_parser::ast::StmtClassDef; +use rustpython_parser::ast::{StmtClassDef}; use ligen::ir::Interface; use crate::identifier::IdentifierParser; -use crate::scope::ScopeParser; +use crate::parser::PythonParser; -#[derive(Default)] -pub struct InterfaceParser { - // scope_parser: Box -} - -impl InterfaceParser { - pub fn full() -> Self { - Default::default() - } - - pub fn symbol() -> Self { - // let scope_parser = Box::new(ScopeParser::symbol()); - // Self { scope_parser } - Default::default() - } -} - -impl Parser> for InterfaceParser { +impl Parser> for PythonParser { type Output = Interface; fn parse(&self, input: WithSource<&StmtClassDef>) -> Result { - let scope = ScopeParser::symbol().parse(input.sub(&input.ast.body))?; + let scope = self.parse(input.sub(input.ast.body.as_slice()))?; let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; let constants = scope.constants; let functions = scope.functions; diff --git a/ecosystem/python/parser/src/lib.rs b/ecosystem/python/parser/src/lib.rs index e4a574d5..63efbba6 100644 --- a/ecosystem/python/parser/src/lib.rs +++ b/ecosystem/python/parser/src/lib.rs @@ -7,4 +7,5 @@ pub mod types; pub mod literal; pub mod scope; pub mod interface; -pub mod constant; \ No newline at end of file +pub mod constant; +pub mod parser; \ No newline at end of file diff --git a/ecosystem/python/parser/src/module/mod.rs b/ecosystem/python/parser/src/module/mod.rs index 63a15ad5..23baeef0 100644 --- a/ecosystem/python/parser/src/module/mod.rs +++ b/ecosystem/python/parser/src/module/mod.rs @@ -1,41 +1,26 @@ use crate::prelude::*; -use ligen::ir::{Module, Identifier}; +use ligen::ir::Module; use rustpython_parser::ast::ModModule; -use crate::identifier::IdentifierParser; -use crate::scope::ScopeParser; +use crate::parser::PythonParser; #[derive(Default)] -pub struct ModuleParser { - scope_parser: ScopeParser, -} - -impl ModuleParser { - pub fn new() -> Self { - let scope_parser = ScopeParser::full(); - Self { scope_parser } - } - - pub fn symbols() -> Self { - let scope_parser = ScopeParser::symbol(); - Self { scope_parser } - } -} +pub struct ModuleParser; impl Parser<&str> for ModuleParser { - type Output = Module; + type Output = WithSource; fn parse(&self, input: &str) -> Result { let module = parse(input, Mode::Module, "") .map_err(|error| Error::Message(format!("Failed to parse module: {}", error)))? .module() .ok_or(Error::Message("No module found".into()))?; - self.parse(WithSource::new(input, module)) + Ok(WithSource::new(input, module)) } } -impl Parser> for ModuleParser { +impl Parser> for PythonParser { type Output = Module; fn parse(&self, input: WithSource) -> Result { - let scope = self.scope_parser.parse(input.sub(&input.ast.body))?; + let scope = self.parse(input.sub(input.ast.body.as_slice()))?; let constants = scope.constants; let types = scope.types; let functions = scope.functions; @@ -47,20 +32,21 @@ impl Parser> for ModuleParser { struct Directory<'a>(pub &'a std::path::Path); struct File<'a>(pub &'a std::path::Path); -impl Parser> for ModuleParser { +impl Parser> for PythonParser { type Output = Module; fn parse(&self, File(input): File<'_>) -> Result { let content = std::fs::read_to_string(input)?; - let mut module = self.parse(content.as_str())?; - module.identifier = self.parse_identifier(input)?; + let module = ModuleParser::default().parse(content.as_str())?; + let mut module = self.parse(module)?; + module.identifier = self.identifier_parser.parse(input)?; Ok(module) } } -impl Parser> for ModuleParser { +impl Parser> for PythonParser { type Output = Module; fn parse(&self, Directory(input): Directory<'_>) -> Result { - let identifier = self.parse_identifier(input)?; + let identifier = self.identifier_parser.parse(input)?; let mut module = Module { identifier, .. Default::default() }; let mut modules: Vec = Vec::new(); for entry in input.read_dir()? { @@ -98,7 +84,7 @@ impl Parser> for ModuleParser { } } -impl Parser<&std::path::Path> for ModuleParser { +impl Parser<&std::path::Path> for PythonParser { type Output = Module; fn parse(&self, input: &std::path::Path) -> Result { if input.is_dir() { @@ -107,15 +93,4 @@ impl Parser<&std::path::Path> for ModuleParser { self.parse(File(input)).map_err(|error| Error::Message(format!("Failed to read {}. Cause: {:?}", input.display(), error))) } } -} - -impl ModuleParser { - fn parse_identifier(&self, input: &std::path::Path) -> Result { - let identifier = input - .file_stem() - .ok_or(Error::Message(format!("Failed to parse file stem from path: {}", input.display())))? - .to_str() - .ok_or(Error::Message(format!("Failed to parse file stem to string: {}", input.display())))?; - IdentifierParser::new().parse(identifier) - } -} +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/parser.rs b/ecosystem/python/parser/src/parser.rs new file mode 100644 index 00000000..38650a0a --- /dev/null +++ b/ecosystem/python/parser/src/parser.rs @@ -0,0 +1,29 @@ +use crate::constant::ConstantParser; +use crate::function::FunctionParser; +use crate::function::method::MethodParser; +use crate::identifier::IdentifierParser; +use crate::types::type_definition::TypeDefinitionParser; + +#[derive(Default)] +pub struct PythonParser { + pub identifier_parser: IdentifierParser, + pub function_parser: FunctionParser, + pub method_parser: MethodParser, + pub type_definition_parser: TypeDefinitionParser, + pub constant_parser: ConstantParser +} + +impl PythonParser { + pub fn full() -> Self { + Default::default() + } + + pub fn symbol() -> Self { + let identifier_parser = IdentifierParser::new(); + let function_parser = FunctionParser::symbol(); + let method_parser = MethodParser::symbol(); + let type_definition_parser = TypeDefinitionParser::symbol(); + let constant_parser = ConstantParser::symbol(); + Self { identifier_parser, function_parser, method_parser, type_definition_parser, constant_parser } + } +} diff --git a/ecosystem/python/parser/src/scope/mod.rs b/ecosystem/python/parser/src/scope/mod.rs index 70ef7275..fb4a34d8 100644 --- a/ecosystem/python/parser/src/scope/mod.rs +++ b/ecosystem/python/parser/src/scope/mod.rs @@ -3,44 +3,11 @@ mod scope_type; use rustpython_parser::ast::{Arguments, Expr, Stmt}; use ligen::ir::{Interface, Constant, Function, Method, TypeDefinition}; use crate::prelude::*; -use crate::interface::InterfaceParser; pub use scope_type::*; -use crate::constant::ConstantParser; -use crate::function::FunctionParser; -use crate::function::method::MethodParser; -use crate::types::type_definition::TypeDefinitionParser; +use crate::parser::PythonParser; -#[derive(Default)] -pub struct ScopeParser { - function_parser: FunctionParser, - method_parser: MethodParser, - interface_parser: InterfaceParser, - type_definition_parser: TypeDefinitionParser, - constant_parser: ConstantParser -} - -impl ScopeParser { - pub fn full() -> Self { - let function_parser = FunctionParser::full(); - let method_parser = MethodParser::full(); - let type_definition_parser = TypeDefinitionParser::full(); - let constant_parser = ConstantParser::full(); - let interface_parser = InterfaceParser::full(); - Self { function_parser, method_parser, interface_parser, type_definition_parser, constant_parser } - } - - pub fn symbol() -> Self { - let function_parser = FunctionParser::symbol(); - let method_parser = MethodParser::symbol(); - let interface_parser = InterfaceParser::symbol(); - let type_definition_parser = TypeDefinitionParser::symbol(); - let constant_parser = ConstantParser::symbol(); - Self { function_parser, method_parser, interface_parser, type_definition_parser, constant_parser } - } -} - -impl Parser> for ScopeParser { +impl Parser> for PythonParser { type Output = Scope; fn parse(&self, input: WithSource<&[Stmt]>) -> Result { let constants = self.parse_constants(&input)?; @@ -57,19 +24,19 @@ impl Parser> for ScopeParser { } } -impl ScopeParser { +impl PythonParser { fn parse_sub_scopes(&self, statements: &WithSource<&[Stmt]>) -> Result> { let mut sub_scopes = Vec::new(); for statement in statements.ast { match statement { Stmt::If(ast) => { - sub_scopes.push(self.parse(statements.sub( &ast.body))?); - sub_scopes.push(self.parse(statements.sub(&ast.orelse))?); + sub_scopes.push(self.parse(statements.sub( ast.body.as_slice()))?); + sub_scopes.push(self.parse(statements.sub(ast.orelse.as_slice()))?); }, Stmt::Try(ast) => { - sub_scopes.push(self.parse(statements.sub(&ast.body))?); - sub_scopes.push(self.parse(statements.sub(&ast.orelse))?); - sub_scopes.push(self.parse(statements.sub(&ast.finalbody))?); + sub_scopes.push(self.parse(statements.sub(ast.body.as_slice()))?); + sub_scopes.push(self.parse(statements.sub(ast.orelse.as_slice()))?); + sub_scopes.push(self.parse(statements.sub(ast.finalbody.as_slice()))?); }, _ => () } @@ -169,7 +136,7 @@ impl ScopeParser { let mut interfaces = Vec::new(); for statement in statements.ast { if let Stmt::ClassDef(class) = statement { - if let Ok(interface) = self.interface_parser.parse(WithSource::new(&statements.source, class)) { + if let Ok(interface) = self.parse(WithSource::new(&statements.source, class)) { interfaces.push(interface) } } diff --git a/ligen/parsing/src/lib.rs b/ligen/parsing/src/lib.rs index dfeb59ad..af59a347 100644 --- a/ligen/parsing/src/lib.rs +++ b/ligen/parsing/src/lib.rs @@ -1,4 +1,4 @@ -mod prelude; +pub mod prelude; pub mod parser; pub mod assert; pub mod utils; diff --git a/ligen/parsing/src/parser/dynamic_parser.rs b/ligen/parsing/src/parser/dynamic_parser.rs new file mode 100644 index 00000000..7d72db21 --- /dev/null +++ b/ligen/parsing/src/parser/dynamic_parser.rs @@ -0,0 +1,64 @@ +#[macro_export] +macro_rules! dynamic_parser { + ($name:ident, $full_parser:path, $symbol_parser:path, $output:ty, $($first:ty, $($rest:ty),*)?) => { + use $crate::prelude::*; + use $crate::parser::Parser; + + trait DynamicParser<'a>: + $( + Parser<$first, Output = $output> + $(+ Parser<$rest, Output = $output>)* + + Parser<&'a str, Output = $output> + )? + {} + + pub struct $name { + parser: Box DynamicParser<'a>> + } + + impl $name { + pub fn full() -> Self { + let parser = Box::new(<$full_parser>::default()); + Self { parser } + } + + pub fn symbol() -> Self { + let parser = Box::new(<$symbol_parser>::default()); + Self { parser } + } + } + + impl Default for FunctionParser { + fn default() -> Self { + Self::full() + } + } + + impl Parser<&str> for $name { + type Output = $output; + fn parse(&self, input: &str) -> Result { + self.parser.parse(input) + } + } + + $( + impl Parser<$first> for $name { + type Output = $output; + fn parse(&self, input: $first) -> Result { + self.parser.parse(input) + } + } + + $( + impl Parser<$rest> for $name { + type Output = $output; + fn parse(&self, input: $rest) -> Result { + self.parser.parse(input) + } + } + )+ + )? + }; +} + +pub use dynamic_parser; \ No newline at end of file diff --git a/ligen/parsing/src/parser/mod.rs b/ligen/parsing/src/parser/mod.rs index f8b88149..52a14d50 100644 --- a/ligen/parsing/src/parser/mod.rs +++ b/ligen/parsing/src/parser/mod.rs @@ -1,3 +1,4 @@ +pub mod dynamic_parser; pub mod universal; use ligen_common::Result; diff --git a/ligen/parsing/src/parser/universal/identifier.rs b/ligen/parsing/src/parser/universal/identifier.rs index 027fb95f..2be918f2 100644 --- a/ligen/parsing/src/parser/universal/identifier.rs +++ b/ligen/parsing/src/parser/universal/identifier.rs @@ -28,6 +28,19 @@ impl Parser<&str> for IdentifierParser { } } +impl Parser<&std::path::Path> for IdentifierParser { + type Output = Identifier; + fn parse(&self, input: &std::path::Path) -> Result { + let identifier = input + .file_stem() + .ok_or(Error::Message(format!("Failed to parse file stem from path: {}", input.display())))? + .to_str() + .ok_or(Error::Message(format!("Failed to parse file stem to string: {}", input.display())))?; + self.parse(identifier) + + } +} + impl Parser for IdentifierParser { type Output = Identifier; fn parse(&self, ident: syn::Ident) -> Result { diff --git a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs index 739191b9..a62aea19 100644 --- a/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs +++ b/tools/editor/src/gui/ui/layout/editor/symbols/menu_button.rs @@ -1,5 +1,6 @@ use ligen_parsing::parser::Parser; use ligen_python_parser::module::ModuleParser; +use ligen_python_parser::parser::PythonParser; use crate::prelude::*; use crate::gui::ui::editor::symbols::Editor; use crate::gui::ui::menu::MenuButton; @@ -17,7 +18,7 @@ impl MenuButton for EditorMenuButton { if let Some(entry) = entry { stacker::grow(1024 * 1024 * 10, || { - let module = ModuleParser::symbols().parse(entry.as_path()).unwrap(); + let module = PythonParser::symbol().parse(entry.as_path()).unwrap(); panes.new_pane(Box::new(Editor::new(module))); }); } From b0d10e1768117d55118b0cbf7e2fb1f0c5f7d610 Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 15:26:07 -0300 Subject: [PATCH 08/11] Adding constraint rules for dynamic_parser --- ecosystem/python/parser/src/function/mod.rs | 3 +- ligen/parsing/src/parser/dynamic_parser.rs | 80 ++++++++++++--------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/ecosystem/python/parser/src/function/mod.rs b/ecosystem/python/parser/src/function/mod.rs index adef82a2..ea38f813 100644 --- a/ecosystem/python/parser/src/function/mod.rs +++ b/ecosystem/python/parser/src/function/mod.rs @@ -15,7 +15,8 @@ dynamic_parser!{ symbol_parser::SymbolParser, Function, WithSource, - WithSource + WithSource, + &str => &'a str } #[cfg(test)] diff --git a/ligen/parsing/src/parser/dynamic_parser.rs b/ligen/parsing/src/parser/dynamic_parser.rs index 7d72db21..10a783a3 100644 --- a/ligen/parsing/src/parser/dynamic_parser.rs +++ b/ligen/parsing/src/parser/dynamic_parser.rs @@ -1,16 +1,53 @@ +#[macro_export] +macro_rules! as_constraint { + ($typ:ty) => { + $typ + }; + ($typ:ty => $constraint:ty) => { + $constraint + }; +} + +#[macro_export] +macro_rules! trait_definition { + ($output:ty, $first:ty $(=> $first_constraint:ty)? $(, $rest:ty $(=> $rest_constraint:ty)?)+) => { + trait DynamicParser<'a>: + Parser<$crate::as_constraint!($first $(=> $first_constraint)?), Output = $output> + $(+ Parser<$crate::as_constraint!($rest $(=> $rest_constraint)?), Output = $output>)+ + {} + } +} + +#[macro_export] +macro_rules! trait_implementation { + ($name:ident, $output:ty, $first:ty $(=> $first_constraint:ty)? $(, $rest:ty $(=> $rest_constraint:ty)?)+) => { + impl Parser<$first> for $name { + type Output = $output; + fn parse(&self, input: $first) -> Result { + self.parser.parse(input) + } + } + + $( + impl Parser<$rest> for $name { + type Output = $output; + fn parse(&self, input: $rest) -> Result { + self.parser.parse(input) + } + } + )+ + + }; +} + #[macro_export] macro_rules! dynamic_parser { - ($name:ident, $full_parser:path, $symbol_parser:path, $output:ty, $($first:ty, $($rest:ty),*)?) => { + ($name:ident, $full_parser:path, $symbol_parser:path, $output:ty, $($input:tt)*) => { use $crate::prelude::*; use $crate::parser::Parser; - trait DynamicParser<'a>: - $( - Parser<$first, Output = $output> - $(+ Parser<$rest, Output = $output>)* - + Parser<&'a str, Output = $output> - )? - {} + $crate::trait_definition!($output, $($input)*); + $crate::trait_implementation!($name, $output, $($input)*); pub struct $name { parser: Box DynamicParser<'a>> @@ -33,32 +70,7 @@ macro_rules! dynamic_parser { Self::full() } } - - impl Parser<&str> for $name { - type Output = $output; - fn parse(&self, input: &str) -> Result { - self.parser.parse(input) - } - } - - $( - impl Parser<$first> for $name { - type Output = $output; - fn parse(&self, input: $first) -> Result { - self.parser.parse(input) - } - } - - $( - impl Parser<$rest> for $name { - type Output = $output; - fn parse(&self, input: $rest) -> Result { - self.parser.parse(input) - } - } - )+ - )? }; } -pub use dynamic_parser; \ No newline at end of file +pub use dynamic_parser; From cc9c90e04e759079eb0acbc6ab93bc9c9592cd0f Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 15:41:22 -0300 Subject: [PATCH 09/11] Generalizing dynamic parser output --- .../python/parser/src/constant/full_parser.rs | 61 ++++++++++++++ ecosystem/python/parser/src/constant/mod.rs | 82 ++++--------------- ecosystem/python/parser/src/function/mod.rs | 4 +- ligen/parsing/src/parser/dynamic_parser.rs | 26 ++++-- 4 files changed, 97 insertions(+), 76 deletions(-) diff --git a/ecosystem/python/parser/src/constant/full_parser.rs b/ecosystem/python/parser/src/constant/full_parser.rs index e69de29b..47b53afe 100644 --- a/ecosystem/python/parser/src/constant/full_parser.rs +++ b/ecosystem/python/parser/src/constant/full_parser.rs @@ -0,0 +1,61 @@ +use rustpython_parser::ast::{Expr, StmtAnnAssign, StmtAssign, StmtAugAssign}; +use ligen::ir::{Constant, Identifier}; +use crate::identifier::IdentifierParser; +use crate::prelude::*; + +use super::DynamicParser; + +impl<'a> DynamicParser<'a> for FullParser {} + +#[derive(Default)] +pub struct FullParser; + +impl Parser<&StmtAnnAssign> for FullParser { + type Output = Constant; + fn parse(&self, input: &StmtAnnAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&StmtAugAssign> for FullParser { + type Output = Constant; + fn parse(&self, input: &StmtAugAssign) -> Result { + self.parse(input.target.as_ref()) + } +} + +impl Parser<&Expr> for FullParser { + type Output = Constant; + fn parse(&self, expr: &Expr) -> Result { + let identifier = expr + .as_name_expr() + .ok_or(Error::Message("Expected identifier".into()))? + .id + .as_str(); + let identifier = IdentifierParser::new().parse(identifier)?; + if self.is_constant(&identifier) { + Ok(Constant { identifier, ..Default::default() }) + } else { + Err(Error::Message("Expected constant".into())) + } + } +} + +impl Parser<&StmtAssign> for FullParser { + type Output = Vec; + fn parse(&self, input: &StmtAssign) -> Result { + let mut constants = Vec::new(); + for target in &input.targets { + if let Ok(constant) = self.parse(target) { + constants.push(constant); + } + } + Ok(constants) + } +} + +impl FullParser { + fn is_constant(&self, identifier: &Identifier) -> bool { + identifier.name.to_uppercase() == identifier.name + } +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/constant/mod.rs b/ecosystem/python/parser/src/constant/mod.rs index 63c5f720..dc5706d8 100644 --- a/ecosystem/python/parser/src/constant/mod.rs +++ b/ecosystem/python/parser/src/constant/mod.rs @@ -1,67 +1,17 @@ -use rustpython_parser::ast::{Expr, StmtAnnAssign, StmtAssign, StmtAugAssign}; -use ligen::ir::{Constant, Identifier}; -use crate::identifier::IdentifierParser; -use crate::prelude::*; - -#[derive(Default)] -pub struct ConstantParser; - -impl ConstantParser { - pub fn full() -> Self { - Self::default() - } - - pub fn symbol() -> Self { - Self - } -} - -impl Parser<&StmtAnnAssign> for ConstantParser { - type Output = Constant; - fn parse(&self, input: &StmtAnnAssign) -> Result { - self.parse(input.target.as_ref()) - } -} - -impl Parser<&StmtAugAssign> for ConstantParser { - type Output = Constant; - fn parse(&self, input: &StmtAugAssign) -> Result { - self.parse(input.target.as_ref()) - } -} - -impl Parser<&Expr> for ConstantParser { - type Output = Constant; - fn parse(&self, expr: &Expr) -> Result { - let identifier = expr - .as_name_expr() - .ok_or(Error::Message("Expected identifier".into()))? - .id - .as_str(); - let identifier = IdentifierParser::new().parse(identifier)?; - if self.is_constant(&identifier) { - Ok(Constant { identifier, ..Default::default() }) - } else { - Err(Error::Message("Expected constant".into())) - } - } +use ligen::parsing::dynamic_parser; +use ligen::ir::Constant; +use rustpython_parser::ast::{StmtAnnAssign, StmtAugAssign, Expr, StmtAssign}; + +mod full_parser; +mod symbol_parser; + +dynamic_parser!{ + ConstantParser, + full_parser::FullParser, + symbol_parser::SymbolParser, + Constant, + &StmtAnnAssign | &'a StmtAnnAssign, + &StmtAugAssign | &'a StmtAugAssign, + &Expr | &'a Expr, + &StmtAssign | &'a StmtAssign => Vec } - -impl Parser<&StmtAssign> for ConstantParser { - type Output = Vec; - fn parse(&self, input: &StmtAssign) -> Result { - let mut constants = Vec::new(); - for target in &input.targets { - if let Ok(constant) = self.parse(target) { - constants.push(constant); - } - } - Ok(constants) - } -} - -impl ConstantParser { - fn is_constant(&self, identifier: &Identifier) -> bool { - identifier.name.to_uppercase() == identifier.name - } -} \ No newline at end of file diff --git a/ecosystem/python/parser/src/function/mod.rs b/ecosystem/python/parser/src/function/mod.rs index ea38f813..dbf1a240 100644 --- a/ecosystem/python/parser/src/function/mod.rs +++ b/ecosystem/python/parser/src/function/mod.rs @@ -6,8 +6,8 @@ use crate::prelude::*; pub mod parameter; pub mod method; -mod symbol_parser; mod full_parser; +mod symbol_parser; dynamic_parser!{ FunctionParser, @@ -16,7 +16,7 @@ dynamic_parser!{ Function, WithSource, WithSource, - &str => &'a str + &str | &'a str } #[cfg(test)] diff --git a/ligen/parsing/src/parser/dynamic_parser.rs b/ligen/parsing/src/parser/dynamic_parser.rs index 10a783a3..7d2aa06d 100644 --- a/ligen/parsing/src/parser/dynamic_parser.rs +++ b/ligen/parsing/src/parser/dynamic_parser.rs @@ -3,26 +3,36 @@ macro_rules! as_constraint { ($typ:ty) => { $typ }; - ($typ:ty => $constraint:ty) => { + ($typ:ty | $constraint:ty) => { $constraint }; } +#[macro_export] +macro_rules! pick_output { + ($global:ty) => { + $global + }; + ($global:ty, $local:ty) => { + $local + } +} + #[macro_export] macro_rules! trait_definition { - ($output:ty, $first:ty $(=> $first_constraint:ty)? $(, $rest:ty $(=> $rest_constraint:ty)?)+) => { + ($output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)+) => { trait DynamicParser<'a>: - Parser<$crate::as_constraint!($first $(=> $first_constraint)?), Output = $output> - $(+ Parser<$crate::as_constraint!($rest $(=> $rest_constraint)?), Output = $output>)+ + Parser<$crate::as_constraint!($first $(| $first_constraint)?), Output = $crate::pick_output!($output $(, $first_output)?)> + $(+ Parser<$crate::as_constraint!($rest $(| $rest_constraint)?), Output = $crate::pick_output!($output $(, $rest_output)?)>)+ {} } } #[macro_export] macro_rules! trait_implementation { - ($name:ident, $output:ty, $first:ty $(=> $first_constraint:ty)? $(, $rest:ty $(=> $rest_constraint:ty)?)+) => { + ($name:ident, $output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)+) => { impl Parser<$first> for $name { - type Output = $output; + type Output = $crate::pick_output!($output $(, $first_output)?); fn parse(&self, input: $first) -> Result { self.parser.parse(input) } @@ -30,7 +40,7 @@ macro_rules! trait_implementation { $( impl Parser<$rest> for $name { - type Output = $output; + type Output = $crate::pick_output!($output $(, $rest_output)?); fn parse(&self, input: $rest) -> Result { self.parser.parse(input) } @@ -65,7 +75,7 @@ macro_rules! dynamic_parser { } } - impl Default for FunctionParser { + impl Default for $name { fn default() -> Self { Self::full() } From c8c82a40449637b996013095424b087d55859a2d Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 15:47:14 -0300 Subject: [PATCH 10/11] Adding docs --- ligen/parsing/src/parser/dynamic_parser.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ligen/parsing/src/parser/dynamic_parser.rs b/ligen/parsing/src/parser/dynamic_parser.rs index 7d2aa06d..b847b2ad 100644 --- a/ligen/parsing/src/parser/dynamic_parser.rs +++ b/ligen/parsing/src/parser/dynamic_parser.rs @@ -50,6 +50,19 @@ macro_rules! trait_implementation { }; } +/// Example: +/// +/// dynamic_parser!{ +/// ConstantParser, +/// full_parser::FullParser, +/// symbol_parser::SymbolParser, +/// Constant, +/// &StmtAnnAssign | &'a StmtAnnAssign, +/// &StmtAugAssign | &'a StmtAugAssign, +/// &Expr | &'a Expr // impl Parser<&Expr> for ConstantParser { ... } +/// &StmtAssign | &'a StmtAssign => Vec // Changes the default output to Vec +/// } +/// #[macro_export] macro_rules! dynamic_parser { ($name:ident, $full_parser:path, $symbol_parser:path, $output:ty, $($input:tt)*) => { From 4b2c3947640beb405bb780044a9a37ccc12eff0e Mon Sep 17 00:00:00 2001 From: Danilo Guanabara Date: Mon, 23 Oct 2023 16:01:44 -0300 Subject: [PATCH 11/11] Cleaning up dynamic parser code --- .../python/parser/src/function/method.rs | 22 +++---------------- ecosystem/python/parser/src/parser.rs | 5 +---- ecosystem/python/parser/src/scope/mod.rs | 4 ++-- .../full_parser.rs} | 21 ++++++------------ .../parser/src/types/type_definition/mod.rs | 15 +++++++++++++ .../types/type_definition/symbol_parser.rs | 19 ++++++++++++++++ ligen/parsing/src/parser/dynamic_parser.rs | 8 +++---- 7 files changed, 51 insertions(+), 43 deletions(-) rename ecosystem/python/parser/src/types/{type_definition.rs => type_definition/full_parser.rs} (51%) create mode 100644 ecosystem/python/parser/src/types/type_definition/mod.rs create mode 100644 ecosystem/python/parser/src/types/type_definition/symbol_parser.rs diff --git a/ecosystem/python/parser/src/function/method.rs b/ecosystem/python/parser/src/function/method.rs index 905873ba..8d830704 100644 --- a/ecosystem/python/parser/src/function/method.rs +++ b/ecosystem/python/parser/src/function/method.rs @@ -1,25 +1,9 @@ use rustpython_parser::ast::{StmtAsyncFunctionDef, StmtFunctionDef}; use ligen::ir::{Method, Mutability}; -use crate::function::FunctionParser; +use crate::parser::PythonParser; use crate::prelude::*; -#[derive(Default)] -pub struct MethodParser { - function_parser: FunctionParser -} - -impl MethodParser { - pub fn full() -> Self { - Default::default() - } - - pub fn symbol() -> Self { - let function_parser = FunctionParser::symbol(); - Self { function_parser } - } -} - -impl Parser> for MethodParser { +impl Parser> for PythonParser { type Output = Method; fn parse(&self, input: WithSource) -> Result { let function = self.function_parser.parse(input)?; @@ -34,7 +18,7 @@ impl Parser> for MethodParser { } } -impl Parser> for MethodParser { +impl Parser> for PythonParser { type Output = Method; fn parse(&self, input: WithSource) -> Result { let function = self.function_parser.parse(input)?; diff --git a/ecosystem/python/parser/src/parser.rs b/ecosystem/python/parser/src/parser.rs index 38650a0a..5b1337f8 100644 --- a/ecosystem/python/parser/src/parser.rs +++ b/ecosystem/python/parser/src/parser.rs @@ -1,6 +1,5 @@ use crate::constant::ConstantParser; use crate::function::FunctionParser; -use crate::function::method::MethodParser; use crate::identifier::IdentifierParser; use crate::types::type_definition::TypeDefinitionParser; @@ -8,7 +7,6 @@ use crate::types::type_definition::TypeDefinitionParser; pub struct PythonParser { pub identifier_parser: IdentifierParser, pub function_parser: FunctionParser, - pub method_parser: MethodParser, pub type_definition_parser: TypeDefinitionParser, pub constant_parser: ConstantParser } @@ -21,9 +19,8 @@ impl PythonParser { pub fn symbol() -> Self { let identifier_parser = IdentifierParser::new(); let function_parser = FunctionParser::symbol(); - let method_parser = MethodParser::symbol(); let type_definition_parser = TypeDefinitionParser::symbol(); let constant_parser = ConstantParser::symbol(); - Self { identifier_parser, function_parser, method_parser, type_definition_parser, constant_parser } + Self { identifier_parser, function_parser, type_definition_parser, constant_parser } } } diff --git a/ecosystem/python/parser/src/scope/mod.rs b/ecosystem/python/parser/src/scope/mod.rs index fb4a34d8..5a61c2f9 100644 --- a/ecosystem/python/parser/src/scope/mod.rs +++ b/ecosystem/python/parser/src/scope/mod.rs @@ -104,12 +104,12 @@ impl PythonParser { if !self.is_static_method(statements.sub(statement)) { match statement { Stmt::FunctionDef(function) => { - if let Ok(function) = self.method_parser.parse(statements.sub(function.clone())) { + if let Ok(function) = self.parse(statements.sub(function.clone())) { methods.push(function) } }, Stmt::AsyncFunctionDef(function) => { - if let Ok(function) = self.method_parser.parse(statements.sub(function.clone())) { + if let Ok(function) = self.parse(statements.sub(function.clone())) { methods.push(function) } }, diff --git a/ecosystem/python/parser/src/types/type_definition.rs b/ecosystem/python/parser/src/types/type_definition/full_parser.rs similarity index 51% rename from ecosystem/python/parser/src/types/type_definition.rs rename to ecosystem/python/parser/src/types/type_definition/full_parser.rs index cde2041e..612c5cd3 100644 --- a/ecosystem/python/parser/src/types/type_definition.rs +++ b/ecosystem/python/parser/src/types/type_definition/full_parser.rs @@ -1,22 +1,15 @@ +use crate::{prelude::*, identifier::IdentifierParser}; +use ligen::ir::{Structure, TypeDefinition}; use rustpython_parser::ast::StmtClassDef; -use ligen::ir::{TypeDefinition, Structure}; -use crate::identifier::IdentifierParser; -use crate::prelude::*; -#[derive(Default)] -pub struct TypeDefinitionParser; +use super::DynamicParser; -impl TypeDefinitionParser { - pub fn full() -> Self { - Default::default() - } +#[derive(Default)] +pub struct FullParser; - pub fn symbol() -> Self { - Self - } -} +impl<'a> DynamicParser<'a> for FullParser {} -impl Parser> for TypeDefinitionParser { +impl Parser> for FullParser { type Output = TypeDefinition; fn parse(&self, input: WithSource) -> Result { let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; diff --git a/ecosystem/python/parser/src/types/type_definition/mod.rs b/ecosystem/python/parser/src/types/type_definition/mod.rs new file mode 100644 index 00000000..ba595524 --- /dev/null +++ b/ecosystem/python/parser/src/types/type_definition/mod.rs @@ -0,0 +1,15 @@ +use crate::prelude::*; +use ligen::parsing::dynamic_parser; +use ligen::ir::TypeDefinition; +use rustpython_parser::ast::StmtClassDef; + +mod full_parser; +mod symbol_parser; + +dynamic_parser! { + TypeDefinitionParser, + full_parser::FullParser, + symbol_parser::SymbolParser, + TypeDefinition, + WithSource +} \ No newline at end of file diff --git a/ecosystem/python/parser/src/types/type_definition/symbol_parser.rs b/ecosystem/python/parser/src/types/type_definition/symbol_parser.rs new file mode 100644 index 00000000..4c854323 --- /dev/null +++ b/ecosystem/python/parser/src/types/type_definition/symbol_parser.rs @@ -0,0 +1,19 @@ +use crate::{prelude::*, identifier::IdentifierParser}; +use ligen::ir::{Structure, TypeDefinition}; +use rustpython_parser::ast::StmtClassDef; + +use super::DynamicParser; + +#[derive(Default)] +pub struct SymbolParser; + +impl<'a> DynamicParser<'a> for SymbolParser {} + +impl Parser> for SymbolParser { + type Output = TypeDefinition; + fn parse(&self, input: WithSource) -> Result { + let identifier = IdentifierParser::new().parse(input.ast.name.as_str())?; + let structure = Structure { identifier, ..Default::default() }; + Ok(structure.into()) + } +} \ No newline at end of file diff --git a/ligen/parsing/src/parser/dynamic_parser.rs b/ligen/parsing/src/parser/dynamic_parser.rs index b847b2ad..91ce60da 100644 --- a/ligen/parsing/src/parser/dynamic_parser.rs +++ b/ligen/parsing/src/parser/dynamic_parser.rs @@ -20,17 +20,17 @@ macro_rules! pick_output { #[macro_export] macro_rules! trait_definition { - ($output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)+) => { + ($output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)*) => { trait DynamicParser<'a>: Parser<$crate::as_constraint!($first $(| $first_constraint)?), Output = $crate::pick_output!($output $(, $first_output)?)> - $(+ Parser<$crate::as_constraint!($rest $(| $rest_constraint)?), Output = $crate::pick_output!($output $(, $rest_output)?)>)+ + $(+ Parser<$crate::as_constraint!($rest $(| $rest_constraint)?), Output = $crate::pick_output!($output $(, $rest_output)?)>)* {} } } #[macro_export] macro_rules! trait_implementation { - ($name:ident, $output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)+) => { + ($name:ident, $output:ty, $first:ty $(| $first_constraint:ty)? $(=> $first_output:ty)? $(, $rest:ty $(| $rest_constraint:ty)? $(=> $rest_output:ty)?)*) => { impl Parser<$first> for $name { type Output = $crate::pick_output!($output $(, $first_output)?); fn parse(&self, input: $first) -> Result { @@ -45,7 +45,7 @@ macro_rules! trait_implementation { self.parser.parse(input) } } - )+ + )* }; }