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;

pub fn expression(p: &mut Parser, in_pipe: bool) -> Option<CompletedMarker> {
    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<CompletedMarker> {
    literal(p)
        .or_else(|| collection(p))
        .or_else(|| parenthesized_expr(p))
}

pub fn parenthesized_expr(p: &mut Parser) -> Option<CompletedMarker> {
    if p.eat(L_PAREN) {
        let par_expr = p.start("parenthesized");
        expression(p, false);
        if !p.eat(R_PAREN) {
            return Some(par_expr.error(p, SyntaxError::Expected(vec![R_PAREN])));
        }

        return Some(par_expr.complete(p, PARENTHESIZED_EXPR));
    }
    None
}
