refactor(src): Make the parsing code private to ensure only one entry point

This commit is contained in:
Benedikt Peetz 2024-05-18 16:47:59 +02:00
parent a088388e19
commit 227cfe5e97
Signed by: bpeetz
GPG Key ID: B6139BCB07CE946D
2 changed files with 36 additions and 18 deletions

View File

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

13
src/parsing.rs Normal file
View File

@ -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<Self, Error<Rule>> {
let parsed = Self::parse(Rule::trinitry, input)?;
Ok(Self(parsed))
}
}