Skip to content

Commit

Permalink
Implement formats function using function generalization
Browse files Browse the repository at this point in the history
Remove initial formats from parser
  • Loading branch information
mitghi committed Mar 12, 2023
1 parent 3d7d91f commit 3dd784f
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 92 deletions.
24 changes: 7 additions & 17 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Module containing types and functionalities for
//! evaluating jetro paths.
use crate::fmt as jetrofmt;
use crate::parser;
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -207,7 +206,6 @@ pub enum Filter {
Child(String),
Descendant(String),
Pick(Vec<PickFilterInner>),
Format(FormatOp),
ArrayIndex(usize),
ArrayFrom(usize),
ArrayTo(usize),
Expand All @@ -231,7 +229,6 @@ struct StackItem<'a> {
struct Context<'a> {
root: Rc<Value>,
stack: Rc<RefCell<Vec<StackItem<'a>>>>,
formater: Box<dyn jetrofmt::KeyFormater>,
registry: Box<dyn crate::func::Registry>,
pub results: Rc<RefCell<Vec<Rc<Value>>>>,
}
Expand All @@ -257,15 +254,17 @@ pub enum FuncArg {
pub struct Func {
pub name: String,
pub args: Vec<FuncArg>,
pub alias: Option<String>,
pub should_deref: bool,
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::EmptyQuery => write!(f, "query is empty"),
Error::Parse(ref msg) => write!(f, "error while parsing query: {}", &msg),
Error::Eval(ref msg) => write!(f, "error while evaluating query: {}", &msg),
Error::FuncEval(ref msg) => write!(f, "error while evaluating function: {}", &msg),
Error::Parse(ref msg) => write!(f, "parse: {}", &msg),
Error::Eval(ref msg) => write!(f, "eval: {}", &msg),
Error::FuncEval(ref msg) => write!(f, "func_eval: {}", &msg),
}
}
}
Expand Down Expand Up @@ -386,6 +385,8 @@ impl Func {
Self {
name: String::new(),
args: Vec::new(),
alias: None,
should_deref: false,
}
}
}
Expand Down Expand Up @@ -660,7 +661,6 @@ impl<'a> Context<'a> {
let results: Rc<RefCell<Vec<Rc<Value>>>> = Rc::new(RefCell::new(Vec::new()));
let stack: Rc<RefCell<Vec<StackItem<'a>>>> = Rc::new(RefCell::new(Vec::new()));
let rv: Rc<Value> = Rc::new(value);
let formater: Box<dyn jetrofmt::KeyFormater> = jetrofmt::default();
let registry: Box<dyn crate::func::Registry> = crate::func::default_registry();
stack
.borrow_mut()
Expand All @@ -669,7 +669,6 @@ impl<'a> Context<'a> {
Self {
root: rv.clone(),
stack,
formater,
registry,
results,
}
Expand Down Expand Up @@ -934,15 +933,6 @@ impl<'a> Context<'a> {
_ => {}
},

(Filter::Format(ref target_format), Some(tail)) => {
match self.formater.eval(&target_format, &current.value) {
Some(output) => {
push_to_stack_or_produce!(self.results, self.stack, tail, output);
}
_ => {}
};
}

(Filter::ArrayIndex(ref index), Some(tail)) => match *current.value {
Value::Array(ref array) => {
if *index < array.len() {
Expand Down
4 changes: 2 additions & 2 deletions src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub(crate) trait KeyFormater {
fn eval(&self, target_format: &FormatOp, value: &Value) -> Option<Value>;
}

struct FormatImpl;
pub(crate) struct FormatImpl;

impl FormatImpl {
fn format(&self, format: &str, value: &Value, keys: &Vec<String>) -> Option<String> {
Expand Down Expand Up @@ -60,7 +60,7 @@ impl KeyFormater for FormatImpl {
}
}

pub(crate) fn default() -> Box<impl KeyFormater> {
pub(crate) fn default_formater() -> Box<impl KeyFormater> {
Box::new(FormatImpl)
}

Expand Down
52 changes: 51 additions & 1 deletion src/func.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Module func provides abstraction for jetro functions.
use crate::context::{Error, Func};
use crate::context::{Error, Func, FuncArg};
use serde_json::Value;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -62,10 +62,60 @@ impl Callable for Reverse {
}
}

struct Formats;

impl Formats {
fn ensure_str(&mut self, value: &Value) -> Result<(), Error> {
match &value {
Value::String(_) => Ok(()),
_ => Err(Error::FuncEval("invalid type, expected string".to_string())),
}
}
}

impl Callable for Formats {
fn call(&mut self, func: &Func, value: &Value) -> Result<Value, Error> {
if func.args.len() < 2 {
return Err(Error::FuncEval("deficit number of arguments".to_string()));
}
let format = match func.args.get(0).unwrap() {
FuncArg::Key(some_key) => some_key,
_ => {
return Err(Error::FuncEval("invalid type, expected string".to_string()));
}
};
let mut args: Vec<String> = vec![];
for v in func.args[1..].iter() {
match &v {
FuncArg::Key(some_key) => {
args.push(some_key.clone());
}
_ => {
return Err(Error::FuncEval("invalid type, expected string".to_string()));
}
};
}

let formater: Box<dyn crate::fmt::KeyFormater> = crate::fmt::default_formater();
match formater.eval(
&crate::context::FormatOp::FormatString {
format: format.to_string(),
arguments: args,
alias: func.alias.clone().unwrap(),
},
&value,
) {
Some(output) => Ok(output),
_ => Err(Error::FuncEval("format failed".to_string())),
}
}
}

impl Default for FuncRegistry {
fn default() -> Self {
let mut output = FuncRegistry::new();
output.register("reverse", Box::new(Reverse));
output.register("formats", Box::new(Formats));
output
}
}
Expand Down
8 changes: 3 additions & 5 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 | 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 = { path ~ (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 ~ (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 @@ -65,8 +65,6 @@ lenFn = { slash ~ len }
sumFn = { slash ~ sum }
squashFn = { slash ~ squash }
pickFn = { slash ~ pick }
formats = { sharp ~ "formats" ~ whitespace ~ lparen ~ literal ~ ((",")* ~ whitespace ~ literal)+ ~ whitespace ~ rparen ~ whitespace ~ (as | asDeref)}
formatsFn = { slash ~ formats }
fnLit = { literal }
fnExpr = { sub_expression }
fnCall = { sharp ~ ident ~ whitespace ~ lparen ~ ((filterStmtCollection|fnLit|fnExpr ) ~ whitespace ~ ((",")* ~ whitespace ~ (filterStmtCollection|fnLit|fnExpr))*)? ~ whitespace ~ rparen ~ whitespace ~ (as | asDeref)? }
Expand All @@ -79,6 +77,6 @@ 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 | fn)* ~
(lenFn | allFn | pickFn | sumFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from | fn)* ~
EOI
}
Loading

0 comments on commit 3dd784f

Please sign in to comment.