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