diff options
Diffstat (limited to 'src/parse.rs')
| -rw-r--r-- | src/parse.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..cc495b1 --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,84 @@ +pub enum Ast { + AssignVar(AssignVar), + Pipes(Pipes), +} + +pub struct AssignVar { + pub to: String, + // TODO: body +} + +pub struct Pipes { + pub cmds: Vec<Command>, +} + +pub struct Command { + pub path: String, + pub args: Vec<String>, +} + +enum ParseError { + Incomplete, + UnexpectedPipe, + UnknownChar(char), +} + +type Result<T> = std::result::Result<T, ParseError>; + +pub fn parse(x: &str) -> Result<Ast> { + let chars: Vec<char> = x.chars().collect(); + Ast::parse(&mut &chars[..]) +} + +trait Parse: Sized { + fn parse(b: &mut &[char]) -> Result<Self>; +} + +fn spaces(b: &mut &[char]) { + while let Some(' ' | '\t') = b.get(0) { + *b = &b[1..]; + } +} + +fn parse_quoted_string(b: &mut &[char], delim: char) -> Result<String> { + // TODO: escape sequence stuff + + *b = &b[1..]; + let mut s = String::new(); + while b.len() > 0 { + if b[0] == delim { + *b = &b[1..]; + return Ok(s); + } + + s.push(b[0]); + *b = &b[1..]; + } + Err(ParseError::Incomplete) +} + +impl Parse for String { + fn parse(b: &mut &[char]) -> Result<Self> { + spaces(b); + if b.is_empty() { + return Err(ParseError::Incomplete); + } + let c = b[0]; + if c == '|' { + Err(ParseError::UnexpectedPipe) + } else if c == '\'' || c == '"' { + *b = &b[1..]; + parse_quoted_string(b, c) + } else if c.is_ascii_graphic() { + parse_quoted_string(b, ' ') + } else { + Err(ParseError::UnknownChar(c)) + } + } +} + +impl Parse for Ast { + fn parse(b: &mut &[char]) -> Result<Self> { + todo!() + } +} |
