Skip to content

Commit

Permalink
Merge pull request #126 from sensorial-systems/dev
Browse files Browse the repository at this point in the history
Dynamic Parser
  • Loading branch information
notdanilo authored Oct 23, 2023
2 parents 5a65438 + 4b2c394 commit a3642bd
Show file tree
Hide file tree
Showing 44 changed files with 701 additions and 466 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ members = [
"ligen",
"ligen/common",
"ligen/ir",
"ligen/symbols",
"ligen/parsing",
"ligen/utils",
"ligen/traits",
Expand Down Expand Up @@ -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" }
Expand Down
61 changes: 61 additions & 0 deletions ecosystem/python/parser/src/constant/full_parser.rs
Original file line number Diff line number Diff line change
@@ -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::Output> {
self.parse(input.target.as_ref())
}
}

impl Parser<&StmtAugAssign> for FullParser {
type Output = Constant;
fn parse(&self, input: &StmtAugAssign) -> Result<Self::Output> {
self.parse(input.target.as_ref())
}
}

impl Parser<&Expr> for FullParser {
type Output = Constant;
fn parse(&self, expr: &Expr) -> Result<Self::Output> {
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<Constant>;
fn parse(&self, input: &StmtAssign) -> Result<Self::Output> {
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
}
}
17 changes: 17 additions & 0 deletions ecosystem/python/parser/src/constant/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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<Constant>
}
61 changes: 61 additions & 0 deletions ecosystem/python/parser/src/constant/symbol_parser.rs
Original file line number Diff line number Diff line change
@@ -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::Output> {
self.parse(input.target.as_ref())
}
}

impl Parser<&StmtAugAssign> for SymbolParser {
type Output = Constant;
fn parse(&self, input: &StmtAugAssign) -> Result<Self::Output> {
self.parse(input.target.as_ref())
}
}

impl Parser<&Expr> for SymbolParser {
type Output = Constant;
fn parse(&self, expr: &Expr) -> Result<Self::Output> {
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<Constant>;
fn parse(&self, input: &StmtAssign) -> Result<Self::Output> {
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
}
}
82 changes: 82 additions & 0 deletions ecosystem/python/parser/src/function/full_parser.rs
Original file line number Diff line number Diff line change
@@ -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<Self::Output> {
let statement = Stmt::parse(input, "<embedded>")
.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<WithSource<StmtFunctionDef>> for FullParser {
type Output = Function;
fn parse(&self, input: WithSource<StmtFunctionDef>) -> Result<Self::Output> {
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<WithSource<StmtAsyncFunctionDef>> for FullParser {
type Output = Function;
fn parse(&self, input: WithSource<StmtAsyncFunctionDef>) -> Result<Self::Output> {
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<Vec<Expr>>) -> Result<Attributes> {
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<Vec<Parameter>> {
let mut parameters = Vec::new();
for arg in args.args {
parameters.push(ParameterParser.parse(arg)?);
}
Ok(parameters)
}

fn parse_output(&self, output: Option<Box<Expr>>) -> Result<Option<Type>> {
if let Some(expr) = output.and_then(|expr| expr.name_expr()) {
Ok(Some(TypeParser.parse(expr)?))
} else {
Ok(None)
}
}
}
34 changes: 34 additions & 0 deletions ecosystem/python/parser/src/function/method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use rustpython_parser::ast::{StmtAsyncFunctionDef, StmtFunctionDef};
use ligen::ir::{Method, Mutability};
use crate::parser::PythonParser;
use crate::prelude::*;

impl Parser<WithSource<StmtFunctionDef>> for PythonParser {
type Output = Method;
fn parse(&self, input: WithSource<StmtFunctionDef>) -> Result<Self::Output> {
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<WithSource<StmtAsyncFunctionDef>> for PythonParser {
type Output = Method;
fn parse(&self, input: WithSource<StmtAsyncFunctionDef>) -> Result<Self::Output> {
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 })
}
}
Loading

0 comments on commit a3642bd

Please sign in to comment.