1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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!()
}
}
|