crystal_cif_io/grammar/strings_textfields/
double_quoted_string.rs

1use std::fmt::Display;
2
3use winnow::{
4    combinator::{peek, preceded, repeat_till, terminated},
5    error::StrContext,
6    Parser,
7};
8
9use crate::grammar::{
10    character_sets::{AnyPrintChar, DoubleQuote},
11    whitespace_comments::WhiteSpace,
12    SyntacticUnit,
13};
14
15#[derive(Debug, Clone)]
16pub struct DoubleQuotedString {
17    content: String,
18}
19
20impl AsRef<str> for DoubleQuotedString {
21    #[inline]
22    fn as_ref(&self) -> &str {
23        <String as AsRef<str>>::as_ref(&self.content)
24    }
25}
26
27impl Display for DoubleQuotedString {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        write!(f, "{}", self.formatted_output())
30    }
31}
32
33impl DoubleQuotedString {
34    pub fn new(content: String) -> Self {
35        Self { content }
36    }
37}
38
39impl SyntacticUnit for DoubleQuotedString {
40    type ParseResult = Self;
41
42    type FormatOutput = String;
43
44    fn parser(input: &mut &str) -> winnow::prelude::PResult<Self::ParseResult> {
45        preceded(
46            DoubleQuote::parser.context(StrContext::Label("<single_quote> Open")),
47            repeat_till(
48                0..,
49                AnyPrintChar::parser.context(StrContext::Label(
50                    "AnyPrintChar, single quote not following white space",
51                )),
52                terminated(DoubleQuote::parser, peek(WhiteSpace::parser))
53                    .context(StrContext::Label("<single_quote><WhiteSpace>")),
54            )
55            .map(|(s, _open_quote): (String, DoubleQuote)| s)
56            .context(StrContext::Label("AnyPrintChar")),
57            // DoubleQuote::parser.context(StrContext::Label("<single_quote> Close")),
58        )
59        .map(DoubleQuotedString::new)
60        .parse_next(input)
61    }
62
63    fn formatted_output(&self) -> Self::FormatOutput {
64        format!(r#""{}""#, self.content)
65    }
66}
67
68#[cfg(test)]
69mod test {
70    // use winnow::{
71    //     combinator::{preceded, repeat_till, terminated},
72    //     error::StrContext,
73    //     Parser,
74    // };
75
76    // use crate::grammar::{
77    //     character_sets::{AnyPrintChar, DoubleQuote},
78    //     whitespace_comments::WhiteSpace,
79    //     SyntacticUnit,
80    // };
81
82    use super::DoubleQuotedString;
83    use crate::grammar::SyntacticUnit;
84
85    #[test]
86    fn double_quoted_string() {
87        let mut input = "\"\\f scans, and \\w scans with \\k offsets Mr. Evan\"s things\"
88";
89        // let mut parser = preceded(
90        //     DoubleQuote::parser.context(StrContext::Label("<single_quote> Open")),
91        //     repeat_till(
92        //         0..,
93        //         AnyPrintChar::parser.context(StrContext::Label(
94        //             "AnyPrintChar, single quote not following white space",
95        //         )),
96        //         terminated(DoubleQuote::parser, WhiteSpace::parser),
97        //     )
98        //     .map(|(s, _open_quote): (String, DoubleQuote)| s)
99        //     .context(StrContext::Label("AnyPrintChar")),
100        //     // DoubleQuote::parser.context(StrContext::Label("<single_quote> Close")),
101        // );
102
103        match DoubleQuotedString::parser(&mut input) {
104            // match parser.parse_next(&mut input) {
105            Ok(s) => {
106                println!("{s}");
107                dbg!(input);
108            }
109            Err(d) => {
110                dbg!(d);
111                dbg!(input);
112            }
113        }
114    }
115}