1#[macro_export]
6macro_rules! token {
7 ($(#[$attrs:meta])* $vis:vis enum $name:ident $(<
8 $($lt:lifetime $(: $ltltbound:lifetime)?),* $(,)?
9 $($T:ident $(: $bound:path)? $(: ?$sized:path)? $(: $ltbound:lifetime)? $(= $default:ty)?),* $(,)?
10 >)? : $src:ty
11 $(where $($U:ty $(: $whbound:path)? $(: ?$whsized:path)? $(: $whltbound:lifetime)?),* $(,)?)?
12 {
13 $(
14 $(#[$f_attrs:meta])*
15 $(@[$($key:ident = $value:ident),* $(,)?])?
16 $var:ident $(($field:ty))? = $token:expr
17 ),+ $(,)?
18 }) => {
19 $(#[$attrs])*
20 $vis enum $name $(<
21 $($lt $(: $ltltbound)?,)*
22 $($T $(: $bound)? $(: ?$sized)? $(: $ltbound)? $(= $default)?),*
23 >)?
24 $(where $($U $(: $whbound)? $(: ?$whsized)? $(: $whltbound)?,)*)?
25 {
26 $($(#[$f_attrs])* $var $(($field))?,)+
27 }
28
29 impl $(<
30 $($lt $(: $ltltbound)?,)*
31 $($T $(: $bound)? $(: ?$sized)? $(: $ltbound)? $(= $default)?),*
32 >)? $name $(<$($lt,)* $($T),*>)?
33 $(where $($U $(: $whbound)? $(: ?$whsized)? $(: $whltbound)?,)*)?
34 {
35 #[allow(dead_code)]
36 pub fn parser<'__parser, __Input>() -> impl somen::parser::Parser<
37 __Input,
38 Output = $name $(<$($lt,)* $($T),*>)?
39 > + '__parser
40 where
41 __Input: Input<Ok=$src> + ?Sized + '__parser,
42 $(
43 $($lt: '__parser,)*
44 $($T: '__parser,)*
45 )?
46 {
47 somen::parser::choice((
48 $(
49 somen::parser::wrapper::Map::new(
50 $token,
51 $crate::__token_inner!{@closure [$name] [$var]; $($field)? },
52 ),
53 )+
54 ))
55 }
56
57 $crate::__token_inner! {@expand [$name] [$src] $([$([$lt])* | $([$T])*])?;
58 $([$var] [$($field)?] [$token] [|] $($([$key = $value])*)?;)+
59 }
60 }
61 };
62}
63
64#[macro_export]
65#[doc(hidden)]
66macro_rules! __token_inner {
67 (@expand [$name:ident] [$src:ty]; $(
68 [$var:ident] [$($field:ty)?] [$token:expr] [|] $([$key:ident = $value:ident])*;
69 )*) => {
70 $(
71 $crate::__token_inner! {
72 @method [$name] [$src] [$var] [$($field)?] [$token];
73 $([$key = $value])*
74 }
75 )*
76 };
77 (@expand [$name:ident] [$src:ty] [|]; $(
78 [$var:ident] [$($field:ty)?] [$token:expr] [$([$lt:lifetime])* | $([$T:ident])*]
79 $([$key:ident = $value:ident])*;
80 )*) => {
81 $(
82 $crate::__token_inner! {
83 @method [$name] [$src] [$var] [$($field)?] [$token] [$($lt),*|$($T),*];
84 $([$key = $value])*
85 }
86 )*
87 };
88 (@expand [$name:ident] [$src:ty] [|[$T:ident]$([$rest:ident])*]; $(
89 [$var:ident] [$($field:ty)?] [$token:expr] [$([$lt:lifetime])* | $([$U:ident])*]
90 $([$key:ident = $value:ident])*;
91 )*) => {
92 $crate::__token_inner! { @expand [$name] [$src] [|$([$rest])*]; $(
93 [$var] [$($field)?] [$token] [$([$lt])*|$([$U])*[$T]] $([$key = $value])*;
94 )* }
95 };
96 (@expand [$name:ident] [$src:ty] [[$lt:lifetime]$([$rest:lifetime])*|$([$T:ident])*]; $(
97 [$var:ident] [$($field:ty)?] [$token:expr] [$([$lt2:lifetime])*|]
98 $([$key:ident = $value:ident])*;
99 )*) => {
100 $crate::__token_inner! { @expand [$name] [$src] [$([$rest])*|$([$T])*]; $(
101 [$var] [$($field)?] [$token] [$([$lt2])*[$lt]|] $([$key = $value])*;
102 )* }
103 };
104 (@method [$name:ident] [$src:ty] [$var:ident] [$($field:ty)?] [$token:expr]
105 $([$($lt:lifetime),*|$($T:ident),*])?;) => {};
106 (@method [$name:ident] [$src:ty] [$var:ident] [$($field:ty)?] [$token:expr]
107 $([$($lt:lifetime),*|$($T:ident),*])?; [match = $fname:ident]$([$k:ident = $v:ident])*) => {
108 #[allow(dead_code)]
109 #[inline]
110 pub fn $fname<'__parser, __Input>() -> impl somen::parser::Parser<
111 __Input, Output = ($($field)?)
112 > + '__parser $($(+ $lt)*)?
113 where
114 __Input: Positioned<Ok = Self> + ?Sized + '__parser $($(+ $lt)*)?,
115 $(
116 $($lt: '__parser,)*
117 $($T: '__parser,)*
118 )?
119 {
120 somen::parser::wrapper::Expect::new(
121 somen::parser::is_some(|c|
122 $crate::__token_inner! { @match c [$name] [$var]; $($field)? }
123 ),
124 stringify!($fname).into(),
125 )
126 }
127
128 $crate::__token_inner! { @method [$name] [$src] [$var] [$($field)?] [$token] $([$($lt),*|$($T),*])?; $([$k = $v])* }
129 };
130 (@method [$name:ident] [$src:ty] [$var:ident] [$field:ty] [$token:expr]
131 $([$($lt:lifetime),*|$($T:ident),*])?; [match_arg = $fname:ident]$([$k:ident = $v:ident])*) => {
132 #[allow(dead_code)]
133 #[inline]
134 pub fn $fname<'__parser, __Input, __Value>(inner: __Value) -> impl somen::parser::Parser<
135 __Input, Output = $field
136 > + '__parser $($(+ $lt)*)?
137 where
138 __Input: Positioned<Ok = Self> + ?Sized + '__parser $($(+ $lt)*)?,
139 __Value: PartialEq<$field> + '__parser $($(+ $lt)*)?,
140 $(
141 $($lt: '__parser,)*
142 $($T: '__parser,)*
143 )?
144 {
145 somen::parser::wrapper::Expect::new(
146 somen::parser::is_some(move |c| match c {
147 $name::$var(val) if inner == val => Some(val),
148 _ => None,
149 }),
150 stringify!($fname).into(),
151 )
152 }
153
154 $crate::__token_inner! { @method [$name] [$src] [$var] [$field] [$token] $([$($lt),*|$($T),*])?; $([$k = $v])* }
155 };
156 (@method [$name:ident] [$src:ty] [$var:ident] [] [$token:expr]
157 $([$($lt:lifetime),*|$($T:ident),*])?; [match_arg = $fname:ident]$([$k:ident = $v:ident])*) => {
158 compile_error!("`match_arg` is not supported for variants without fields.");
159
160 $crate::__token_inner! { @method [$name] [$src] [$var] [] [$token] $([$($lt),*|$($T),*])?; $([$k = $v])* }
161 };
162 (@method [$name:ident] [$src:ty] [$var:ident] [$($field:ty)?] [$token:expr]
163 $([$($lt:lifetime),*|$($T:ident),*])?; [single = $fname:ident]$([$k:ident = $v:ident])*) => {
164 #[allow(dead_code)]
165 #[inline]
166 pub fn $fname<'__parser, __Input>() -> impl somen::parser::Parser<
167 __Input,
168 Output = $name $(<$($lt,)* $($T),*>)?
169 > + '__parser
170 where
171 __Input: Input<Ok=$src> + ?Sized + '__parser,
172 $(
173 $($lt: '__parser,)*
174 $($T: '__parser,)*
175 )?
176 {
177 somen::parser::wrapper::Map::new(
178 $token,
179 $crate::__token_inner! { @closure [$name] [$var]; $($field)? },
180 )
181 }
182
183 $crate::__token_inner! { @method [$name] [$src] [$var] [$($field)?] [$token] $([$($lt),*|$($T),*])?; $([$k = $v])* }
184 };
185 (@match $c:ident [$name:ident] [$var:ident];) => {
186 match $c {
187 $name::$var => Some(()),
188 _ => None,
189 }
190 };
191 (@match $c:ident [$name:ident] [$var:ident]; $field:ty) => {
192 match $c {
193 $name::$var(inner) => Some(inner),
194 _ => None,
195 }
196 };
197 (@closure [$name:ident] [$var:ident];) => {
198 |_| $name::$var
199 };
200 (@closure [$name:ident] [$var:ident]; $field:ty) => {
201 $name::$var
202 };
203}
204
205#[cfg(feature = "alloc")]
207#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
208#[macro_export]
209macro_rules! infix {
210 (
211 $name:ident: $output:ty;
212 $($atom_val:ident : $atom:expr => $atom_ex:expr;)+
213 $(
214 @[$type:ident $(($($vars:tt)*))?]
215 $($op:expr => $ex:expr;)+
216 )*
217 ) => {{
218 let $name = || somen::parser::choice(($(
219 somen::parser::wrapper::Map::new(
220 $atom,
221 |$atom_val| -> $output { $atom_ex },
222 ),
223 )+));
224
225 $(
226 let $name = move || $crate::__infix_inner! {
227 [$type $(($($vars)*))?] $name, $output;
228 $($op => $ex;)+
229 };
230 )*
231 $name()
232 }};
233}
234
235#[macro_export]
236#[doc(hidden)]
237macro_rules! __infix_inner {
238 ([prefix($val:ident)] $name:ident, $output:ty;
239 $($op:expr => $ex:expr;)+) => {{
240 extern crate alloc;
241
242 somen::parser::wrapper::Map::new(
243 (
244 somen::parser::iterable::combinator::Collect::<_, alloc::vec::Vec<_>>::new(
245 somen::parser::iterable::generator::Repeat::new(
246 somen::parser::one_of([$($op),+]),
247 ..,
248 )
249 ),
250 $name(),
251 ),
252 |(collect, init): (alloc::vec::Vec<_>, $output)| -> $output {
253 collect
254 .into_iter()
255 .rev()
256 .fold(init, |$val: $output, op| match op {
257 $(
258 $op => $ex,
259 )+
260 _ => unreachable!(),
261 })
262 },
263 )
264 }};
265 ([prefix_once($val:ident)] $name:ident, $output:ty; $($op:expr => $ex:expr;)+) => {
266 somen::parser::wrapper::Map::new(
267 (somen::parser::combinator::Opt::new(somen::parser::one_of([$($op),+])), $name()),
268 |(op, $val): (core::option::Option<_>, $output)| -> $output {
269 match op {
270 $(
271 Some($op) => $ex,
272 )+
273 Some(_) => unreachable!(),
274 None => $val,
275 }
276 },
277 )
278 };
279 ([postfix($val:ident)] $name:ident, $output:ty; $($op:expr => $ex:expr;)+) => {
280 somen::parser::iterable::combinator::Fold::new(
281 somen::parser::iterable::generator::Repeat::new(somen::parser::one_of([$($op),+]), ..),
282 $name(),
283 |$val: $output, op: _| match op {
284 $(
285 $op => $ex,
286 )+
287 _ => unreachable!(),
288 },
289 )
290 };
291 ([postfix_once($val:ident)] $name:ident, $output:ty; $($op:expr => $ex:expr;)+) => {
292 somen::parser::wrapper::Map::new(
293 ($name(), somen::parser::combinator::Opt::new(somen::parser::one_of([$($op),+]))),
294 |($val, op): ($output, core::option::Option<_>)| -> $output {
295 match op {
296 $(
297 Some($op) => $ex,
298 )+
299 Some(_) => unreachable!(),
300 None => $val,
301 }
302 },
303 )
304 };
305 ([binary($rhs:ident $(: $rt:ty)? $(= $rp:expr)?, $lhs:ident $(: $lt:ty)? $(= $lp:expr)?)]
306 $name:ident, $output:ty; $($op:expr => $ex:expr;)+) => {
307 somen::parser::wrapper::Map::new(
308 (
309 $crate::__infix_inner!(@opt $name; $($rp)?),
310 somen::parser::combinator::Opt::new((
311 somen::parser::one_of([$($op),+]),
312 $crate::__infix_inner!(@opt $name; $($lp)?),
313 ))
314 ),
315 |($rhs, op): (
316 $crate::__infix_inner!(@opt_ty $output; $($rt)? $(= $rp)?),
317 core::option::Option<(_, $crate::__infix_inner!(@opt_ty $output; $($lt)? $(= $lp)?))>
318 )| -> $output {
319 match op {
320 $(
321 Some(($op, $lhs)) => $ex,
322 )+
323 Some(_) => unreachable!(),
324 None => $rhs,
325 }
326 },
327 )
328 };
329 ([left($rhs:ident, $lhs:ident $(: $lt:ty)? $(= $lp:expr)?)] $name:ident, $output:ty;
330 $($op:expr => $ex:expr;)+) => {
331 somen::parser::iterable::combinator::Fold::new(
332 somen::parser::iterable::generator::Repeat::new(
333 (somen::parser::one_of([$($op),+]), $crate::__infix_inner!(@opt $name; $($lp)?)),
334 ..
335 ),
336 $name(),
337 |$rhs: $output, (op, $lhs): (_, $crate::__infix_inner!(@opt_ty $output; $($lt)? $(= $lp)?))|
338 -> $output {
339 match op {
340 $(
341 $op => $ex,
342 )+
343 _ => unreachable!(),
344 }
345 },
346 )
347 };
348 ([right($rhs:ident $(: $rt:ty)? $(= $rp:expr)?, $lhs:ident)] $name:ident, $output:ty;
349 $($op:expr => $ex:expr;)+) => {{
350 extern crate alloc;
351
352 somen::parser::wrapper::Map::new(
353 (
354 somen::parser::iterable::combinator::Collect::<_, alloc::vec::Vec<_>>::new(
355 somen::parser::iterable::generator::Repeat::new(
356 (
357 $crate::__infix_inner!(@opt $name; $($rp)?),
358 somen::parser::one_of([$($op),+]),
359 ),
360 ..,
361 )
362 ),
363 $name(),
364 ),
365 |(collect, init): (
366 alloc::vec::Vec<($crate::__infix_inner!(@opt_ty $output; $($rt)? $(= $rp)?), _)>,
367 $output
368 )| -> $output {
369 collect
370 .into_iter()
371 .rev()
372 .fold(init, |$lhs, ($rhs, op)| match op {
373 $(
374 $op => $ex,
375 )+
376 _ => unreachable!(),
377 })
378 },
379 )
380 }};
381 (@opt $name:ident;) => { $name() };
382 (@opt $name:ident; $parser:expr) => { $parser };
383 (@opt_ty $output:ty;) => { $output };
384 (@opt_ty $output:ty; = $parser:expr) => { _ };
385 (@opt_ty $output:ty; $type:ty $(= $parser:expr)?) => { $type };
386}