blob: 8df705cda1a985eb8e15d7a3114b703b11041261 [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
David Tolnay62604d92016-09-30 14:47:48 -0700227pub fn str_chars(s: &str) -> Vec<char> {
228 // Can't do `s.chars().collect()` because it triggers a compiler bug in 1.12.0
229 // https://github.com/dtolnay/syn/issues/20
230 let mut result = Vec::new();
231 for ch in s.chars() {
232 result.push(ch);
233 }
234 result
235}
236
David Tolnayb5a7b142016-09-13 22:46:39 -0700237macro_rules! take_until {
238 ($input:expr, $substr:expr) => {{
239 if $substr.len() > $input.len() {
240 $crate::nom::IResult::Error
241 } else {
David Tolnay62604d92016-09-30 14:47:48 -0700242 let substr_vec: Vec<char> = $crate::nom::str_chars($substr);
David Tolnayb5a7b142016-09-13 22:46:39 -0700243 let mut window: Vec<char> = vec![];
244 let mut offset = $input.len();
245 let mut parsed = false;
246 for (o, c) in $input.char_indices() {
247 window.push(c);
248 if window.len() > substr_vec.len() {
249 window.remove(0);
250 }
251 if window == substr_vec {
252 parsed = true;
253 window.pop();
254 let window_len: usize = window.iter()
255 .map(|x| x.len_utf8())
256 .fold(0, |x, y| x + y);
257 offset = o - window_len;
258 break;
259 }
260 }
261 if parsed {
262 $crate::nom::IResult::Done(&$input[offset..], &$input[..offset])
263 } else {
264 $crate::nom::IResult::Error
265 }
266 }
267 }};
268}
269
270macro_rules! tag {
271 ($i:expr, $tag: expr) => {
272 if $tag.len() > $i.len() {
273 $crate::nom::IResult::Error
274 } else if $i.starts_with($tag) {
275 $crate::nom::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
276 } else {
277 $crate::nom::IResult::Error
278 }
279 };
280}
281
282macro_rules! switch {
283 ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
284 match $submac!($i, $($args)*) {
285 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
286 $crate::nom::IResult::Done(i, o) => match o {
287 $(
288 $p => $subrule!(i, $($args2)*),
289 )*
290 _ => $crate::nom::IResult::Error,
291 }
292 }
293 };
294}
295
296macro_rules! value {
297 ($i:expr, $res:expr) => {
298 $crate::nom::IResult::Done($i, $res)
299 };
300}
301
302macro_rules! delimited {
303 ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
304 match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
305 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
306 $crate::nom::IResult::Done(i1, (_, o, _)) => $crate::nom::IResult::Done(i1, o)
307 }
308 };
309
310 ($i:expr, $f:expr, $($rest:tt)+) => {
311 delimited!($i, call!($f), $($rest)*);
312 };
313}
314
315macro_rules! separated_list {
316 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
317 let mut res = ::std::vec::Vec::new();
318 let mut input = $i;
319
320 // get the first element
321 match $submac!(input, $($args2)*) {
322 $crate::nom::IResult::Error => $crate::nom::IResult::Done(input, ::std::vec::Vec::new()),
323 $crate::nom::IResult::Done(i,o) => {
324 if i.len() == input.len() {
325 $crate::nom::IResult::Error
326 } else {
327 res.push(o);
328 input = i;
329
330 // get the separator first
331 while let $crate::nom::IResult::Done(i2, _) = $sep!(input, $($args)*) {
332 if i2.len() == input.len() {
333 break;
334 }
335
336 // get the element next
337 if let $crate::nom::IResult::Done(i3,o3) = $submac!(i2, $($args2)*) {
338 if i3.len() == i2.len() {
339 break;
340 }
341 res.push(o3);
342 input = i3;
343 } else {
344 break;
345 }
346 }
347 $crate::nom::IResult::Done(input, res)
348 }
349 }
350 }
351 }};
352
353 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
354 separated_list!($i, $submac!($($args)*), call!($g));
355 };
356
357 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
358 separated_list!($i, call!($f), $submac!($($args)*));
359 };
360
361 ($i:expr, $f:expr, $g:expr) => {
362 separated_list!($i, call!($f), call!($g));
363 };
364}
365
366macro_rules! separated_nonempty_list {
367 ($i:expr, $sep:ident!( $($args:tt)* ), $submac:ident!( $($args2:tt)* )) => {{
368 let mut res = ::std::vec::Vec::new();
369 let mut input = $i;
370
371 // get the first element
372 match $submac!(input, $($args2)*) {
373 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
374 $crate::nom::IResult::Done(i,o) => {
375 if i.len() == input.len() {
376 $crate::nom::IResult::Error
377 } else {
378 res.push(o);
379 input = i;
380
381 while let $crate::nom::IResult::Done(i2, _) = $sep!(input, $($args)*) {
382 if i2.len() == input.len() {
383 break;
384 }
385
386 if let $crate::nom::IResult::Done(i3,o3) = $submac!(i2, $($args2)*) {
387 if i3.len() == i2.len() {
388 break;
389 }
390 res.push(o3);
391 input = i3;
392 } else {
393 break;
394 }
395 }
396 $crate::nom::IResult::Done(input, res)
397 }
398 }
399 }
400 }};
401
402 ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
403 separated_nonempty_list!($i, $submac!($($args)*), call!($g));
404 };
405
406 ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => {
407 separated_nonempty_list!($i, call!($f), $submac!($($args)*));
408 };
409
410 ($i:expr, $f:expr, $g:expr) => {
411 separated_nonempty_list!($i, call!($f), call!($g));
412 };
413}
414
415macro_rules! tuple {
416 ($i:expr, $($rest:tt)*) => {
417 tuple_parser!($i, (), $($rest)*)
418 };
419}
420
421/// Internal parser, do not use directly
422macro_rules! tuple_parser {
423 ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
424 tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*);
425 };
426
427 ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
428 match $submac!($i, $($args)*) {
429 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
430 $crate::nom::IResult::Done(i,o) =>
431 tuple_parser!(i, (o), $($rest)*),
432 }
433 };
434
435 ($i:expr, ($($parsed:tt)*), $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, ($($parsed)* , o), $($rest)*),
440 }
441 };
442
443 ($i:expr, ($($parsed:tt),*), $e:ident) => {
444 tuple_parser!($i, ($($parsed),*), call!($e));
445 };
446
447 ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
448 $submac!($i, $($args)*)
449 };
450
451 ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
452 match $submac!($i, $($args)*) {
453 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
454 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, ($($parsed),*, o))
455 }
456 };
457
458 ($i:expr, ($($parsed:expr),*)) => {
459 $crate::nom::IResult::Done($i, ($($parsed),*))
460 };
461}
462
463macro_rules! alt {
464 ($i:expr, $e:ident | $($rest:tt)*) => {
465 alt!($i, call!($e) | $($rest)*);
466 };
467
468 ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
469 match $subrule!($i, $($args)*) {
470 res @ $crate::nom::IResult::Done(_, _) => res,
471 _ => alt!($i, $($rest)*)
472 }
473 };
474
475 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
476 match $subrule!($i, $($args)*) {
477 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
478 $crate::nom::IResult::Error => alt!($i, $($rest)*)
479 }
480 };
481
482 ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
483 alt!($i, call!($e) => { $gen } | $($rest)*);
484 };
485
486 ($i:expr, $e:ident => { $gen:expr }) => {
487 alt!($i, call!($e) => { $gen });
488 };
489
490 ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
491 match $subrule!($i, $($args)*) {
492 $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, $gen(o)),
493 $crate::nom::IResult::Error => alt!($i)
494 }
495 };
496
497 ($i:expr, $e:ident) => {
498 alt!($i, call!($e));
499 };
500
501 ($i:expr, $subrule:ident!( $($args:tt)*)) => {
502 match $subrule!( $i, $($args)* ) {
503 $crate::nom::IResult::Done(i,o) => $crate::nom::IResult::Done(i,o),
504 $crate::nom::IResult::Error => alt!($i),
505 }
506 };
507
508 ($i:expr) => {
509 $crate::nom::IResult::Error
510 };
511}
512
513macro_rules! do_parse {
514 ($i:expr, ( $($rest:expr),* )) => {
515 $crate::nom::IResult::Done($i, ( $($rest),* ))
516 };
517
518 ($i:expr, $e:ident >> $($rest:tt)*) => {
519 do_parse!($i, call!($e) >> $($rest)*);
520 };
521
522 ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
523 match $submac!($i, $($args)*) {
524 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
525 $crate::nom::IResult::Done(i, _) =>
526 do_parse!(i, $($rest)*),
527 }
528 };
529
530 ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
531 do_parse!($i, $field: call!($e) >> $($rest)*);
532 };
533
534 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
535 match $submac!($i, $($args)*) {
536 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
537 $crate::nom::IResult::Done(i,o) => {
538 let $field = o;
539 do_parse!(i, $($rest)*)
540 },
541 }
542 };
543
David Tolnayfa0edf22016-09-23 22:58:24 -0700544 ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
545 do_parse!($i, $field: call!($e) >> $($rest)*);
546 };
547
548 ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
549 match $submac!($i, $($args)*) {
550 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
551 $crate::nom::IResult::Done(i,o) => {
552 let mut $field = o;
553 do_parse!(i, $($rest)*)
554 },
555 }
556 };
557
David Tolnayb5a7b142016-09-13 22:46:39 -0700558 // ending the chain
559 ($i:expr, $e:ident >> ( $($rest:tt)* )) => {
560 do_parse!($i, call!($e) >> ( $($rest)* ));
561 };
562
563 ($i:expr, $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => {
564 match $submac!($i, $($args)*) {
565 $crate::nom::IResult::Done(i, _) => $crate::nom::IResult::Done(i, ($($rest)*)),
566 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
567 }
568 };
569
570 ($i:expr, $field:ident : $e:ident >> ( $($rest:tt)* )) => {
571 do_parse!($i, $field: call!($e) >> ( $($rest)* ) );
572 };
573
574 ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> ( $($rest:tt)* )) => {
575 match $submac!($i, $($args)*) {
576 $crate::nom::IResult::Error => $crate::nom::IResult::Error,
577 $crate::nom::IResult::Done(i,o) => {
578 let $field = o;
579 $crate::nom::IResult::Done(i, ($($rest)*))
580 },
581 }
582 };
583}