crystal_cif_io/grammar/strings_textfields/
mod.rs

1use std::fmt::Display;
2
3use winnow::{
4    combinator::{alt, opt, preceded},
5    Parser,
6};
7
8use self::unquoted_string::pure_unquoted;
9
10use super::{reserved_words::ReservedWords, whitespace_comments::WhiteSpace, SyntacticUnit, Value};
11
12mod double_quoted_string;
13mod single_quoted_string;
14mod text_field;
15mod unquoted_string;
16
17pub use text_field::TextField;
18
19pub use double_quoted_string::DoubleQuotedString;
20pub use single_quoted_string::SingleQuotedString;
21pub use unquoted_string::UnquotedString;
22
23#[derive(Debug, Clone)]
24pub enum CharString {
25    Unquoted(UnquotedString),
26    SingleQuoted(SingleQuotedString),
27    DoubleQuoted(DoubleQuotedString),
28}
29
30impl AsRef<str> for CharString {
31    fn as_ref(&self) -> &str {
32        match self {
33            CharString::Unquoted(u) => u.as_ref(),
34            CharString::SingleQuoted(s) => s.as_ref(),
35            CharString::DoubleQuoted(d) => d.as_ref(),
36        }
37    }
38}
39
40impl SyntacticUnit for CharString {
41    type ParseResult = Self;
42
43    type FormatOutput = String;
44
45    fn parser(input: &mut &str) -> winnow::prelude::PResult<Self::ParseResult> {
46        alt((
47            preceded(opt(WhiteSpace::parser), SingleQuotedString::parser)
48                .map(CharString::SingleQuoted),
49            preceded(opt(WhiteSpace::parser), DoubleQuotedString::parser)
50                .map(CharString::DoubleQuoted),
51            alt((
52                preceded(opt(WhiteSpace::parser), pure_unquoted),
53                UnquotedString::parser,
54            ))
55            .verify(|u| {
56                let mut input = u.as_ref();
57                ReservedWords::not_reserved_words(&mut input)
58            })
59            .map(CharString::Unquoted),
60        ))
61        .parse_next(input)
62    }
63
64    fn formatted_output(&self) -> Self::FormatOutput {
65        match self {
66            CharString::Unquoted(s) => format!("{s}"),
67            CharString::SingleQuoted(s) => format!("{s}"),
68            CharString::DoubleQuoted(s) => format!("{s}"),
69        }
70    }
71}
72
73impl Display for CharString {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        write!(f, "{}", self.formatted_output())
76    }
77}
78
79impl From<CharString> for Value {
80    fn from(value: CharString) -> Self {
81        Value::CharString(value)
82    }
83}
84
85#[cfg(test)]
86mod test {
87    use crate::grammar::{strings_textfields::CharString, SyntacticUnit};
88
89    #[test]
90    fn char_string() {
91        let mut input = "'C16 H38 N4 2+, C4 H4 O5 2-, 2C H4 O'
92";
93        let mut input_2 = "    rm
94";
95        let mut input_3 = "_symmetry_cell_setting
96";
97        dbg!(CharString::parser(&mut input).unwrap());
98        dbg!(CharString::parser(&mut input_2).unwrap());
99        dbg!(CharString::parser(&mut input_3).unwrap());
100    }
101}