Skip to content

Commit

Permalink
function modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
dzhibas committed Feb 11, 2024
1 parent efc3b6a commit de23022
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
- [+] Atom parsing for Date
- [+] Date converted to chrono datetime for comparison later
- [+] Scopes and negated scopes. ex.: a=b and !(c=d or g=z)
- [ ] either lower() or upper() function calls or case insensitive string comparison operators
- [+] either lower() or upper() function calls or case insensitive string comparison operators
- [+] support for single quote strings
- [ ] not quoted strings as values treated as variables now, needs a fix
- [ ] evaluation with provided context
7 changes: 7 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,17 @@ pub enum ArrayOp {
NotIn,
}

#[derive(Debug, Clone, PartialEq)]
pub enum FnCall {
Upper,
Lower,
}

#[derive(Debug, Clone, PartialEq)]
pub enum AstNode {
Void,
Variable(Atom),
Function(FnCall, Box<AstNode>),
Constant(Atom),
List(Vec<Atom>),
Compare(Box<AstNode>, ComparisonOp, Box<AstNode>),
Expand Down
41 changes: 38 additions & 3 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use nom::{
IResult,
};

use crate::ast::{ArrayOp, AstNode, Atom, ComparisonOp, LogicOp};
use crate::ast::{ArrayOp, AstNode, Atom, ComparisonOp, FnCall, LogicOp};

/// Took from nom recipes
fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(
Expand Down Expand Up @@ -122,6 +122,20 @@ fn parse_variable_node(i: &str) -> IResult<&str, AstNode> {
map(parse_variable, AstNode::Variable)(i)
}

fn parse_variable_node_modifier(i: &str) -> IResult<&str, AstNode> {
let parser = tuple((
ws(parse_function_names),
delimited(tag("("), ws(parse_variable_node), tag(")")),
));
map(parser, |(fn_call, expr)| {
AstNode::Function(fn_call, Box::new(expr))
})(i)
}

fn parse_variable_node_or_modified(i: &str) -> IResult<&str, AstNode> {
alt((parse_variable_node_modifier, parse_variable_node))(i)
}

fn parse_constant(i: &str) -> IResult<&str, AstNode> {
map(parse_atom, AstNode::Constant)(i)
}
Expand All @@ -133,15 +147,30 @@ fn parse_array_op(i: &str) -> IResult<&str, ArrayOp> {
))(i)
}

fn parse_function_names(i: &str) -> IResult<&str, FnCall> {
alt((
map(tag_no_case("upper"), |_| FnCall::Upper),
map(tag_no_case("lower"), |_| FnCall::Lower),
))(i)
}

fn parse_array_expr(i: &str) -> IResult<&str, AstNode> {
let parser = tuple((parse_variable_node, ws(parse_array_op), parse_list));
let parser = tuple((
parse_variable_node_or_modified,
ws(parse_array_op),
parse_list,
));
map(parser, |(var, op, val)| {
AstNode::Array(Box::new(var), op, Box::new(val))
})(i)
}

fn parse_compare_expr(i: &str) -> IResult<&str, AstNode> {
let parser = tuple((parse_variable_node, ws(parse_comparison_op), parse_constant));
let parser = tuple((
parse_variable_node_or_modified,
ws(parse_comparison_op),
parse_constant,
));
map(parser, |(var, op, val)| {
AstNode::Compare(Box::new(var), op, Box::new(val))
})(i)
Expand Down Expand Up @@ -329,6 +358,12 @@ mod tests {
assert_eq!(res.is_ok(), true);
}

#[test]
fn test_fn_modifiers() {
let res = parse("UPPER(_demo) == 'DEMO DEMO'");
assert_eq!(res.is_ok(), true);
}

// #[test]
// fn test_extreme_test() {
// let expression = r###"a = b and c=d and something not in (1,2,3) or lower(z) == "demo car" or
Expand Down

0 comments on commit de23022

Please sign in to comment.