vrsh 0.1.0

A simple shell written for my own learning.
use crate::shell::common::types::{Cmd, CmdPart, Arg, Redirect, CmdPartSection, Assignment, CmdType};

grammar;

match {
    ">" => REDIRECT_OUT,
    "<" => REDIRECT_IN,
    "|" => PIPE,
    "=" => EQUALS,
    "set" => SET,
    r#""[^"]*""# => STRING,
    r#"'[^']*'"# => SINGLE_QUOTED_STRING,
    r#"[^\s|"$()=#']+"# => WORD,
    r#"\s*"# => {},
}

pub Command: Cmd = {
    <p0:CmdType> <prest:(PIPE <CmdType>)*> => Cmd{
        parts: vec![p0].into_iter().chain(prest.into_iter()).collect(),
    }
}

CmdType: CmdType = {
    <part: Part> => CmdType::Cmd(part),
    SET <var: WORD> EQUALS <ass: Assignment> => CmdType::Variable(String::from(var), match ass {
        Assignment::Word(w) => w,
        Assignment::String(s) => s
    })
}

Part: CmdPart = {
    <redirects: Redirect*> <cmd: WORD> <args: CmdPartSection*> => CmdPart {
        cmd: String::from(cmd),
        args: args.clone().into_iter().filter_map(|v| match v {
                          CmdPartSection::Redirect(_) => None,
                          CmdPartSection::Arg(arg) => Some(arg),
                      }).collect(),
        redirects: [redirects, args.into_iter().filter_map(|v| match v {
            CmdPartSection::Redirect(r) => Some(r),
            CmdPartSection::Arg(_) => None,
        }).collect()].concat(),
    },

}

CmdPartSection: CmdPartSection = {
    Arg => CmdPartSection::Arg(<>),
    Redirect => CmdPartSection::Redirect(<>),
}

Arg: Arg = {
    <word: WORD> EQUALS <ass: Assignment> => Arg::Assignment(String::from(word), ass),
    <ass: Assignment> => match ass {
        Assignment::String(s) => Arg::String(s),
        Assignment::Word(w) => Arg::Word(w),
    }
}

Redirect: Redirect = {
    REDIRECT_IN <f: WORD> => Redirect::In(String::from(f)),
    REDIRECT_OUT <f: WORD> => Redirect::Out(String::from(f))
}

Assignment: Assignment = {
    SINGLE_QUOTED_STRING => Assignment::String(String::from(<>.strip_prefix("'").unwrap().strip_suffix("'").unwrap())),
    STRING => Assignment::String(String::from(<>.strip_prefix('"').unwrap().strip_suffix('"').unwrap())),
    WORD => Assignment::Word(String::from(<>)),
}