104 lines
3 KiB
Rust
104 lines
3 KiB
Rust
use std::mem;
|
|
|
|
use logos::Logos;
|
|
use logos::Span;
|
|
|
|
use crate::lexer::Token;
|
|
|
|
use self::error::FileId;
|
|
use self::error::SyntaxError;
|
|
|
|
pub mod check;
|
|
mod error;
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct PipelineElement {
|
|
pub kind: PipelineElementKind,
|
|
pub span: Span,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum PipelineElementKind {
|
|
Pipe,
|
|
Command(Vec<CommandPart>),
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct CommandPart {
|
|
pub kind: CommandPartKind,
|
|
pub span: Span,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum CommandPartKind {
|
|
Word(String),
|
|
Integer(i64),
|
|
Float(f64),
|
|
String(String),
|
|
}
|
|
|
|
pub fn parse_syntax(input: &str, file_id: FileId) -> Result<Vec<PipelineElement>, SyntaxError> {
|
|
let lexer = Token::lexer(input);
|
|
let mut errs = Vec::new();
|
|
|
|
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 {
|
|
errs.push((file_id, span))
|
|
}
|
|
}
|
|
|
|
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,
|
|
});
|
|
}
|
|
|
|
if errs.is_empty() {
|
|
Ok(r)
|
|
} else {
|
|
Err(SyntaxError::InvalidToken(errs))
|
|
}
|
|
}
|