plantuml_parser/dsl/line/
empty.rs1use crate::{ParseContainer, ParseResult, wr};
2use nom::branch::alt;
3use nom::bytes::complete::{tag, take_till, take_until};
4use nom::character::complete::{line_ending, space0};
5use nom::combinator::{eof, map};
6use nom::multi::many_till;
7use nom::{IResult, Parser};
8
9#[derive(Clone, Debug)]
38pub struct EmptyLine;
39
40impl EmptyLine {
41 pub fn parse(input: ParseContainer) -> ParseResult<Self> {
43 let (rest, parsed) =
44 alt((parse_only_space, parse_comment, parse_oneline_block_comment)).parse(input)?;
45
46 let ret0 = ParseContainer::from(parsed);
47 let ret1 = Self;
48
49 Ok((rest, (ret0, ret1)))
50 }
51}
52
53fn parse_only_space(input: ParseContainer) -> IResult<ParseContainer, Vec<ParseContainer>> {
54 let (rest, parsed) = (wr!(space0), alt((wr!(eof), wr!(line_ending)))).parse(input)?;
55
56 let parsed = Vec::from(<[ParseContainer; 2]>::from(parsed));
57 Ok((rest, parsed))
58}
59
60fn parse_comment(input: ParseContainer) -> IResult<ParseContainer, Vec<ParseContainer>> {
61 let (rest, parsed) = (
62 wr!(space0),
63 wr!(tag("'")),
64 wr!(take_till(|c| c == '\n' || c == '\r')),
65 alt((wr!(eof), wr!(line_ending))),
66 )
67 .parse(input)?;
68
69 let parsed = Vec::from(<[ParseContainer; 4]>::from(parsed));
70 Ok((rest, parsed))
71}
72
73fn parse_oneline_block_comment(
74 input: ParseContainer,
75) -> IResult<ParseContainer, Vec<ParseContainer>> {
76 let (rest, parsed) = (
77 wr!(space0),
78 wr!(tag("/'")),
79 map(
80 many_till(
81 (wr!(take_until("'/")), wr!(tag("'/")), wr!(space0)),
82 alt((wr!(eof), wr!(line_ending))),
83 ),
84 |(many_closes, ending)| {
85 let mut flattened: Vec<_> = many_closes
86 .into_iter()
87 .flat_map(|(comment, close_tag, space0_1)| [comment, close_tag, space0_1])
88 .collect();
89 flattened.push(ending);
90 flattened
91 },
92 ),
93 )
94 .parse(input)?;
95
96 let (space0_0, open_tag, flattened) = parsed;
97
98 let mut parsed = Vec::from(<[ParseContainer; 2]>::from((space0_0, open_tag)));
99 parsed.extend(flattened);
100
101 Ok((rest, parsed))
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn test_parse_only_space() -> anyhow::Result<()> {
110 let testdata = "\n";
111 let (rest, parsed) = parse_only_space(testdata.into())?;
112 assert_eq!(rest, "");
113 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
114
115 let testdata = " \n";
116 let (rest, parsed) = parse_only_space(testdata.into())?;
117 assert_eq!(rest, "");
118 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
119
120 Ok(())
121 }
122
123 #[test]
124 fn test_parse_comment() -> anyhow::Result<()> {
125 let testdata = "' comment\n";
126 let (rest, parsed) = parse_comment(testdata.into())?;
127 assert_eq!(rest, "");
128 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
129
130 let testdata = " ' comment \n";
131 let (rest, parsed) = parse_comment(testdata.into())?;
132 assert_eq!(rest, "");
133 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
134
135 Ok(())
136 }
137
138 #[test]
139 fn test_parse_oneline_block_comment() -> anyhow::Result<()> {
140 let testdata = [
141 " /' oneline block comment '/ \n",
142 " /' oneline block comment '/ \n",
143 "/' oneline /' block '/ comment '/\n",
144 " /' oneline '/ /' block '/ /' comment '/ \n",
145 ];
146
147 for testdata in testdata.into_iter() {
148 let (rest, parsed) = parse_oneline_block_comment(testdata.into())?;
149 assert_eq!(rest, "");
150 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
151 }
152
153 let testdata = " /' oneline '/ /' block '/ /' comment '/ \n/' line 2 '/\n";
154 let (rest, parsed) = parse_oneline_block_comment(testdata.into())?;
155 assert_eq!(rest, "/' line 2 '/\n");
156 assert_eq!(
157 &testdata[0..testdata.len() - rest.len()],
158 ParseContainer::from(parsed).as_str()
159 );
160
161 let testdata = rest.as_str();
162 let (rest, parsed) = parse_oneline_block_comment(testdata.into())?;
163 assert_eq!(rest, "");
164 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
165
166 Ok(())
167 }
168
169 #[test]
170 fn test_parse() -> anyhow::Result<()> {
171 let testdata = [
172 "\n",
173 " \n",
174 "' comment\n",
175 " ' comment \n",
176 " /' oneline block comment '/ \n",
177 ];
178
179 for testdata in testdata.into_iter() {
180 println!("try: testdata = {testdata:?}");
181 let (rest, (parsed, _)) = EmptyLine::parse(testdata.into())?;
182 assert_eq!(rest, "");
183 assert_eq!(testdata, ParseContainer::from(parsed).as_str());
184 }
185
186 Ok(())
187 }
188}