Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Parser #126

Merged
merged 11 commits into from
Oct 23, 2023
Merged
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
Loading