diff --git a/src/lib.rs b/src/lib.rs index 97ca1bc..edd90ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,22 +74,27 @@ //! 1. `) end` use std::fmt::Display; -use pest::{error::Error, Parser}; -use pest_derive::Parser; +use parsing::{Rule, TrinitryParser}; +use pest::error::Error; -#[derive(Parser)] -#[grammar = "trinitry.pest"] -pub struct Trinitry { +mod parsing; + +pub struct Command { command: String, arguments: Vec, } -impl Trinitry { +impl Command { pub fn new(input: &str) -> Result> { - let parsed = Self::parse(Rule::trinitry, input)?; + let parsed = TrinitryParser::new(input)?; + Ok(Self::from(parsed)) + } +} +impl From> for Command { + fn from(parsed: TrinitryParser) -> Self { let command = { - let command: Vec<_> = parsed.clone().find_tagged("command").collect(); + let command: Vec<_> = parsed.0.clone().find_tagged("command").collect(); // Ensure that we have only one command // This should be ensured by the grammar, thus the 'debug_assert' @@ -102,9 +107,9 @@ impl Trinitry { .expect("This should contain exactly one element") .to_owned() }; - let arguments: Vec<_> = parsed.clone().find_tagged("argument").collect(); + let arguments: Vec<_> = parsed.0.clone().find_tagged("argument").collect(); - Ok(Trinitry { + Self { command: command.as_str().to_owned(), arguments: arguments .iter() @@ -134,11 +139,11 @@ impl Trinitry { arg.to_owned() }) .collect(), - }) + } } } -impl Display for Trinitry { +impl Display for Command { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.arguments.is_empty() { f.write_str(&self.command) @@ -156,12 +161,12 @@ mod tests; #[cfg(test)] mod test { - use crate::Trinitry; + use crate::Command; #[test] fn parse_cmd() { let string = "quit"; - let p = Trinitry::new(string).unwrap_or_else(|e| { + let p = Command::new(string).unwrap_or_else(|e| { panic!("{}", e); }); assert_eq!(&p.command, "quit"); @@ -171,7 +176,7 @@ mod test { #[test] fn parse_arg_clean() { let string = r##"lua print("Hi")"##; - let p = Trinitry::new(string).unwrap_or_else(|e| { + let p = Command::new(string).unwrap_or_else(|e| { panic!("{}", e); }); assert_eq!(&p.command, "lua"); @@ -181,7 +186,7 @@ mod test { #[test] fn parse_arg_quote() { let string = r##"write "some 'file' name""##; - let p = Trinitry::new(string).unwrap_or_else(|e| { + let p = Command::new(string).unwrap_or_else(|e| { panic!("{}", e); }); assert_eq!(&p.command, "write"); @@ -191,7 +196,7 @@ mod test { #[test] fn parse_arg_single_quote() { let string = r##"write 'some "file" name'"##; - let p = Trinitry::new(string).unwrap_or_else(|e| { + let p = Command::new(string).unwrap_or_else(|e| { panic!("{}", e); }); assert_eq!(&p.command, "write"); @@ -201,7 +206,7 @@ mod test { #[test] fn parse_arg_multi() { let string = r##"write 'some "file" name' "other name" last"##; - let p = Trinitry::new(string).unwrap_or_else(|e| { + let p = Command::new(string).unwrap_or_else(|e| { panic!("{}", e); }); diff --git a/src/parsing.rs b/src/parsing.rs new file mode 100644 index 0000000..ad927c8 --- /dev/null +++ b/src/parsing.rs @@ -0,0 +1,13 @@ +use pest::{error::Error, iterators::Pairs, Parser}; +use pest_derive::Parser; + +#[derive(Parser)] +#[grammar = "trinitry.pest"] +pub(crate) struct TrinitryParser<'a>(pub(crate) Pairs<'a, Rule>); + +impl<'a> TrinitryParser<'a> { + pub fn new(input: &'a str) -> Result> { + let parsed = Self::parse(Rule::trinitry, input)?; + Ok(Self(parsed)) + } +}