1use nom::branch::alt;
2use nom::bytes::complete::{tag, tag_no_case};
3use nom::character::complete::{alpha1, alphanumeric1, char, digit1, line_ending, not_line_ending, one_of, space0};
4use nom::combinator::{map_res, opt, recognize};
5use nom::error::VerboseError;
6use nom::combinator::map;
7use nom::multi::{many0, many1};
8use nom::sequence::{delimited, pair, preceded, terminated, tuple};
9use nom::{Err, IResult, Parser};
10use std::str;
11use std::str::FromStr;
12
13use reda_unit::{Angle, Capacitance, Current, Frequency, Inductance, Number, Resistance, Suffix, Time, Voltage};
14
15pub type NomResult<'a, O> = IResult<&'a str, O, VerboseError<&'a str>>;
16
17pub trait ToFailure<T, E> {
19 fn to_failure(self) -> Result<T, nom::Err<E>>;
20}
21
22impl<T, E> ToFailure<T, E> for Result<T, nom::Err<E>> {
23 fn to_failure(self) -> Result<T, nom::Err<E>> {
24 self.map_err(|e| match e {
25 nom::Err::Error(e) => nom::Err::Failure(e),
26 other => other,
27 })
28 }
29}
30
31pub fn smart_space0(input: &str) -> NomResult<()> {
42 let mut i = input;
43 while !i.is_empty() {
44 let bytes = i.as_bytes();
45 match bytes[0] {
46 b' ' | b'\t' | b'\r' => {
47 i = &i[1..];
48 }
49 b'\n' => {
50 if i.len() >= 2 && i.as_bytes()[1] == b'+' {
51 i = &i[2..];
52 while i.starts_with(' ') || i.starts_with('\t') {
53 i = &i[1..];
54 }
55 } else {
56 break;
57 }
58 }
59 _ => break,
60 }
61 }
62 Ok((i, ()))
63}
64
65pub fn hws<'a, F: 'a, O>(inner: F) -> impl FnMut(&'a str) -> NomResult<'a, O>
66where
67 F: FnMut(&'a str) -> NomResult<'a, O>,
68{
69 delimited(smart_space0, inner, smart_space0)
70}
71
72macro_rules! wrap_parser {
73 ($parser:expr, $input:expr, $ctx:expr) => {
74 match $parser {
75 Ok(v) => Ok(v),
76 Err(Err::Incomplete(n)) => Err(Err::Incomplete(n)),
77 Err(Err::Error(_)) => Err(Err::Error(nom::error::VerboseError {
78 errors: [($input, nom::error::VerboseErrorKind::Context($ctx))].into(),
79 })),
80 Err(Err::Failure(_)) => Err(Err::Failure(nom::error::VerboseError {
81 errors: [($input, nom::error::VerboseErrorKind::Context($ctx))].into(),
82 })),
83 }
84 };
85}
86
87pub fn identifier(input: &str) -> NomResult<&str> {
90 pub fn _identifier(input: &str) -> NomResult<&str> {
91 recognize(pair(
92 alt((alpha1, tag("_"))),
93 many0(alt((alphanumeric1, tag("_"), tag(".")))),
94 ))(input)
95 }
96 wrap_parser!(_identifier(input), input, "identifier")
97}
98
99pub fn node(input: &str) -> NomResult<&str> {
102 pub fn _node(input: &str) -> NomResult<&str> {
103 recognize(many1(alt((alphanumeric1, tag("_"), tag(".")))))(input)
104 }
105 wrap_parser!(_node(input), input, "node")
106}
107
108pub fn unsigned_int(input: &str) -> NomResult<u32> {
111 pub fn _unsigned_int(input: &str) -> NomResult<u32> {
112 let str_parser = recognize(digit1);
113 map_res(
114 str_parser,
115 |res: &str| u32::from_str(res)
116 )(input)
117 }
118 wrap_parser!(_unsigned_int(input), input, "unsigned_int")
119}
120
121pub fn float(input: &str) -> NomResult<f64> {
124 pub fn _float(input: &str) -> NomResult<f64> {
125 map_res(
126 alt((
127 recognize(tuple((opt(char('-')), decimal, char('.'), opt(decimal)))),
129 recognize(tuple((opt(char('-')), decimal))), )),
131 |res: &str| f64::from_str(res),
132 )(input)
133 }
134 wrap_parser!(_float(input), input, "float")
135}
136
137fn decimal(input: &str) -> NomResult<&str> {
138 recognize(many1(terminated(one_of("0123456789"), many0(char('_')))))(input)
139}
140
141pub fn number(input: &str) -> NomResult<Number> {
142 pub fn _number(input: &str) -> NomResult<Number> {
143 let (input, value) = float(input)?;
144 let (input, suffix) = opt(alt((
145 tag_no_case("g").map(|_| Suffix::Mega),
146 tag_no_case("meg").map(|_| Suffix::Mega),
147 tag_no_case("k").map(|_| Suffix::Kilo),
148 tag_no_case("m").map(|_| Suffix::Milli),
149 tag_no_case("u").map(|_| Suffix::Micro),
150 tag_no_case("n").map(|_| Suffix::Nano),
151 tag_no_case("p").map(|_| Suffix::Pico),
152 )))(input)?;
153
154 Ok((
155 input,
156 Number {
157 value,
158 suffix: suffix.unwrap_or(Suffix::None),
159 },
160 ))
161 }
162 wrap_parser!(_number(input), input, "expect number")
163}
164
165pub fn time_number(input: &str) -> NomResult<Time> {
166 pub fn _time_number(input: &str) -> NomResult<Time> {
167 let (input, value) = float(input)?;
168 let (input, suffix) = opt(alt((
169 tag_no_case("gs").map(|_| Suffix::Mega),
170 tag_no_case("megs").map(|_| Suffix::Mega),
171 tag_no_case("ks").map(|_| Suffix::Kilo),
172 tag_no_case("ms").map(|_| Suffix::Milli),
173 tag_no_case("us").map(|_| Suffix::Micro),
174 tag_no_case("ns").map(|_| Suffix::Nano),
175 tag_no_case("ps").map(|_| Suffix::Pico),
176 tag_no_case("g").map(|_| Suffix::Mega),
177 tag_no_case("meg").map(|_| Suffix::Mega),
178 tag_no_case("k").map(|_| Suffix::Kilo),
179 tag_no_case("m").map(|_| Suffix::Milli),
180 tag_no_case("u").map(|_| Suffix::Micro),
181 tag_no_case("n").map(|_| Suffix::Nano),
182 tag_no_case("p").map(|_| Suffix::Pico),
183 tag_no_case("s").map(|_| Suffix::None),
184 )))(input)?;
185
186 Ok((
187 input,
188 Number {
189 value,
190 suffix: suffix.unwrap_or(Suffix::None),
191 }.into(),
192 ))
193 }
194 wrap_parser!(_time_number(input), input, "expect time number")
195}
196
197pub fn voltage_number(input: &str) -> NomResult<Voltage> {
198 pub fn _voltage_number(input: &str) -> NomResult<Voltage> {
199 let (input, value) = float(input)?;
200 let (input, suffix) = opt(alt((
201 tag_no_case("gv").map(|_| Suffix::Mega),
202 tag_no_case("megv").map(|_| Suffix::Mega),
203 tag_no_case("kv").map(|_| Suffix::Kilo),
204 tag_no_case("mv").map(|_| Suffix::Milli),
205 tag_no_case("uv").map(|_| Suffix::Micro),
206 tag_no_case("nv").map(|_| Suffix::Nano),
207 tag_no_case("pv").map(|_| Suffix::Pico),
208 tag_no_case("g").map(|_| Suffix::Mega),
209 tag_no_case("meg").map(|_| Suffix::Mega),
210 tag_no_case("k").map(|_| Suffix::Kilo),
211 tag_no_case("m").map(|_| Suffix::Milli),
212 tag_no_case("u").map(|_| Suffix::Micro),
213 tag_no_case("n").map(|_| Suffix::Nano),
214 tag_no_case("p").map(|_| Suffix::Pico),
215 tag_no_case("v").map(|_| Suffix::None),
216 )))(input)?;
217
218 Ok((
219 input,
220 Number {
221 value,
222 suffix: suffix.unwrap_or(Suffix::None),
223 }.into(),
224 ))
225 }
226 wrap_parser!(_voltage_number(input), input, "expect voltage number")
227}
228
229pub fn current_number(input: &str) -> NomResult<Current> {
230 pub fn _current_number(input: &str) -> NomResult<Current> {
231 let (input, value) = float(input)?;
232 let (input, suffix) = opt(alt((
233 tag_no_case("gA").map(|_| Suffix::Mega),
234 tag_no_case("megA").map(|_| Suffix::Mega),
235 tag_no_case("kA").map(|_| Suffix::Kilo),
236 tag_no_case("mA").map(|_| Suffix::Milli),
237 tag_no_case("uA").map(|_| Suffix::Micro),
238 tag_no_case("nA").map(|_| Suffix::Nano),
239 tag_no_case("pA").map(|_| Suffix::Pico),
240 tag_no_case("g").map(|_| Suffix::Mega),
241 tag_no_case("meg").map(|_| Suffix::Mega),
242 tag_no_case("k").map(|_| Suffix::Kilo),
243 tag_no_case("m").map(|_| Suffix::Milli),
244 tag_no_case("u").map(|_| Suffix::Micro),
245 tag_no_case("n").map(|_| Suffix::Nano),
246 tag_no_case("p").map(|_| Suffix::Pico),
247 tag_no_case("A").map(|_| Suffix::None),
248 )))(input)?;
249
250 Ok((
251 input,
252 Number {
253 value,
254 suffix: suffix.unwrap_or(Suffix::None),
255 }.into(),
256 ))
257 }
258 wrap_parser!(_current_number(input), input, "expect current number")
259}
260
261pub fn resistance_number(input: &str) -> NomResult<Resistance> {
262 pub fn _resistance_number(input: &str) -> NomResult<Resistance> {
263 let (input, value) = float(input)?;
264 let (input, suffix) = opt(alt((
265 tag_no_case("gΩ").map(|_| Suffix::Mega),
266 tag_no_case("megΩ").map(|_| Suffix::Mega),
267 tag_no_case("kΩ").map(|_| Suffix::Kilo),
268 tag_no_case("mΩ").map(|_| Suffix::Milli),
269 tag_no_case("uΩ").map(|_| Suffix::Micro),
270 tag_no_case("nΩ").map(|_| Suffix::Nano),
271 tag_no_case("pΩ").map(|_| Suffix::Pico),
272 tag_no_case("g").map(|_| Suffix::Mega),
273 tag_no_case("meg").map(|_| Suffix::Mega),
274 tag_no_case("k").map(|_| Suffix::Kilo),
275 tag_no_case("m").map(|_| Suffix::Milli),
276 tag_no_case("u").map(|_| Suffix::Micro),
277 tag_no_case("n").map(|_| Suffix::Nano),
278 tag_no_case("p").map(|_| Suffix::Pico),
279 tag_no_case("Ω").map(|_| Suffix::None),
280 )))(input)?;
281
282 Ok((
283 input,
284 Number {
285 value,
286 suffix: suffix.unwrap_or(Suffix::None),
287 }.into(),
288 ))
289 }
290 wrap_parser!(_resistance_number(input), input, "expect resistance number")
291}
292
293pub fn capacitance_number(input: &str) -> NomResult<Capacitance> {
294 pub fn _capacitance_number(input: &str) -> NomResult<Capacitance> {
295 let (input, value) = float(input)?;
296 let (input, suffix) = opt(alt((
297 tag_no_case("gF").map(|_| Suffix::Mega),
298 tag_no_case("megF").map(|_| Suffix::Mega),
299 tag_no_case("kF").map(|_| Suffix::Kilo),
300 tag_no_case("mF").map(|_| Suffix::Milli),
301 tag_no_case("uF").map(|_| Suffix::Micro),
302 tag_no_case("nF").map(|_| Suffix::Nano),
303 tag_no_case("pF").map(|_| Suffix::Pico),
304 tag_no_case("g").map(|_| Suffix::Mega),
305 tag_no_case("meg").map(|_| Suffix::Mega),
306 tag_no_case("k").map(|_| Suffix::Kilo),
307 tag_no_case("m").map(|_| Suffix::Milli),
308 tag_no_case("u").map(|_| Suffix::Micro),
309 tag_no_case("n").map(|_| Suffix::Nano),
310 tag_no_case("p").map(|_| Suffix::Pico),
311 tag_no_case("F").map(|_| Suffix::None),
312 )))(input)?;
313
314 Ok((
315 input,
316 Number {
317 value,
318 suffix: suffix.unwrap_or(Suffix::None),
319 }.into(),
320 ))
321 }
322 wrap_parser!(_capacitance_number(input), input, "expect capacitance number")
323}
324
325pub fn inductance_number(input: &str) -> NomResult<Inductance> {
326 pub fn _inductance_number(input: &str) -> NomResult<Inductance> {
327 let (input, value) = float(input)?;
328 let (input, suffix) = opt(alt((
329 tag_no_case("gH").map(|_| Suffix::Mega),
330 tag_no_case("megH").map(|_| Suffix::Mega),
331 tag_no_case("kH").map(|_| Suffix::Kilo),
332 tag_no_case("mH").map(|_| Suffix::Milli),
333 tag_no_case("uH").map(|_| Suffix::Micro),
334 tag_no_case("nH").map(|_| Suffix::Nano),
335 tag_no_case("pH").map(|_| Suffix::Pico),
336 tag_no_case("g").map(|_| Suffix::Mega),
337 tag_no_case("meg").map(|_| Suffix::Mega),
338 tag_no_case("k").map(|_| Suffix::Kilo),
339 tag_no_case("m").map(|_| Suffix::Milli),
340 tag_no_case("u").map(|_| Suffix::Micro),
341 tag_no_case("n").map(|_| Suffix::Nano),
342 tag_no_case("p").map(|_| Suffix::Pico),
343 tag_no_case("H").map(|_| Suffix::Pico),
344 )))(input)?;
345
346 Ok((
347 input,
348 Number {
349 value,
350 suffix: suffix.unwrap_or(Suffix::None),
351 }.into(),
352 ))
353 }
354 wrap_parser!(_inductance_number(input), input, "expect inductance number")
355}
356
357pub fn frequency_number(input: &str) -> NomResult<Frequency> {
358 let (input, n) = number(input)?;
359 Ok((input, n.into()))
360}
361
362pub fn angle_number(input: &str) -> NomResult<Angle> {
363 let (input, n) = number(input)?;
364 Ok((input, n.into()))
365}
366
367pub fn comment(input: &str) -> NomResult<&str> {
368 pub fn _comment(input: &str) -> NomResult<&str> {
369 map(
370 terminated(
371 preceded(
372 alt((tag("*"), tag(";"))),
373 preceded(space0, not_line_ending),
374 ),
375 alt((line_ending, nom::combinator::eof)),
376 ),
377 |text: &str| text.trim_end(),
378 )(input)
379 }
380 wrap_parser!(_comment(input), input, "comment")
381}
382
383#[allow(unused)]
384#[cfg(test)]
385mod tests {
386 use super::*;
387
388 #[test]
389 fn test_decimal() {
390 let res = decimal("012ds").unwrap();
391 assert_eq!(res.0, "ds");
392 assert_eq!(res.1, "012");
393 }
394
395 #[test]
396 fn test_float() {
397 let res = float("1.2323 hhh").unwrap();
398 assert_eq!(res.0, " hhh");
399 assert_eq!(res.1, 1.2323);
400 }
401
402 #[test]
403 fn test_unsigned_int() {
404 let res = unsigned_int("1231 hhh").unwrap();
405 assert_eq!(res.0, " hhh");
406 assert_eq!(res.1, 1231);
407 }
408
409 #[test]
410 fn test_tstring() {
411 let res = identifier("hello world!").unwrap();
412 assert_eq!(res.0, " world!");
413 assert_eq!(res.1, "hello");
414 }
415
416 #[test]
417 fn test_comment() {
418 let input = "* this is a comment\r\n.nextline";
419 let (rest, c) = comment(input).unwrap();
420 assert_eq!(c, "this is a comment");
421 assert_eq!(rest, ".nextline");
422
423 let input = "; another comment without newline";
424 let (rest, c) = comment(input).unwrap();
425 assert_eq!(c, "another comment without newline");
426 assert_eq!(rest, "");
427 }
428}