crystal_cif_io/grammar/strings_textfields/
mod.rs1use 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}