99 lines
2.8 KiB
Rust
99 lines
2.8 KiB
Rust
|
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<CommandPart>),
|
||
|
}
|
||
|
|
||
|
#[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<PipelineElement> {
|
||
|
let lexer = Token::lexer(input);
|
||
|
|
||
|
let mut r = Vec::new();
|
||
|
|
||
|
let mut partial_command: Vec<CommandPart> = 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);
|
||
|
}
|