diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/commands/mod.rs | 2 | ||||
-rw-r--r-- | src/commands/parser.rs | 77 | ||||
-rw-r--r-- | src/commands/start.rs | 12 | ||||
-rw-r--r-- | src/main.rs | 5 |
7 files changed, 112 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7ff5c21 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "tidsreg" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2321cd0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tidsreg" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..5a61ce8 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,2 @@ +mod start; +mod parser; diff --git a/src/commands/parser.rs b/src/commands/parser.rs new file mode 100644 index 0000000..e75840c --- /dev/null +++ b/src/commands/parser.rs @@ -0,0 +1,77 @@ + +pub enum ParseResult<'a, T> { + Success(T, &'a str), + Failure(String), +} + +pub trait Parse<'a> { + type Res; + + fn parse(self, input: &'a str) -> ParseResult<'a, Self::Res>; +} + +pub struct Text(String); + +impl<'a> Parse<'a> for Text { + type Res = Text; + + fn parse(self, input: &'a str) -> ParseResult<'a, Text> { + let mut value = String::new(); + + let mut it = input.chars(); + let mut escape_next = false; + while let Some(c) = it.next() { + if c == '\\' && !escape_next { + escape_next = true; + continue; + } else if c == ';' { + break; + } + value.push(c); + + escape_next = false; + } + + ParseResult::Success(Text(value), it.as_str()) + } +} + +pub struct Branch<T> { + choices: Vec<(&'static str, Option<char>, T)>, +} + +impl<'a, T> Parse<'a> for Branch<T> { + type Res = T; + + fn parse(self, input: &'a str) -> ParseResult<'a, T> { + let choices: Vec<&'static str> = self.choices.iter().map(|x| x.0).collect(); + + for (long, short_op, res) in self.choices { + let rest = if input.starts_with(long) { + Some(&input[long.len()..]) + } else if let Some(short) = short_op { + if input.starts_with(short) { + Some(&input[1..]) + } else { + None + } + } else { None }; + + if let Some(rest) = rest { + return ParseResult::Success(res, rest); + } + } + + return ParseResult::Failure(format!("Expected one of [{}]", choices.join(", "))); + } +} + +impl<T> Branch<T> { + pub fn new() -> Branch<T> { + Branch { choices: Vec::new() } + } + + pub fn add(&mut self, long: &'static str, short: Option<char>, res: T) { + self.choices.push((long, short, res)); + } +} diff --git a/src/commands/start.rs b/src/commands/start.rs new file mode 100644 index 0000000..a122d5c --- /dev/null +++ b/src/commands/start.rs @@ -0,0 +1,12 @@ +use crate::commands::parser::{Text, Parse}; + +pub enum Commands { + Start(Text), +} + +impl<'a> Parse<'a> for Commands { + type Res = Commands; + + fn parse(self +} + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b97e52d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,5 @@ +mod commands; + +fn main() { + println!("Hello, world!"); +} |