Skip to content

Commit

Permalink
WIP: implement function generalization
Browse files Browse the repository at this point in the history
  • Loading branch information
mitghi committed Mar 11, 2023
1 parent 3d82d7a commit 56c7727
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 5 deletions.
25 changes: 25 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ pub enum Filter {
All,
Len,
Sum,
Function(Func),
}

#[allow(dead_code)]
Expand All @@ -241,6 +242,21 @@ pub enum Error {
Eval(String),
}

#[allow(dead_code)]
#[derive(Debug, PartialEq, Clone)]
pub enum FuncArg {
None,
Key(String),
Ord(Filter),
SubExpr(Vec<Filter>),
}

#[derive(Debug, PartialEq, Clone)]
pub struct Func {
pub name: String,
pub args: Vec<FuncArg>,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Expand Down Expand Up @@ -362,6 +378,15 @@ macro_rules! do_comparision {
};
}

impl Func {
pub fn new() -> Self {
Self {
name: String::new(),
args: Vec::new(),
}
}
}

impl FilterInner {
fn eval(&self, entry: &Value) -> bool {
let obj = if let Some(output) = entry.as_object() {
Expand Down
12 changes: 8 additions & 4 deletions src/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ pick = {
((",") ~ (" ")* ~ (literal_keyed | (sub_expression_keyed | sub_expression_keyed_reversed) ))* ~
(" ")* ~ ")"
}
sub_expression = { path ~ (formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | child | any_child | grouped_any | descendant_child | array_index | slice | array_to | array_from)* }
sub_expression_reversed = { reverse_path ~ (formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from)* }
sub_expression = { path ~ (formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | child | any_child | grouped_any | descendant_child | array_index | slice | array_to | array_from | fn)* }
sub_expression_reversed = { reverse_path ~ (formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from | fn)* }
sub_expression_keyed = { sub_expression ~ as? }
sub_expression_keyed_reversed = { sub_expression_reversed ~ as? }

Expand All @@ -67,14 +67,18 @@ squashFn = { slash ~ squash }
pickFn = { slash ~ pick }
formats = { sharp ~ "formats" ~ whitespace ~ lparen ~ literal ~ ((",")* ~ whitespace ~ literal)+ ~ whitespace ~ rparen ~ whitespace ~ (as | asDeref)}
formatsFn = { slash ~ formats }
fnCall = { sharp ~ ident ~ whitespace ~ lparen ~ ((literal|sub_expression) ~ whitespace ~ ((",")* ~ whitespace ~ (literal|sub_expression))*)? ~ whitespace ~ rparen ~ whitespace ~ (as | asDeref)? }
fnLit = { literal }
fnExpr = { sub_expression }
fnCall = { sharp ~ ident ~ whitespace ~ lparen ~ ((filterStmtCollection|fnLit|fnExpr ) ~ whitespace ~ ((",")* ~ whitespace ~ (filterStmtCollection|fnLit|fnExpr))*)? ~ whitespace ~ rparen ~ whitespace ~ (as | asDeref)? }
fn = {slash ~ fnCall}
filterStmt = { ( filter_elem ~ whitespace ~ cmp ~ whitespace ~ (float | truthy | literal | number ) ) }
filterStmtCollection = { filterStmt ~ whitespace ~ (logical_cmp ~ whitespace ~ filterStmt~ whitespace)* }
filter = { sharp ~ "filter" ~ lparen ~ whitespace ~ ( filterStmt ~ whitespace ~ (logical_cmp ~ whitespace ~ filterStmt~ whitespace)* ) ~ whitespace ~ rparen }
filter_elem = { literal }
filterFn = { slash ~ filter }

expression = {
(path|reverse_path) ~
(formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from)* ~
(formatsFn | lenFn | allFn | pickFn | sumFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from | fn)* ~
EOI
}
72 changes: 71 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use std::cell::RefCell;
use std::rc::Rc;

use pest::iterators::Pair;

use crate::context::{
Filter, FilterAST, FilterInner, FilterInnerRighthand, FilterLogicalOp, FilterOp, FormatOp,
PickFilterInner,
Func, FuncArg, PickFilterInner,
};

use crate::*;
Expand All @@ -26,6 +28,49 @@ pub(crate) fn parse<'a>(input: &'a str) -> Result<Vec<Filter>, pest::error::Erro
let mut actions: Vec<Filter> = vec![];
for token in root.into_inner() {
match token.as_rule() {
Rule::r#fn => {
let inner: Pair<Rule> = token.clone().into_inner().nth(1).unwrap();
let mut func = Func::new();

func.name
.insert_str(0, inner.clone().into_inner().next().unwrap().as_str());

for value in inner.into_inner() {
match &value.as_rule() {
Rule::ident => {}
Rule::fnLit => {
let literal = &value
.clone()
.into_inner()
.next()
.unwrap()
.into_inner()
.as_str();
func.args.push(FuncArg::Key(literal.to_string()));
}
Rule::fnExpr => {
let expr = parse(
&value
.clone()
.into_inner()
.next()
.unwrap()
.into_inner()
.as_str(),
)?;
func.args.push(FuncArg::SubExpr(expr));
}
Rule::filterStmtCollection => {
todo!("handle filter statements");
}
_ => {
todo!("handle unmatched arm of function generalization",);
}
}
}

actions.push(Filter::Function(func));
}
Rule::path | Rule::reverse_path => actions.push(Filter::Root),
Rule::allFn => actions.push(Filter::All),
Rule::lenFn => actions.push(Filter::Len),
Expand Down Expand Up @@ -142,10 +187,12 @@ pub(crate) fn parse<'a>(input: &'a str) -> Result<Vec<Filter>, pest::error::Erro
let mut arguments: Vec<String> = vec![];
let mut elem = token.into_inner().nth(1).unwrap().into_inner();
let format = elem.next().unwrap().into_inner().as_str().to_string();

// default alias for keyed subpath
let mut alias = "unknown".to_string();
// sugar to return object containing only '{alias: eval expr}'
let mut should_deref = false;

for e in elem {
match e.as_rule() {
Rule::literal => {
Expand Down Expand Up @@ -746,4 +793,27 @@ mod test {
]
);
}

#[test]
fn parse_fncall() {
let actions = parse(">/#someFn('some', 'argument', >/and/path)").unwrap();
assert_eq!(
actions,
vec![
Filter::Root,
Filter::Function(Func {
name: "someFn".to_string(),
args: vec![
FuncArg::Key("some".to_string()),
FuncArg::Key("argument".to_string()),
FuncArg::SubExpr(vec![
Filter::Root,
Filter::Child("and".to_string()),
Filter::Child("path".to_string()),
])
],
})
]
);
}
}

0 comments on commit 56c7727

Please sign in to comment.