blob: 7283e41de31e3888ba8414b5d4333ca295a2d9d6 [file] [log] [blame]
Michael Layzell5bde96f2017-01-24 17:59:21 -05001use IResult;
David Tolnaydef66372016-10-24 21:51:32 -07002use space::{skip_whitespace, word_break};
David Tolnayb79ee962016-09-04 09:39:20 -07003
Michael Layzell5bde96f2017-01-24 17:59:21 -05004#[macro_export]
David Tolnayb79ee962016-09-04 09:39:20 -07005macro_rules! punct {
6 ($i:expr, $punct:expr) => {
David Tolnay5fe14fc2017-01-27 16:22:08 -08007 $crate::helper::punct($i, $punct)
David Tolnayb79ee962016-09-04 09:39:20 -07008 };
9}
10
David Tolnay5fe14fc2017-01-27 16:22:08 -080011// Not public API.
12#[doc(hidden)]
David Tolnay13e5da42016-09-04 16:18:34 -070013pub fn punct<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, &'a str> {
David Tolnaydef66372016-10-24 21:51:32 -070014 let input = skip_whitespace(input);
David Tolnay14cbdeb2016-10-01 12:13:59 -070015 if input.starts_with(token) {
16 IResult::Done(&input[token.len()..], token)
17 } else {
18 IResult::Error
David Tolnay13e5da42016-09-04 16:18:34 -070019 }
David Tolnay13e5da42016-09-04 16:18:34 -070020}
21
Michael Layzell5bde96f2017-01-24 17:59:21 -050022#[macro_export]
David Tolnay10413f02016-09-30 09:12:02 -070023macro_rules! keyword {
24 ($i:expr, $keyword:expr) => {
David Tolnay5fe14fc2017-01-27 16:22:08 -080025 $crate::helper::keyword($i, $keyword)
David Tolnay10413f02016-09-30 09:12:02 -070026 };
27}
28
David Tolnay5fe14fc2017-01-27 16:22:08 -080029// Not public API.
30#[doc(hidden)]
David Tolnay10413f02016-09-30 09:12:02 -070031pub fn keyword<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, &'a str> {
32 match punct(input, token) {
33 IResult::Done(rest, _) => {
34 match word_break(rest) {
35 IResult::Done(_, _) => IResult::Done(rest, token),
36 IResult::Error => IResult::Error,
37 }
38 }
39 IResult::Error => IResult::Error,
40 }
41}
42
Michael Layzell5bde96f2017-01-24 17:59:21 -050043#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070044macro_rules! option {
45 ($i:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayf6ccb832016-09-04 15:00:56 -070046 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050047 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, Some(o)),
48 $crate::IResult::Error => $crate::IResult::Done($i, None),
David Tolnayf6ccb832016-09-04 15:00:56 -070049 }
David Tolnayb5a7b142016-09-13 22:46:39 -070050 };
David Tolnayf6ccb832016-09-04 15:00:56 -070051
David Tolnayb5a7b142016-09-13 22:46:39 -070052 ($i:expr, $f:expr) => {
53 option!($i, call!($f));
54 };
55}
56
Michael Layzell5bde96f2017-01-24 17:59:21 -050057#[macro_export]
David Tolnayb5a7b142016-09-13 22:46:39 -070058macro_rules! opt_vec {
59 ($i:expr, $submac:ident!( $($args:tt)* )) => {
David Tolnayb79ee962016-09-04 09:39:20 -070060 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050061 $crate::IResult::Done(i, o) => $crate::IResult::Done(i, o),
62 $crate::IResult::Error => $crate::IResult::Done($i, Vec::new()),
David Tolnayb79ee962016-09-04 09:39:20 -070063 }
David Tolnayb5a7b142016-09-13 22:46:39 -070064 };
65}
David Tolnayb79ee962016-09-04 09:39:20 -070066
Michael Layzell5bde96f2017-01-24 17:59:21 -050067#[macro_export]
David Tolnayb79ee962016-09-04 09:39:20 -070068macro_rules! epsilon {
69 ($i:expr,) => {
Michael Layzell5bde96f2017-01-24 17:59:21 -050070 $crate::IResult::Done($i, ())
David Tolnayfa0edf22016-09-23 22:58:24 -070071 };
72}
73
Michael Layzell5bde96f2017-01-24 17:59:21 -050074#[macro_export]
David Tolnayfa0edf22016-09-23 22:58:24 -070075macro_rules! tap {
76 ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
77 match $submac!($i, $($args)*) {
Michael Layzell5bde96f2017-01-24 17:59:21 -050078 $crate::IResult::Done(i, o) => {
David Tolnayfa0edf22016-09-23 22:58:24 -070079 let $name = o;
80 $e;
Michael Layzell5bde96f2017-01-24 17:59:21 -050081 $crate::IResult::Done(i, ())
David Tolnayfa0edf22016-09-23 22:58:24 -070082 }
Michael Layzell5bde96f2017-01-24 17:59:21 -050083 $crate::IResult::Error => $crate::IResult::Error,
David Tolnayfa0edf22016-09-23 22:58:24 -070084 }
85 };
86
87 ($i:expr, $name:ident : $f:expr => $e:expr) => {
88 tap!($i, $name: call!($f) => $e);
David Tolnayb79ee962016-09-04 09:39:20 -070089 };
90}
David Tolnay674258d2016-10-08 13:30:45 -070091
Michael Layzell5bde96f2017-01-24 17:59:21 -050092#[macro_export]
David Tolnay674258d2016-10-08 13:30:45 -070093macro_rules! separated_list {
94 ($i:expr, punct!($sep:expr), $f:expr) => {
David Tolnay5fe14fc2017-01-27 16:22:08 -080095 $crate::helper::separated_list($i, $sep, $f, false)
David Tolnay674258d2016-10-08 13:30:45 -070096 };
97}
98
Michael Layzell5bde96f2017-01-24 17:59:21 -050099#[macro_export]
David Tolnayff46fd22016-10-08 13:53:28 -0700100macro_rules! terminated_list {
101 ($i:expr, punct!($sep:expr), $f:expr) => {
David Tolnay5fe14fc2017-01-27 16:22:08 -0800102 $crate::helper::separated_list($i, $sep, $f, true)
David Tolnayff46fd22016-10-08 13:53:28 -0700103 };
104}
105
David Tolnay5fe14fc2017-01-27 16:22:08 -0800106// Not public API.
107#[doc(hidden)]
David Tolnayc7f646a2016-10-16 10:54:39 -0700108pub fn separated_list<'a, T>(mut input: &'a str,
109 sep: &'static str,
110 f: fn(&'a str) -> IResult<&'a str, T>,
111 terminated: bool)
112 -> IResult<&'a str, Vec<T>> {
David Tolnay674258d2016-10-08 13:30:45 -0700113 let mut res = Vec::new();
114
115 // get the first element
116 match f(input) {
117 IResult::Error => IResult::Done(input, Vec::new()),
118 IResult::Done(i, o) => {
119 if i.len() == input.len() {
120 IResult::Error
121 } else {
122 res.push(o);
123 input = i;
124
125 // get the separator first
126 while let IResult::Done(i2, _) = punct(input, sep) {
127 if i2.len() == input.len() {
128 break;
129 }
130
131 // get the element next
132 if let IResult::Done(i3, o3) = f(i2) {
133 if i3.len() == i2.len() {
134 break;
135 }
136 res.push(o3);
137 input = i3;
138 } else {
139 break;
140 }
141 }
David Tolnayff46fd22016-10-08 13:53:28 -0700142 if terminated {
143 if let IResult::Done(after, _) = punct(input, sep) {
144 input = after;
145 }
146 }
David Tolnay674258d2016-10-08 13:30:45 -0700147 IResult::Done(input, res)
148 }
149 }
150 }
151}