mech_syntax/
repl.rs

1use crate::*;
2use mech_core::*;
3use nom::{
4  IResult,
5  bytes::complete::tag,
6  branch::alt,
7  bytes::complete::{take_while, take_until, take_till1},
8  combinator::{opt, not},
9  multi::{separated_list1, separated_list0},
10  character::complete::{space0,space1,digit1},
11  sequence::tuple as nom_tuple,
12};
13
14#[derive(Debug, Clone)]
15pub enum ReplCommand {
16  Help,
17  Quit,
18  //Pause,
19  //Resume,
20  //Stop,
21  Save(String),
22  Docs(Option<String>),
23  Code(Vec<(String,MechSourceCode)>),
24  Ls,
25  Cd(String),
26  Step(Option<usize>),
27  Load(Vec<String>),
28  Whos(Vec<String>),
29  Plan,
30  Symbols(Option<String>),
31  Clear(Option<String>),
32  Clc,
33  //Error(String),
34  //Empty,
35}
36
37pub fn parse_repl_command(input: &str) -> IResult<&str, ReplCommand> {
38  let (input, _) = tag(":")(input)?;
39  let (input, command) = alt((
40    step_rpl,
41    help_rpl,
42    quit_rpl,
43    save_rpl,
44    symbols_rpl,
45    plan_rpl,
46    ls_rpl,
47    cd_rpl,
48    whos_rpl,
49    clear_rpl,
50    clc_rpl,
51    load_rpl,
52    docs_rpl,
53  ))(input)?;
54  let (input, _) = opt(tag("\r\n"))(input)?;
55  Ok((input, command))
56}
57
58fn save_rpl(input: &str) -> IResult<&str, ReplCommand> {
59  let (input, _) = tag("save")(input)?;
60  let (input, _) = space1(input)?;
61  let (input, path) = take_while(|c: char| c.is_alphanumeric() || c == '/' || c == '.' || c == '_')(input)?;
62  Ok((input, ReplCommand::Save(path.to_string())))
63}
64
65fn docs_rpl(input: &str) -> IResult<&str, ReplCommand> {
66  let (input, _) = alt((tag("docs"), tag("d")))(input)?;
67  let (input, _) = space0(input)?;
68  let (input, name) = opt(take_till1(|c| c == '\r' || c == '\n'))(input)?;
69  let name = name.map(|s| s.to_string());
70  Ok((input, ReplCommand::Docs(name)))
71}
72
73fn help_rpl(input: &str) -> IResult<&str, ReplCommand> {
74  let (input, _) = alt((tag("h"), tag("help")))(input)?;
75  Ok((input, ReplCommand::Help))
76}
77
78fn quit_rpl(input: &str) -> IResult<&str, ReplCommand> {
79  let (input, _) = alt((tag("q"), tag("quit"), tag("exit")))(input)?;
80  Ok((input, ReplCommand::Quit))
81}
82
83fn cd_rpl(input: &str) -> IResult<&str, ReplCommand> {
84  let (input, _) = tag("cd")(input)?;
85  let (input, _) = space0(input)?;
86  let (input, path) = take_until("\r\n")(input)?;
87  Ok((input, ReplCommand::Cd(path.to_string())))
88}
89
90fn symbols_rpl(input: &str) -> IResult<&str, ReplCommand> {
91  let (input, _) = alt((tag("s"), tag("symbols")))(input)?;
92  let (input, _) = space0(input)?;
93  let (input, name) = opt(take_while(|c: char| c.is_alphanumeric()))(input)?;
94  Ok((input, ReplCommand::Symbols(name.map(|s| s.to_string()))))
95}
96
97fn plan_rpl(input: &str) -> IResult<&str, ReplCommand> {
98  let (input, _) = alt((tag("p"), tag("plan")))(input)?;
99  Ok((input, ReplCommand::Plan))
100}
101
102fn identifier(input: &str) -> IResult<&str, String> {
103    let (input, id) = take_till1(|c| c == ' ' || c == '\n' || c == '\r')(input)?;
104    Ok((input, id.to_string()))
105}
106
107fn whos_rpl(input: &str) -> IResult<&str, ReplCommand> {
108    let (input, _) = alt((tag("whos"), tag("w")))(input)?;
109    let (input, _) = space0(input)?;
110    let (input, names) = separated_list0(many1(tag(" ")), identifier)(input)?;
111    Ok((input, ReplCommand::Whos(names)))
112}
113
114fn clear_rpl(input: &str) -> IResult<&str, ReplCommand> {
115  let (input, _) = tag("clear")(input)?;
116  Ok((input, ReplCommand::Clear(None)))
117}
118
119fn clc_rpl(input: &str) -> IResult<&str, ReplCommand> {
120  let (input, _) = alt((tag("c"), tag("clc")))(input)?;
121  Ok((input, ReplCommand::Clc))
122}
123
124fn ls_rpl(input: &str) -> IResult<&str, ReplCommand> {
125  let (input, _) = tag("ls")(input)?;
126  Ok((input, ReplCommand::Ls))
127}
128
129fn load_rpl(input: &str) -> IResult<&str, ReplCommand> {
130  let (input, _) = tag("load")(input)?;
131  let (input, _) = space1(input)?;
132  let (input, path_strings) = separated_list1(space1, alt((take_until(" "),take_until("\r\n"))))(input)?;
133  Ok((input, ReplCommand::Load(path_strings.iter().map(|s| s.to_string()).collect())))
134}
135
136fn step_rpl(input: &str) -> IResult<&str, ReplCommand> {
137  let (input, _) = tag("step")(input)?;
138  let (input, _) = space0(input)?;
139  let (input, count) = opt(digit1)(input)?;
140  Ok((input, ReplCommand::Step(count.map(|s| s.parse().unwrap()))))
141}