blob: a899a20201ac53c0085bd7b74e3dbadb13df8929 [file] [log] [blame]
David Tolnayb5a7b142016-09-13 22:46:39 -07001// Adapted from nom <https://github.com/Geal/nom> by removing the
2// IResult::Incomplete variant, which we don't use and which unfortunately more
3// than doubles the compilation time.
4
5#[derive(Debug, PartialEq, Eq, Clone)]
6pub enum IResult<I, O> {
7 /// indicates a correct parsing, the first field containing the rest of the
8 /// unparsed data, the second field contains the parsed data
9 Done(I, O),
10 Error,
11}
12
13/// Recognizes spaces, tabs, carriage returns and line feeds
14pub fn multispace(input: &str) -> IResult<&str, &str> {
15 if input.is_empty() {
16 return IResult::Error;
17 }
18
19 for (idx, item) in input.char_indices() {
20 let chr = item;
21 if !(chr == ' ' || chr == '\t' || chr == '\r' || chr == '\n') {
22 if idx == 0 {
23 return IResult::Error;
24 } else {
25 return IResult::Done(&input[idx..], &input[0..idx]);
26 }
27 }
28 }
29 IResult::Done("", input)
30}
31
32/// Recognizes numerical characters: 0-9
33pub fn digit(input: &str) -> IResult<&str, &str> {
34 if input.is_empty() {
35 return IResult::Error;
36 }
37
38 for (idx, item) in input.char_indices() {
39 if !item.is_digit(10) {
40 if idx == 0 {
41 return IResult::Error;
42 } else {
43 return IResult::Done(&input[idx..], &input[0..idx]);
44 }
45 }
46 }
47 IResult::Done("", input)
48}
49
50macro_rules! named {
51 ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
52 fn $name(i: &str) -> $crate::nom::IResult<&str, $o> {
53 $submac!(i, $($args)*)
54 }
55 };
56
57 (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
58 pub fn $name(i: &str) -> $crate::nom::IResult<&str, $o> {
59 $submac!(i, $($args)*)
60 }
61 };
62}
63
64macro_rules! call {
65 ($i:expr, $fun:expr) => {
66 $fun($i)
67 };
68}
69
70macro_rules! map {
71 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
72 map_impl!($i, $submac!($($args)*), call!($g));
73 };
74
75 ($i:expr, $f:expr, $g:expr) => {
76 map_impl!($i, call!($f), call!($g));
77 };
78}
79
80/// Internal parser, do not use directly
81macro_rules! map_impl {
82 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
83 match $submac!($i, $($args)*) {
84 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
85 $crate::nom::IResult::Done(i, o) => {
86 $crate::nom::IResult::Done(i, $submac2!(o, $($args2)*))
87 }
88 }
89 };
90}
91
92macro_rules! map_res {
93 ($i:expr, $f:expr, $g:expr) => {
94 map_res_impl!($i, call!($f), call!($g));
95 };
96}
97
98/// Internal parser, do not use directly
99macro_rules! map_res_impl {
100 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
101 match $submac!($i, $($args)*) {
102 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
103 $crate::nom::IResult::Done(i, o) => match $submac2!(o, $($args2)*) {
104 Ok(output) => $crate::nom::IResult::Done(i, output),
105 Err(_) => $crate::nom::IResult::Error,
106 }
107 }
108 };
109}
110
111macro_rules! not {
112 ($i:expr, $submac:ident!( $($args:tt)* )) => {
113 match $submac!($i, $($args)*) {
114 $crate::nom::IResult::Done(_, _) => $crate::nom::IResult::Error,
115 $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, ""),
116 }
117 };
118}
119
120macro_rules! cond {
121 ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
122 if $cond {
123 match $submac!($i, $($args)*) {
124 $crate::nom::IResult::Done(i,o) => $crate::nom::IResult::Done(i, ::std::option::Option::Some(o)),
125 $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, ::std::option::Option::None),
126 }
127 } else {
128 $crate::nom::IResult::Done($i, ::std::option::Option::None)
129 }
130 }
131}
132
133macro_rules! preceded {
134 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
135 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
136 $crate::nom::IResult::Done(remaining, (_, o)) => $crate::nom::IResult::Done(remaining, o),
137 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
138 }
139 };
140
141 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
142 preceded!($i, $submac!($($args)*), call!($g));
143 };
144
145 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
146 preceded!($i, call!($f), $submac!($($args)*));
147 };
148
149 ($i:expr, $f:expr, $g:expr) => {
150 preceded!($i, call!($f), call!($g));
151 };
152}
153
154macro_rules! terminated {
155 ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
156 match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
157 $crate::nom::IResult::Done(remaining, (o, _)) => $crate::nom::IResult::Done(remaining, o),
158 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
159 }
160 };
161
162 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
163 terminated!($i, $submac!($($args)*), call!($g));
164 };
165
166 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
167 terminated!($i, call!($f), $submac!($($args)*));
168 };
169
170 ($i:expr, $f:expr, $g:expr) => {
171 terminated!($i, call!($f), call!($g));
172 };
173}
174
175macro_rules! many0 {
176 ($i:expr, $submac:ident!( $($args:tt)* )) => {{
177 let ret;
178 let mut res = ::std::vec::Vec::new();
179 let mut input = $i;
180
181 loop {
182 if input.is_empty() {
183 ret = $crate::nom::IResult::Done(input, res);
184 break;
185 }
186
187 match $submac!(input, $($args)*) {
188 $crate::nom::IResult::Error => {
189 ret = $crate::nom::IResult::Done(input, res);
190 break;
191 }
192 $crate::nom::IResult::Done(i, o) => {
193 // loop trip must always consume (otherwise infinite loops)
194 if i == input {
195 ret = $crate::nom::IResult::Error;
196 break;
197 }
198
199 res.push(o);
200 input = i;
201 }
202 }
203 }
204
205 ret
206 }};
207
208 ($i:expr, $f:expr) => {
209 many0!($i, call!($f));
210 };
211}
212
213macro_rules! peek {
214 ($i:expr, $submac:ident!( $($args:tt)* )) => {
215 match $submac!($i, $($args)*) {
216 $crate::nom::IResult::Done(_, o) => $crate::nom::IResult::Done($i, o),
217 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
218 }
219 };
220}
221
222macro_rules! take_while1 {
223 ($input:expr, $submac:ident!( $($args:tt)* )) => {{
224 let mut offset = $input.len();
225 for (o, c) in $input.char_indices() {
226 if !$submac!(c, $($args)*) {
227 offset = o;
228 break;
229 }
230 }
231 if offset == 0 {
232 $crate::nom::IResult::Error
233 } else if offset < $input.len() {
234 $crate::nom::IResult::Done(&$input[offset..], &$input[..offset])
235 } else {
236 $crate::nom::IResult::Done("", $input)
237 }
238 }};
239
240 ($input:expr, $f:expr) => {
241 take_while1!($input, call!($f));
242 };
243}
244
245macro_rules! take_until {
246 ($input:expr, $substr:expr) => {{
247 if $substr.len() > $input.len() {
248 $crate::nom::IResult::Error
249 } else {
250 let substr_vec: Vec<char> = $substr.chars().collect();
251 let mut window: Vec<char> = vec![];
252 let mut offset = $input.len();
253 let mut parsed = false;
254 for (o, c) in $input.char_indices() {
255 window.push(c);
256 if window.len() > substr_vec.len() {
257 window.remove(0);
258 }
259 if window == substr_vec {
260 parsed = true;
261 window.pop();
262 let window_len: usize = window.iter()
263 .map(|x| x.len_utf8())
264 .fold(0, |x, y| x + y);
265 offset = o - window_len;
266 break;
267 }
268 }
269 if parsed {
270 $crate::nom::IResult::Done(&$input[offset..], &$input[..offset])
271 } else {
272 $crate::nom::IResult::Error
273 }
274 }
275 }};
276}
277
278macro_rules! tag {
279 ($i:expr, $tag: expr) => {
280 if $tag.len() > $i.len() {
281 $crate::nom::IResult::Error
282 } else if $i.starts_with($tag) {
283 $crate::nom::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
284 } else {
285 $crate::nom::IResult::Error
286 }
287 };
288}
289
290macro_rules! switch {
291 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
292 match $submac!($i, $($args)*) {
293 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
294 $crate::nom::IResult::Done(i, o) => match o {
295 $(
296 $p => $subrule!(i, $($args2)*),
297 )*
298 _ => $crate::nom::IResult::Error,
299 }
300 }
301 };
302}
303
304macro_rules! value {
305 ($i:expr, $res:expr) => {
306 $crate::nom::IResult::Done($i, $res)
307 };
308}
309
310macro_rules! delimited {
311 ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
312 match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
313 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
314 $crate::nom::IResult::Done(i1, (_, o, _)) => $crate::nom::IResult::Done(i1, o)
315 }
316 };
317
318 ($i:expr, $f:expr, $($rest:tt)+) => {
319 delimited!($i, call!($f), $($rest)*);
320 };
321}
322
323macro_rules! separated_list {
324 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
325 let mut res = ::std::vec::Vec::new();
326 let mut input = $i;
327
328 // get the first element
329 match $submac!(input, $($args2)*) {
330 $crate::nom::IResult::Error => $crate::nom::IResult::Done(input, ::std::vec::Vec::new()),
331 $crate::nom::IResult::Done(i,o) => {
332 if i.len() == input.len() {
333 $crate::nom::IResult::Error
334 } else {
335 res.push(o);
336 input = i;
337
338 // get the separator first
339 while let $crate::nom::IResult::Done(i2, _) = $sep!(input, $($args)*) {
340 if i2.len() == input.len() {
341 break;
342 }
343
344 // get the element next
345 if let $crate::nom::IResult::Done(i3,o3) = $submac!(i2, $($args2)*) {
346 if i3.len() == i2.len() {
347 break;
348 }
349 res.push(o3);
350 input = i3;
351 } else {
352 break;
353 }
354 }
355 $crate::nom::IResult::Done(input, res)
356 }
357 }
358 }
359 }};
360
361 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
362 separated_list!($i, $submac!($($args)*), call!($g));
363 };
364
365 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
366 separated_list!($i, call!($f), $submac!($($args)*));
367 };
368
369 ($i:expr, $f:expr, $g:expr) => {
370 separated_list!($i, call!($f), call!($g));
371 };
372}
373
374macro_rules! separated_nonempty_list {
375 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
376 let mut res = ::std::vec::Vec::new();
377 let mut input = $i;
378
379 // get the first element
380 match $submac!(input, $($args2)*) {
381 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
382 $crate::nom::IResult::Done(i,o) => {
383 if i.len() == input.len() {
384 $crate::nom::IResult::Error
385 } else {
386 res.push(o);
387 input = i;
388
389 while let $crate::nom::IResult::Done(i2, _) = $sep!(input, $($args)*) {
390 if i2.len() == input.len() {
391 break;
392 }
393
394 if let $crate::nom::IResult::Done(i3,o3) = $submac!(i2, $($args2)*) {
395 if i3.len() == i2.len() {
396 break;
397 }
398 res.push(o3);
399 input = i3;
400 } else {
401 break;
402 }
403 }
404 $crate::nom::IResult::Done(input, res)
405 }
406 }
407 }
408 }};
409
410 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
411 separated_nonempty_list!($i, $submac!($($args)*), call!($g));
412 };
413
414 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
415 separated_nonempty_list!($i, call!($f), $submac!($($args)*));
416 };
417
418 ($i:expr, $f:expr, $g:expr) => {
419 separated_nonempty_list!($i, call!($f), call!($g));
420 };
421}
422
423macro_rules! tuple {
424 ($i:expr, $($rest:tt)*) => {
425 tuple_parser!($i, (), $($rest)*)
426 };
427}
428
429/// Internal parser, do not use directly
430macro_rules! tuple_parser {
431 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
432 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*);
433 };
434
435 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
436 match $submac!($i, $($args)*) {
437 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
438 $crate::nom::IResult::Done(i,o) =>
439 tuple_parser!(i, (o), $($rest)*),
440 }
441 };
442
443 ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
444 match $submac!($i, $($args)*) {
445 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
446 $crate::nom::IResult::Done(i,o) =>
447 tuple_parser!(i, ($($parsed)* , o), $($rest)*),
448 }
449 };
450
451 ($i:expr, ($($parsed:tt),*), $e:ident) => {
452 tuple_parser!($i, ($($parsed),*), call!($e));
453 };
454
455 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
456 $submac!($i, $($args)*)
457 };
458
459 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
460 match $submac!($i, $($args)*) {
461 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
462 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, ($($parsed),*, o))
463 }
464 };
465
466 ($i:expr, ($($parsed:expr),*)) => {
467 $crate::nom::IResult::Done($i, ($($parsed),*))
468 };
469}
470
471macro_rules! alt {
472 ($i:expr, $e:ident | $($rest:tt)*) => {
473 alt!($i, call!($e) | $($rest)*);
474 };
475
476 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
477 match $subrule!($i, $($args)*) {
478 res @ $crate::nom::IResult::Done(_, _) => res,
479 _ => alt!($i, $($rest)*)
480 }
481 };
482
483 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
484 match $subrule!($i, $($args)*) {
485 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
486 $crate::nom::IResult::Error => alt!($i, $($rest)*)
487 }
488 };
489
490 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
491 alt!($i, call!($e) => { $gen } | $($rest)*);
492 };
493
494 ($i:expr, $e:ident => { $gen:expr }) => {
495 alt!($i, call!($e) => { $gen });
496 };
497
498 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
499 match $subrule!($i, $($args)*) {
500 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
501 $crate::nom::IResult::Error => alt!($i)
502 }
503 };
504
505 ($i:expr, $e:ident) => {
506 alt!($i, call!($e));
507 };
508
509 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
510 match $subrule!( $i, $($args)* ) {
511 $crate::nom::IResult::Done(i,o) => $crate::nom::IResult::Done(i,o),
512 $crate::nom::IResult::Error => alt!($i),
513 }
514 };
515
516 ($i:expr) => {
517 $crate::nom::IResult::Error
518 };
519}
520
521macro_rules! do_parse {
522 ($i:expr, ( $($rest:expr),* )) => {
523 $crate::nom::IResult::Done($i, ( $($rest),* ))
524 };
525
526 ($i:expr, $e:ident >> $($rest:tt)*) => {
527 do_parse!($i, call!($e) >> $($rest)*);
528 };
529
530 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
531 match $submac!($i, $($args)*) {
532 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
533 $crate::nom::IResult::Done(i, _) =>
534 do_parse!(i, $($rest)*),
535 }
536 };
537
538 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
539 do_parse!($i, $field: call!($e) >> $($rest)*);
540 };
541
542 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
543 match $submac!($i, $($args)*) {
544 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
545 $crate::nom::IResult::Done(i,o) => {
546 let $field = o;
547 do_parse!(i, $($rest)*)
548 },
549 }
550 };
551
552 // ending the chain
553 ($i:expr, $e:ident >> ( $($rest:tt)* )) => {
554 do_parse!($i, call!($e) >> ( $($rest)* ));
555 };
556
557 ($i:expr, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => {
558 match $submac!($i, $($args)*) {
559 $crate::nom::IResult::Done(i, _) => $crate::nom::IResult::Done(i, ($($rest)*)),
560 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
561 }
562 };
563
564 ($i:expr, $field:ident : $e:ident >> ( $($rest:tt)* )) => {
565 do_parse!($i, $field: call!($e) >> ( $($rest)* ) );
566 };
567
568 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => {
569 match $submac!($i, $($args)*) {
570 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
571 $crate::nom::IResult::Done(i,o) => {
572 let $field = o;
573 $crate::nom::IResult::Done(i, ($($rest)*))
574 },
575 }
576 };
577}