1use proc_macro2::Span;
101
102macro_rules! tokens {
103 (
104 punct: {
105 $($punct:tt pub struct $punct_name:ident/$len:tt #[$punct_doc:meta])*
106 }
107 delimiter: {
108 $($delimiter:tt pub struct $delimiter_name:ident #[$delimiter_doc:meta])*
109 }
110 keyword: {
111 $($keyword:tt pub struct $keyword_name:ident #[$keyword_doc:meta])*
112 }
113 ) => (
114 $(token_punct! { #[$punct_doc] $punct pub struct $punct_name/$len })*
115 $(token_delimiter! { #[$delimiter_doc] $delimiter pub struct $delimiter_name })*
116 $(token_keyword! { #[$keyword_doc] $keyword pub struct $keyword_name })*
117 )
118}
119
120macro_rules! token_punct {
121 (#[$doc:meta] $s:tt pub struct $name:ident/$len:tt) => {
122 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
123 #[$doc]
124 pub struct $name(pub [Span; $len]);
130
131 impl $name {
132 pub fn new(span: Span) -> Self {
133 $name([span; $len])
134 }
135 }
136
137 impl ::std::default::Default for $name {
138 fn default() -> Self {
139 $name([Span::def_site(); $len])
140 }
141 }
142
143 #[cfg(feature = "extra-traits")]
144 impl ::std::fmt::Debug for $name {
145 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
146 f.write_str(stringify!($name))
147 }
148 }
149
150 #[cfg(feature = "extra-traits")]
151 impl ::std::cmp::Eq for $name {}
152
153 #[cfg(feature = "extra-traits")]
154 impl ::std::cmp::PartialEq for $name {
155 fn eq(&self, _other: &$name) -> bool {
156 true
157 }
158 }
159
160 #[cfg(feature = "extra-traits")]
161 impl ::std::hash::Hash for $name {
162 fn hash<H>(&self, _state: &mut H)
163 where H: ::std::hash::Hasher
164 {}
165 }
166
167 #[cfg(feature = "printing")]
168 impl ::quote::ToTokens for $name {
169 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
170 printing::punct($s, &self.0, tokens);
171 }
172 }
173
174 #[cfg(feature = "parsing")]
175 impl ::Synom for $name {
176 fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
177 parsing::punct($s, tokens, $name)
178 }
179
180 fn description() -> Option<&'static str> {
181 Some(concat!("`", $s, "`"))
182 }
183 }
184
185 impl From<Span> for $name {
186 fn from(span: Span) -> Self {
187 $name([span; $len])
188 }
189 }
190 }
191}
192
193macro_rules! token_keyword {
194 (#[$doc:meta] $s:tt pub struct $name:ident) => {
195 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
196 #[$doc]
197 pub struct $name(pub Span);
203
204 impl ::std::default::Default for $name {
205 fn default() -> Self {
206 $name(Span::def_site())
207 }
208 }
209
210 #[cfg(feature = "extra-traits")]
211 impl ::std::fmt::Debug for $name {
212 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
213 f.write_str(stringify!($name))
214 }
215 }
216
217 #[cfg(feature = "extra-traits")]
218 impl ::std::cmp::Eq for $name {}
219
220 #[cfg(feature = "extra-traits")]
221 impl ::std::cmp::PartialEq for $name {
222 fn eq(&self, _other: &$name) -> bool {
223 true
224 }
225 }
226
227 #[cfg(feature = "extra-traits")]
228 impl ::std::hash::Hash for $name {
229 fn hash<H>(&self, _state: &mut H)
230 where H: ::std::hash::Hasher
231 {}
232 }
233
234 #[cfg(feature = "printing")]
235 impl ::quote::ToTokens for $name {
236 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
237 printing::keyword($s, &self.0, tokens);
238 }
239 }
240
241 #[cfg(feature = "parsing")]
242 impl ::Synom for $name {
243 fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
244 parsing::keyword($s, tokens, $name)
245 }
246
247 fn description() -> Option<&'static str> {
248 Some(concat!("`", $s, "`"))
249 }
250 }
251
252 impl From<Span> for $name {
253 fn from(span: Span) -> Self {
254 $name(span)
255 }
256 }
257 }
258}
259
260macro_rules! token_delimiter {
261 (#[$doc:meta] $s:tt pub struct $name:ident) => {
262 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
263 #[$doc]
264 pub struct $name(pub Span);
265
266 impl ::std::default::Default for $name {
267 fn default() -> Self {
268 $name(Span::def_site())
269 }
270 }
271
272 #[cfg(feature = "extra-traits")]
273 impl ::std::fmt::Debug for $name {
274 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
275 f.write_str(stringify!($name))
276 }
277 }
278
279 #[cfg(feature = "extra-traits")]
280 impl ::std::cmp::Eq for $name {}
281
282 #[cfg(feature = "extra-traits")]
283 impl ::std::cmp::PartialEq for $name {
284 fn eq(&self, _other: &$name) -> bool {
285 true
286 }
287 }
288
289 #[cfg(feature = "extra-traits")]
290 impl ::std::hash::Hash for $name {
291 fn hash<H>(&self, _state: &mut H)
292 where H: ::std::hash::Hasher
293 {}
294 }
295
296 impl $name {
297 #[cfg(feature = "printing")]
298 pub fn surround<F>(&self,
299 tokens: &mut ::quote::Tokens,
300 f: F)
301 where F: FnOnce(&mut ::quote::Tokens)
302 {
303 printing::delim($s, &self.0, tokens, f);
304 }
305
306 #[cfg(feature = "parsing")]
307 pub fn parse<F, R>(tokens: $crate::buffer::Cursor, f: F) -> $crate::synom::PResult<($name, R)>
308 where F: FnOnce($crate::buffer::Cursor) -> $crate::synom::PResult<R>
309 {
310 parsing::delim($s, tokens, $name, f)
311 }
312 }
313
314 impl From<Span> for $name {
315 fn from(span: Span) -> Self {
316 $name(span)
317 }
318 }
319 }
320}
321
322tokens! {
323 punct: {
324 "+" pub struct Add/1 "+=" pub struct AddEq/2 "&" pub struct And/1 "&&" pub struct AndAnd/2 "&=" pub struct AndEq/2 "@" pub struct At/1 "!" pub struct Bang/1 "^" pub struct Caret/1 "^=" pub struct CaretEq/2 ":" pub struct Colon/1 "::" pub struct Colon2/2 "," pub struct Comma/1 "/" pub struct Div/1 "/=" pub struct DivEq/2 "." pub struct Dot/1 ".." pub struct Dot2/2 "..." pub struct Dot3/3 "..=" pub struct DotDotEq/3 "=" pub struct Eq/1 "==" pub struct EqEq/2 ">=" pub struct Ge/2 ">" pub struct Gt/1 "<=" pub struct Le/2 "<" pub struct Lt/1 "*=" pub struct MulEq/2 "!=" pub struct Ne/2 "|" pub struct Or/1 "|=" pub struct OrEq/2 "||" pub struct OrOr/2 "#" pub struct Pound/1 "?" pub struct Question/1 "->" pub struct RArrow/2 "<-" pub struct LArrow/2 "%" pub struct Rem/1 "%=" pub struct RemEq/2 "=>" pub struct Rocket/2 ";" pub struct Semi/1 "<<" pub struct Shl/2 "<<=" pub struct ShlEq/3 ">>" pub struct Shr/2 ">>=" pub struct ShrEq/3 "*" pub struct Star/1 "-" pub struct Sub/1 "-=" pub struct SubEq/2 "_" pub struct Underscore/1 }
370 delimiter: {
371 "{" pub struct Brace "[" pub struct Bracket "(" pub struct Paren " " pub struct Group }
376 keyword: {
377 "as" pub struct As "auto" pub struct Auto "box" pub struct Box "break" pub struct Break "Self" pub struct CapSelf "catch" pub struct Catch "const" pub struct Const "continue" pub struct Continue "crate" pub struct Crate "default" pub struct Default "do" pub struct Do "dyn" pub struct Dyn "else" pub struct Else "enum" pub struct Enum "extern" pub struct Extern "fn" pub struct Fn "for" pub struct For "if" pub struct If "impl" pub struct Impl "in" pub struct In "let" pub struct Let "loop" pub struct Loop "macro" pub struct Macro "match" pub struct Match "mod" pub struct Mod "move" pub struct Move "mut" pub struct Mut "pub" pub struct Pub "ref" pub struct Ref "return" pub struct Return "self" pub struct Self_ "static" pub struct Static "struct" pub struct Struct "super" pub struct Super "trait" pub struct Trait "type" pub struct Type "union" pub struct Union "unsafe" pub struct Unsafe "use" pub struct Use "where" pub struct Where "while" pub struct While "yield" pub struct Yield }
420}
421
422#[macro_export]
431macro_rules! Token {
432 (+) => { $crate::token::Add };
433 (+=) => { $crate::token::AddEq };
434 (&) => { $crate::token::And };
435 (&&) => { $crate::token::AndAnd };
436 (&=) => { $crate::token::AndEq };
437 (@) => { $crate::token::At };
438 (!) => { $crate::token::Bang };
439 (^) => { $crate::token::Caret };
440 (^=) => { $crate::token::CaretEq };
441 (:) => { $crate::token::Colon };
442 (::) => { $crate::token::Colon2 };
443 (,) => { $crate::token::Comma };
444 (/) => { $crate::token::Div };
445 (/=) => { $crate::token::DivEq };
446 (.) => { $crate::token::Dot };
447 (..) => { $crate::token::Dot2 };
448 (...) => { $crate::token::Dot3 };
449 (..=) => { $crate::token::DotDotEq };
450 (=) => { $crate::token::Eq };
451 (==) => { $crate::token::EqEq };
452 (>=) => { $crate::token::Ge };
453 (>) => { $crate::token::Gt };
454 (<=) => { $crate::token::Le };
455 (<) => { $crate::token::Lt };
456 (*=) => { $crate::token::MulEq };
457 (!=) => { $crate::token::Ne };
458 (|) => { $crate::token::Or };
459 (|=) => { $crate::token::OrEq };
460 (||) => { $crate::token::OrOr };
461 (#) => { $crate::token::Pound };
462 (?) => { $crate::token::Question };
463 (->) => { $crate::token::RArrow };
464 (<-) => { $crate::token::LArrow };
465 (%) => { $crate::token::Rem };
466 (%=) => { $crate::token::RemEq };
467 (=>) => { $crate::token::Rocket };
468 (;) => { $crate::token::Semi };
469 (<<) => { $crate::token::Shl };
470 (<<=) => { $crate::token::ShlEq };
471 (>>) => { $crate::token::Shr };
472 (>>=) => { $crate::token::ShrEq };
473 (*) => { $crate::token::Star };
474 (-) => { $crate::token::Sub };
475 (-=) => { $crate::token::SubEq };
476 (_) => { $crate::token::Underscore };
477 (as) => { $crate::token::As };
478 (auto) => { $crate::token::Auto };
479 (box) => { $crate::token::Box };
480 (break) => { $crate::token::Break };
481 (Self) => { $crate::token::CapSelf };
482 (catch) => { $crate::token::Catch };
483 (const) => { $crate::token::Const };
484 (continue) => { $crate::token::Continue };
485 (crate) => { $crate::token::Crate };
486 (default) => { $crate::token::Default };
487 (do) => { $crate::token::Do };
488 (dyn) => { $crate::token::Dyn };
489 (else) => { $crate::token::Else };
490 (enum) => { $crate::token::Enum };
491 (extern) => { $crate::token::Extern };
492 (fn) => { $crate::token::Fn };
493 (for) => { $crate::token::For };
494 (if) => { $crate::token::If };
495 (impl) => { $crate::token::Impl };
496 (in) => { $crate::token::In };
497 (let) => { $crate::token::Let };
498 (loop) => { $crate::token::Loop };
499 (macro) => { $crate::token::Macro };
500 (match) => { $crate::token::Match };
501 (mod) => { $crate::token::Mod };
502 (move) => { $crate::token::Move };
503 (mut) => { $crate::token::Mut };
504 (pub) => { $crate::token::Pub };
505 (ref) => { $crate::token::Ref };
506 (return) => { $crate::token::Return };
507 (self) => { $crate::token::Self_ };
508 (static) => { $crate::token::Static };
509 (struct) => { $crate::token::Struct };
510 (super) => { $crate::token::Super };
511 (trait) => { $crate::token::Trait };
512 (type) => { $crate::token::Type };
513 (union) => { $crate::token::Union };
514 (unsafe) => { $crate::token::Unsafe };
515 (use) => { $crate::token::Use };
516 (where) => { $crate::token::Where };
517 (while) => { $crate::token::While };
518 (yield) => { $crate::token::Yield };
519}
520
521#[cfg(feature = "parsing")]
529#[macro_export]
530macro_rules! punct {
531 ($i:expr, +) => { call!($i, <$crate::token::Add as $crate::synom::Synom>::parse) };
532 ($i:expr, +=) => { call!($i, <$crate::token::AddEq as $crate::synom::Synom>::parse) };
533 ($i:expr, &) => { call!($i, <$crate::token::And as $crate::synom::Synom>::parse) };
534 ($i:expr, &&) => { call!($i, <$crate::token::AndAnd as $crate::synom::Synom>::parse) };
535 ($i:expr, &=) => { call!($i, <$crate::token::AndEq as $crate::synom::Synom>::parse) };
536 ($i:expr, @) => { call!($i, <$crate::token::At as $crate::synom::Synom>::parse) };
537 ($i:expr, !) => { call!($i, <$crate::token::Bang as $crate::synom::Synom>::parse) };
538 ($i:expr, ^) => { call!($i, <$crate::token::Caret as $crate::synom::Synom>::parse) };
539 ($i:expr, ^=) => { call!($i, <$crate::token::CaretEq as $crate::synom::Synom>::parse) };
540 ($i:expr, :) => { call!($i, <$crate::token::Colon as $crate::synom::Synom>::parse) };
541 ($i:expr, ::) => { call!($i, <$crate::token::Colon2 as $crate::synom::Synom>::parse) };
542 ($i:expr, ,) => { call!($i, <$crate::token::Comma as $crate::synom::Synom>::parse) };
543 ($i:expr, /) => { call!($i, <$crate::token::Div as $crate::synom::Synom>::parse) };
544 ($i:expr, /=) => { call!($i, <$crate::token::DivEq as $crate::synom::Synom>::parse) };
545 ($i:expr, .) => { call!($i, <$crate::token::Dot as $crate::synom::Synom>::parse) };
546 ($i:expr, ..) => { call!($i, <$crate::token::Dot2 as $crate::synom::Synom>::parse) };
547 ($i:expr, ...) => { call!($i, <$crate::token::Dot3 as $crate::synom::Synom>::parse) };
548 ($i:expr, ..=) => { call!($i, <$crate::token::DotDotEq as $crate::synom::Synom>::parse) };
549 ($i:expr, =) => { call!($i, <$crate::token::Eq as $crate::synom::Synom>::parse) };
550 ($i:expr, ==) => { call!($i, <$crate::token::EqEq as $crate::synom::Synom>::parse) };
551 ($i:expr, >=) => { call!($i, <$crate::token::Ge as $crate::synom::Synom>::parse) };
552 ($i:expr, >) => { call!($i, <$crate::token::Gt as $crate::synom::Synom>::parse) };
553 ($i:expr, <=) => { call!($i, <$crate::token::Le as $crate::synom::Synom>::parse) };
554 ($i:expr, <) => { call!($i, <$crate::token::Lt as $crate::synom::Synom>::parse) };
555 ($i:expr, *=) => { call!($i, <$crate::token::MulEq as $crate::synom::Synom>::parse) };
556 ($i:expr, !=) => { call!($i, <$crate::token::Ne as $crate::synom::Synom>::parse) };
557 ($i:expr, |) => { call!($i, <$crate::token::Or as $crate::synom::Synom>::parse) };
558 ($i:expr, |=) => { call!($i, <$crate::token::OrEq as $crate::synom::Synom>::parse) };
559 ($i:expr, ||) => { call!($i, <$crate::token::OrOr as $crate::synom::Synom>::parse) };
560 ($i:expr, #) => { call!($i, <$crate::token::Pound as $crate::synom::Synom>::parse) };
561 ($i:expr, ?) => { call!($i, <$crate::token::Question as $crate::synom::Synom>::parse) };
562 ($i:expr, ->) => { call!($i, <$crate::token::RArrow as $crate::synom::Synom>::parse) };
563 ($i:expr, <-) => { call!($i, <$crate::token::LArrow as $crate::synom::Synom>::parse) };
564 ($i:expr, %) => { call!($i, <$crate::token::Rem as $crate::synom::Synom>::parse) };
565 ($i:expr, %=) => { call!($i, <$crate::token::RemEq as $crate::synom::Synom>::parse) };
566 ($i:expr, =>) => { call!($i, <$crate::token::Rocket as $crate::synom::Synom>::parse) };
567 ($i:expr, ;) => { call!($i, <$crate::token::Semi as $crate::synom::Synom>::parse) };
568 ($i:expr, <<) => { call!($i, <$crate::token::Shl as $crate::synom::Synom>::parse) };
569 ($i:expr, <<=) => { call!($i, <$crate::token::ShlEq as $crate::synom::Synom>::parse) };
570 ($i:expr, >>) => { call!($i, <$crate::token::Shr as $crate::synom::Synom>::parse) };
571 ($i:expr, >>=) => { call!($i, <$crate::token::ShrEq as $crate::synom::Synom>::parse) };
572 ($i:expr, *) => { call!($i, <$crate::token::Star as $crate::synom::Synom>::parse) };
573 ($i:expr, -) => { call!($i, <$crate::token::Sub as $crate::synom::Synom>::parse) };
574 ($i:expr, -=) => { call!($i, <$crate::token::SubEq as $crate::synom::Synom>::parse) };
575 ($i:expr, _) => { call!($i, <$crate::token::Underscore as $crate::synom::Synom>::parse) };
576}
577
578#[cfg(feature = "parsing")]
586#[macro_export]
587macro_rules! keyword {
588 ($i:expr, as) => { call!($i, <$crate::token::As as $crate::synom::Synom>::parse) };
589 ($i:expr, auto) => { call!($i, <$crate::token::Auto as $crate::synom::Synom>::parse) };
590 ($i:expr, box) => { call!($i, <$crate::token::Box as $crate::synom::Synom>::parse) };
591 ($i:expr, break) => { call!($i, <$crate::token::Break as $crate::synom::Synom>::parse) };
592 ($i:expr, Self) => { call!($i, <$crate::token::CapSelf as $crate::synom::Synom>::parse) };
593 ($i:expr, catch) => { call!($i, <$crate::token::Catch as $crate::synom::Synom>::parse) };
594 ($i:expr, const) => { call!($i, <$crate::token::Const as $crate::synom::Synom>::parse) };
595 ($i:expr, continue) => { call!($i, <$crate::token::Continue as $crate::synom::Synom>::parse) };
596 ($i:expr, crate) => { call!($i, <$crate::token::Crate as $crate::synom::Synom>::parse) };
597 ($i:expr, default) => { call!($i, <$crate::token::Default as $crate::synom::Synom>::parse) };
598 ($i:expr, do) => { call!($i, <$crate::token::Do as $crate::synom::Synom>::parse) };
599 ($i:expr, dyn) => { call!($i, <$crate::token::Dyn as $crate::synom::Synom>::parse) };
600 ($i:expr, else) => { call!($i, <$crate::token::Else as $crate::synom::Synom>::parse) };
601 ($i:expr, enum) => { call!($i, <$crate::token::Enum as $crate::synom::Synom>::parse) };
602 ($i:expr, extern) => { call!($i, <$crate::token::Extern as $crate::synom::Synom>::parse) };
603 ($i:expr, fn) => { call!($i, <$crate::token::Fn as $crate::synom::Synom>::parse) };
604 ($i:expr, for) => { call!($i, <$crate::token::For as $crate::synom::Synom>::parse) };
605 ($i:expr, if) => { call!($i, <$crate::token::If as $crate::synom::Synom>::parse) };
606 ($i:expr, impl) => { call!($i, <$crate::token::Impl as $crate::synom::Synom>::parse) };
607 ($i:expr, in) => { call!($i, <$crate::token::In as $crate::synom::Synom>::parse) };
608 ($i:expr, let) => { call!($i, <$crate::token::Let as $crate::synom::Synom>::parse) };
609 ($i:expr, loop) => { call!($i, <$crate::token::Loop as $crate::synom::Synom>::parse) };
610 ($i:expr, macro) => { call!($i, <$crate::token::Macro as $crate::synom::Synom>::parse) };
611 ($i:expr, match) => { call!($i, <$crate::token::Match as $crate::synom::Synom>::parse) };
612 ($i:expr, mod) => { call!($i, <$crate::token::Mod as $crate::synom::Synom>::parse) };
613 ($i:expr, move) => { call!($i, <$crate::token::Move as $crate::synom::Synom>::parse) };
614 ($i:expr, mut) => { call!($i, <$crate::token::Mut as $crate::synom::Synom>::parse) };
615 ($i:expr, pub) => { call!($i, <$crate::token::Pub as $crate::synom::Synom>::parse) };
616 ($i:expr, ref) => { call!($i, <$crate::token::Ref as $crate::synom::Synom>::parse) };
617 ($i:expr, return) => { call!($i, <$crate::token::Return as $crate::synom::Synom>::parse) };
618 ($i:expr, self) => { call!($i, <$crate::token::Self_ as $crate::synom::Synom>::parse) };
619 ($i:expr, static) => { call!($i, <$crate::token::Static as $crate::synom::Synom>::parse) };
620 ($i:expr, struct) => { call!($i, <$crate::token::Struct as $crate::synom::Synom>::parse) };
621 ($i:expr, super) => { call!($i, <$crate::token::Super as $crate::synom::Synom>::parse) };
622 ($i:expr, trait) => { call!($i, <$crate::token::Trait as $crate::synom::Synom>::parse) };
623 ($i:expr, type) => { call!($i, <$crate::token::Type as $crate::synom::Synom>::parse) };
624 ($i:expr, union) => { call!($i, <$crate::token::Union as $crate::synom::Synom>::parse) };
625 ($i:expr, unsafe) => { call!($i, <$crate::token::Unsafe as $crate::synom::Synom>::parse) };
626 ($i:expr, use) => { call!($i, <$crate::token::Use as $crate::synom::Synom>::parse) };
627 ($i:expr, where) => { call!($i, <$crate::token::Where as $crate::synom::Synom>::parse) };
628 ($i:expr, while) => { call!($i, <$crate::token::While as $crate::synom::Synom>::parse) };
629 ($i:expr, yield) => { call!($i, <$crate::token::Yield as $crate::synom::Synom>::parse) };
630}
631
632#[cfg(feature = "parsing")]
633mod parsing {
634 use proc_macro2::{Delimiter, Spacing, Span};
635
636 use buffer::Cursor;
637 use parse_error;
638 use synom::PResult;
639
640 pub trait FromSpans: Sized {
641 fn from_spans(spans: &[Span]) -> Self;
642 }
643
644 impl FromSpans for [Span; 1] {
645 fn from_spans(spans: &[Span]) -> Self {
646 [spans[0]]
647 }
648 }
649
650 impl FromSpans for [Span; 2] {
651 fn from_spans(spans: &[Span]) -> Self {
652 [spans[0], spans[1]]
653 }
654 }
655
656 impl FromSpans for [Span; 3] {
657 fn from_spans(spans: &[Span]) -> Self {
658 [spans[0], spans[1], spans[2]]
659 }
660 }
661
662 pub fn punct<'a, T, R>(s: &str, mut tokens: Cursor<'a>, new: fn(T) -> R) -> PResult<'a, R>
663 where
664 T: FromSpans,
665 {
666 let mut spans = [Span::def_site(); 3];
667 assert!(s.len() <= spans.len());
668 let chars = s.chars();
669
670 for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
671 match tokens.op() {
672 Some((span, op, kind, rest)) if op == ch => {
673 if i != s.len() - 1 {
674 match kind {
675 Spacing::Joint => {}
676 _ => return parse_error(),
677 }
678 }
679 *slot = span;
680 tokens = rest;
681 }
682 _ => return parse_error(),
683 }
684 }
685 Ok((new(T::from_spans(&spans)), tokens))
686 }
687
688 pub fn keyword<'a, T>(keyword: &str, tokens: Cursor<'a>, new: fn(Span) -> T) -> PResult<'a, T> {
689 if let Some((span, term, rest)) = tokens.term() {
690 if term.as_str() == keyword {
691 return Ok((new(span), rest));
692 }
693 }
694 parse_error()
695 }
696
697 pub fn delim<'a, F, R, T>(
698 delim: &str,
699 tokens: Cursor<'a>,
700 new: fn(Span) -> T,
701 f: F,
702 ) -> PResult<'a, (T, R)>
703 where
704 F: FnOnce(Cursor) -> PResult<R>,
705 {
706 let delim = match delim {
708 "(" => Delimiter::Parenthesis,
709 "{" => Delimiter::Brace,
710 "[" => Delimiter::Bracket,
711 " " => Delimiter::None,
712 _ => panic!("unknown delimiter: {}", delim),
713 };
714
715 if let Some((inside, span, rest)) = tokens.group(delim) {
716 match f(inside) {
717 Ok((ret, remaining)) => {
718 if remaining.eof() {
719 return Ok(((new(span), ret), rest));
720 }
721 }
722 Err(err) => return Err(err),
723 }
724 }
725 parse_error()
726 }
727}
728
729#[cfg(feature = "printing")]
730mod printing {
731 use proc_macro2::{Delimiter, Spacing, Span, Term, TokenNode, TokenTree};
732 use quote::Tokens;
733
734 pub fn punct(s: &str, spans: &[Span], tokens: &mut Tokens) {
735 assert_eq!(s.len(), spans.len());
736
737 let mut chars = s.chars();
738 let mut spans = spans.iter();
739 let ch = chars.next_back().unwrap();
740 let span = spans.next_back().unwrap();
741 for (ch, span) in chars.zip(spans) {
742 tokens.append(TokenTree {
743 span: *span,
744 kind: TokenNode::Op(ch, Spacing::Joint),
745 });
746 }
747
748 tokens.append(TokenTree {
749 span: *span,
750 kind: TokenNode::Op(ch, Spacing::Alone),
751 });
752 }
753
754 pub fn keyword(s: &str, span: &Span, tokens: &mut Tokens) {
755 tokens.append(TokenTree {
756 span: *span,
757 kind: TokenNode::Term(Term::intern(s)),
758 });
759 }
760
761 pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
762 where
763 F: FnOnce(&mut Tokens),
764 {
765 let delim = match s {
766 "(" => Delimiter::Parenthesis,
767 "[" => Delimiter::Bracket,
768 "{" => Delimiter::Brace,
769 " " => Delimiter::None,
770 _ => panic!("unknown delimiter: {}", s),
771 };
772 let mut inner = Tokens::new();
773 f(&mut inner);
774 tokens.append(TokenTree {
775 span: *span,
776 kind: TokenNode::Group(delim, inner.into()),
777 });
778 }
779}