diff --git a/ecosystem/python/parser/src/lib.rs b/ecosystem/python/parser/src/lib.rs index b9ff00c5..5d818eaf 100644 --- a/ecosystem/python/parser/src/lib.rs +++ b/ecosystem/python/parser/src/lib.rs @@ -8,5 +8,6 @@ pub mod literal; pub mod scope; pub mod interface; pub mod object; +pub mod path; mod parser; pub use parser::*; \ No newline at end of file diff --git a/ecosystem/python/parser/src/macro_attributes/attributes/mod.rs b/ecosystem/python/parser/src/macro_attributes/attributes/mod.rs index 5fa9695a..f39085dd 100644 --- a/ecosystem/python/parser/src/macro_attributes/attributes/mod.rs +++ b/ecosystem/python/parser/src/macro_attributes/attributes/mod.rs @@ -2,13 +2,16 @@ pub mod attribute; use crate::identifier::IdentifierParser; use crate::literal::LiteralParser; +use crate::path::PathParser; use crate::prelude::*; use ligen::parser::ParserConfig; use ligen::ir::{Attributes, Attribute, macro_attributes::{Group, Named}}; use rustpython_parser::ast::{Expr, Keyword}; #[derive(Default)] -pub struct AttributesParser {} +pub struct AttributesParser { + path_parser: PathParser, +} impl Parser>> for AttributesParser { type Output = Attributes; @@ -54,18 +57,16 @@ impl Parser> for AttributesParser { fn parse(&self, input: WithSource<&Expr>, config: &ParserConfig) -> Result { match input.ast { Expr::Call(expr) => { - let name = expr.func.as_name_expr().map(|value| value.id.to_string()).expect("Failed to parse attribute name"); - let identifier = IdentifierParser::default().parse(name, config)?; + let path = self.path_parser.parse(&*expr.func, config)?; let mut attributes = self.parse(input.sub(&expr.args), config)?; let keywords = self.parse(input.sub(&expr.keywords), config)?; attributes.attributes.extend(keywords.attributes); - Ok(Group::new(identifier, attributes).into()) + Ok(Group::new(path, attributes).into()) }, Expr::Name(expr) => { - let name = expr.id.to_string(); - let identifier = IdentifierParser::default().parse(name, config)?; + let path = self.path_parser.parse(&*expr, config)?; let attributes = Attributes::default(); - Ok(Group::new(identifier, attributes).into()) + Ok(Group::new(path, attributes).into()) }, Expr::Attribute(expr) => { let name = expr.attr.to_string(); diff --git a/ecosystem/python/parser/src/path.rs b/ecosystem/python/parser/src/path.rs new file mode 100644 index 00000000..1038b8d8 --- /dev/null +++ b/ecosystem/python/parser/src/path.rs @@ -0,0 +1,44 @@ +use rustpython_parser::ast::{ExprAttribute, Expr, Identifier, ExprName}; + +use crate::{prelude::*, identifier::IdentifierParser}; + +use ligen::{ir::Path, parser::ParserConfig}; + +#[derive(Default)] +pub struct PathParser { + identifier_parser: IdentifierParser, +} + +impl Parser<&ExprAttribute> for PathParser { + type Output = Path; + fn parse(&self, input: &ExprAttribute, config: &ParserConfig) -> Result { + Ok(self.parse(&input.attr, config)?.join(self.parse(&*input.value, config)?)) + } +} + +impl Parser<&ExprName> for PathParser { + type Output = Path; + fn parse(&self, input: &ExprName, config: &ParserConfig) -> Result { + self.parse(&input.id, config) + } + +} + +impl Parser<&Identifier> for PathParser { + type Output = Path; + fn parse(&self, input: &Identifier, config: &ParserConfig) -> Result { + let identifier = self.identifier_parser.parse(input.as_str(), config)?; + Ok(Path::from(identifier)) + } +} + +impl Parser<&Expr> for PathParser { + type Output = Path; + fn parse(&self, input: &Expr, config: &ParserConfig) -> Result { + match input { + Expr::Attribute(attribute) => self.parse(attribute, config), + Expr::Name(name) => self.parse(name, config), + _ => Err(Error::Message(format!("Failed to parse path from {:?}", input))), + } + } +} \ No newline at end of file