use std::mem; use logos::Logos; use logos::Span; use crate::lexer::Token; #[derive(Debug, Clone, PartialEq)] pub struct PipelineElement { kind: PipelineElementKind, span: Span, } #[derive(Debug, Clone, PartialEq)] pub enum PipelineElementKind { Pipe, Command(Vec), } #[derive(Debug, Clone, PartialEq)] pub struct CommandPart { kind: CommandPartKind, span: Span, } #[derive(Debug, Clone, PartialEq)] pub enum CommandPartKind { Word(String), Integer(i64), Float(f64), String(String), } pub fn parse(input: &str) -> Vec { let lexer = Token::lexer(input); let mut r = Vec::new(); let mut partial_command: Vec = Vec::new(); for (tok, span) in lexer.spanned().into_iter() { if let Ok(tok) = tok { match tok { Token::Pipe => { if !partial_command.is_empty() { let span = partial_command.first().unwrap().span.start ..partial_command.last().unwrap().span.end; r.push(PipelineElement { kind: PipelineElementKind::Command(mem::replace( &mut partial_command, Vec::new(), )), span, }); } r.push(PipelineElement { kind: PipelineElementKind::Pipe, span, }); } Token::Word(word) => partial_command.push(CommandPart { kind: CommandPartKind::Word(word.to_owned()), span, }), Token::IntLiteral(int) => partial_command.push(CommandPart { kind: CommandPartKind::Integer(int), span, }), Token::FloatLiteral(float) => partial_command.push(CommandPart { kind: CommandPartKind::Float(float), span, }), Token::StringLiteral(string) => partial_command.push(CommandPart { kind: CommandPartKind::String(string), span, }), _ => {} } } else { } } if !partial_command.is_empty() { let span = partial_command.first().unwrap().span.start..partial_command.last().unwrap().span.end; r.push(PipelineElement { kind: PipelineElementKind::Command(mem::replace(&mut partial_command, Vec::new())), span, }); } r } #[test] fn test_simple_parse_pipeline() { let test_pipeline = "load ./image.png | invert | save ./image_processed.jpg"; parse(test_pipeline); }