From e65938a2d071f755787a807ee078c546bc9b4059 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Sat, 25 Mar 2023 10:42:45 +0100 Subject: [PATCH] Add support for line break Add test case --- src/grammar.pest | 20 +++++++-------- src/parser.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/grammar.pest b/src/grammar.pest index 9e94e7b..a976ed7 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -46,7 +46,7 @@ and = { "and" } or = { "or" } logical_cmp = { and | or } child = { slash ~ ident } -any_child = { slash ~ asterisk } +any_child = { slash ~ asterisk } descendant_child = { slash ~ double_dot ~ ident } grouped_any = { slash ~ grouped_literal } array_index = { slash ~ "[" ~ number ~ "]" } @@ -55,19 +55,19 @@ slice = { slash ~ "[" ~ number ~ ":" ~ number ~ "]" } array_to = { slash ~ "[:" ~ number ~ "]" } array_from = { slash ~ "[" ~ number ~ ":]" } pick = { - sharp ~ "pick" ~ (" ")* ~ - "(" ~ (literal_keyed | (sub_expression_keyed | sub_expression_keyed_reversed) ) ~ - ((",") ~ (" ")* ~ (literal_keyed | (sub_expression_keyed | sub_expression_keyed_reversed) ))* ~ - (" ")* ~ ")" + sharp ~ "pick" ~ + "(" ~ whitespace ~ (literal_keyed | (sub_expression_keyed | sub_expression_keyed_reversed) ) ~ whitespace ~ + (whitespace ~ (",") ~ whitespace ~ (literal_keyed | (sub_expression_keyed | sub_expression_keyed_reversed) ))* ~ + whitespace ~ ")" } -sub_expression = { path ~ (pickFn | filterFn | child | any_child | grouped_any | descendant_child | array_index | slice | array_to | array_from | fn)* } +sub_expression = { path ~ (pickFn ~ whitespace| filterFn ~ whitespace| child ~ whitespace| any_child ~ whitespace| grouped_any ~ whitespace| descendant_child ~ whitespace| array_index ~ whitespace| slice ~ whitespace| array_to ~ whitespace| array_from ~ whitespace| fn ~ whitespace)* } sub_expression_reversed = { reverse_path ~ (pickFn | 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? } pickFn = { slash ~ pick } fnLit = { literal } fnExpr = { sub_expression } -fnCall = { sharp ~ ident ~ (whitespace ~ lparen ~ ((mapStmt|filterStmtCollection|fnLit|fnExpr) ~ whitespace ~ ((",")* ~ whitespace ~ (mapStmt|filterStmtCollection|fnLit|fnExpr))*)? ~ whitespace ~ rparen ~ whitespace)? ~ (arrow | arrowDeref)? } +fnCall = { sharp ~ ident ~ (whitespace ~ lparen ~ ((mapStmt|filterStmtCollection|fnLit|fnExpr) ~ whitespace ~ ((",") ~ whitespace ~ (mapStmt|filterStmtCollection|fnLit|fnExpr))*)? ~ whitespace ~ rparen ~ whitespace)? ~ (arrow | arrowDeref)? } fn = {slash ~ fnCall} filterStmt = { ( filter_elem ~ whitespace ~ cmp ~ whitespace ~ (float | truthy | literal | number ) ) } filterStmtCollection = { filterStmt ~ whitespace ~ (logical_cmp ~ whitespace ~ filterStmt~ whitespace)* } @@ -79,7 +79,7 @@ pathExpr = { ident ~ (dot ~ (pure_index|methodCall|ident))* } mapStmt = { ident ~ whitespace ~ colon ~ whitespace ~ pathExpr } expression = { - (path|reverse_path) ~ - (pickFn | filterFn | grouped_any | child | any_child | descendant_child | array_index | slice | array_to | array_from | fn)* ~ + (path|reverse_path) ~ whitespace ~ + (whitespace ~ pickFn ~ whitespace | filterFn ~ whitespace| grouped_any ~ whitespace | child ~ whitespace | any_child ~ whitespace | descendant_child ~ whitespace | array_index ~ whitespace | slice ~ whitespace | array_to ~ whitespace | array_from ~ whitespace | fn ~ whitespace)* ~ EOI -} +} \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index dca2dca..cbffaad 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -951,4 +951,69 @@ mod test { ] ); } + + #[test] + fn parse_with_line_break() { + let actions = parse( + r#">/#pick( + >/get + /..recursive + /value + /#filter('some_key' > 10) as 'values', + + >/..preferences + /#map(x: x.preference) as 'preferences' +) +"#, + ) + .unwrap(); + + assert_eq!( + actions, + vec![ + Filter::Root, + Filter::Pick(vec![ + PickFilterInner::KeyedSubpath { + alias: "values".to_string(), + reverse: false, + subpath: vec![ + Filter::Root, + Filter::Child("get".to_string()), + Filter::Descendant("recursive".to_string()), + Filter::Child("value".to_string()), + Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + operator: FilterLogicalOp::None, + left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: "some_key".to_string(), + op: FilterOp::Gt, + right: FilterInnerRighthand::Number(10), + }))), + right: None, + }))), + ], + }, + PickFilterInner::KeyedSubpath { + alias: "preferences".to_string(), + reverse: false, + subpath: vec![ + Filter::Root, + Filter::Descendant("preferences".to_string()), + Filter::Function(Func { + name: "map".to_string(), + alias: None, + should_deref: false, + args: vec![FuncArg::MapStmt(MapAST { + arg: "x".to_string(), + body: MapBody::Subpath(vec![ + Filter::Root, + Filter::Child("preference".to_string()), + ],), + })], + }), + ], + } + ]), + ] + ); + } }