use crate::lst_parser::{error::SyntaxError, syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; use self::{collection::collection, instruction::instr, lit::literal, pipeline::PIPES}; mod collection; mod instruction; mod lit; mod pipeline { use enumset::enum_set; use crate::lst_parser::{ error::SyntaxError, syntax_kind::{SyntaxKind::*, TokenSet}, CompletedMarker, Parser, }; use super::expression; pub fn pipeline(p: &mut Parser, start_expr: CompletedMarker) -> Option { if !pipe(p) { return Some(start_expr); } let pipeline_marker = start_expr.precede(p, "pipeline_start"); loop { if expression(p, true).is_none() { return Some(pipeline_marker.complete_err(p, SyntaxError::PipelineNeedsSink)); } if !pipe(p) { return Some(pipeline_marker.complete(p, PIPELINE)); } } } pub const PIPES: TokenSet = enum_set!(PIPE | MAPPING_PIPE | NULL_PIPE); fn pipe(p: &mut Parser) -> bool { if PIPES.contains(p.current()) { p.do_bump(); true } else { false } } } pub fn expression(p: &mut Parser, in_pipe: bool) -> Option { let expr = p.start("expr"); if atom(p).or_else(|| instr(p)).is_none() { expr.abandon(p); return None; } let r = expr.complete(p, EXPR); if PIPES.contains(p.current()) && !in_pipe { pipeline::pipeline(p, r) } else { Some(r) } } pub fn atom(p: &mut Parser) -> Option { literal(p) .or_else(|| collection(p)) .or_else(|| parenthesized_expr(p)) } pub fn parenthesized_expr(p: &mut Parser) -> Option { if p.eat(L_PAREN) { let par_expr = p.start("parenthesized"); expression(p, false); if !p.eat(R_PAREN) { return Some(par_expr.complete_err(p, SyntaxError::Expected(vec![R_PAREN]))); } return Some(par_expr.complete(p, PARENTHESIZED_EXPR)); } None }