diff options
Diffstat (limited to 'rprt-engine/src/parser.rs')
| -rw-r--r-- | rprt-engine/src/parser.rs | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/rprt-engine/src/parser.rs b/rprt-engine/src/parser.rs index c17913a..9536046 100644 --- a/rprt-engine/src/parser.rs +++ b/rprt-engine/src/parser.rs @@ -120,6 +120,7 @@ fn can_start_composition(context: &ParseContext, offset: usize) -> bool { | Some(Token::Complement) | Some(Token::Conditional) | Some(Token::LParen) + | Some(Token::LBrace) | Some(Token::Dot) | Some(Token::Change) | Some(Token::Insert) @@ -144,6 +145,21 @@ fn parse_base_function(context: &mut ParseContext) -> Result<Composite, ParseErr } context.advance(1, false)?; Ok(func) + } else if matches!(context.current()?, Token::LBrace) { + context.advance(1, true)?; + let mut operations = vec![parse_composition(context)?]; + while matches!(context.current(), Ok(Token::Comma)) { + context.advance(1, true)?; + operations.push(parse_composition(context)?); + } + if !matches!(context.current()?, Token::RBrace) { + return Err(ParseError::UnexpectedToken { + found: context.current()?, + expecting: "}", + }); + } + context.advance(1, false)?; + Ok(Composite::Group { operations }) } else if is_function_t(context)? { parse_builtin_function_t(context) } else if is_function_s(context)? { @@ -874,4 +890,150 @@ mod tests { _ => panic!(), } } + + #[test] + fn test_parse_group() { + let input = r#"{e, #5 -, "tr"}"#; + let tokens = tokenise(input).unwrap(); + let result = parse(tokens).unwrap(); + match result { + Composite::Group { operations } => { + assert_eq!(operations.len(), 3); + match &operations[0] { + Composite::SelectionFunction { + func: BuiltinSelectionFn::Empty, + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + match &operations[1] { + Composite::Train2 { f, g } => { + match &**f { + Composite::SelectionFunction { + func: BuiltinSelectionFn::CharOffset(5), + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + match &**g { + Composite::SelectionFunction { + func: BuiltinSelectionFn::Span, + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + } + _ => panic!(), + } + match &operations[2] { + Composite::TextFunction { + func: BuiltinTextFn::Literal(s), + swapped: false, + } => { + assert_eq!(s, "tr"); + } + _ => panic!(), + } + } + _ => panic!(), + } + } + + #[test] + fn test_parse_nested_groups_in_train() { + let input = r#"{e<#5, ;$ i} (~e<d) $"#; + let tokens = tokenise(input).unwrap(); + let result = parse(tokens).unwrap(); + match result { + Composite::Train3 { f, g, h } => { + match f.as_ref() { + Composite::Group { operations } => { + assert_eq!(operations.len(), 2); + match &operations[0] { + Composite::Hook { + kind: HookKind::After, + left, + right, + } => { + match left.as_ref() { + Composite::SelectionFunction { + func: BuiltinSelectionFn::Empty, + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + match right.as_ref() { + Composite::SelectionFunction { + func: BuiltinSelectionFn::CharOffset(5), + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + } + _ => panic!(), + } + match &operations[1] { + Composite::Train2 { f: f2, g: g2 } => { + match f2.as_ref() { + Composite::SelectionFunction { + func: BuiltinSelectionFn::EndOfBuffer, + search_mod: Some(SearchModifier::Sequential), + result_transform: None, + } => {} + _ => panic!(), + } + match g2.as_ref() { + Composite::TextFunction { + func: BuiltinTextFn::Insert, + swapped: false, + } => {} + _ => panic!(), + } + } + _ => panic!(), + } + } + _ => panic!(), + } + match g.as_ref() { + Composite::Hook { + kind: HookKind::After, + left, + right, + } => { + match left.as_ref() { + Composite::SelectionFunction { + func: BuiltinSelectionFn::Empty, + search_mod: None, + result_transform: Some(ResultTransform::Complement), + } => {} + _ => panic!(), + } + match right.as_ref() { + Composite::TextFunction { + func: BuiltinTextFn::Delete, + swapped: false, + } => {} + _ => panic!(), + } + } + _ => panic!(), + } + match h.as_ref() { + Composite::SelectionFunction { + func: BuiltinSelectionFn::EndOfBuffer, + search_mod: None, + result_transform: None, + } => {} + _ => panic!(), + } + } + _ => panic!(), + } + } } |
