blob: eb5d6e0bfa62edf65aad768629511bb07cacb139 [file] [log] [blame]
Alex Crichton954046c2017-05-30 21:49:42 -07001//! Discrete tokens that can be parsed out by synom.
2//!
3//! This module contains a number of useful tokens like `+=` and `/` along with
4//! keywords like `crate` and such. These structures are used to track the spans
5//! of these tokens and all implment the `ToTokens` and `Synom` traits when the
6//! corresponding feature is activated.
7
David Tolnay98942562017-12-26 21:24:35 -05008use proc_macro2::Span;
Alex Crichton7b9e02f2017-05-30 15:54:33 -07009
10macro_rules! tokens {
11 (
12 ops: {
13 $(($($op:tt)*),)*
14 }
15 delim: {
16 $(($($delim:tt)*),)*
17 }
18 syms: {
19 $(($($sym:tt)*),)*
20 }
21 ) => (
22 $(op! { $($op)* })*
23 $(delim! { $($delim)* })*
24 $(sym! { $($sym)* })*
25 )
26}
27
28macro_rules! op {
29 (pub struct $name:ident($($contents:tt)*) => $s:expr) => {
30 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070031 #[derive(Default)]
32 pub struct $name(pub $($contents)*);
33
Nika Layzelld73a3652017-10-24 08:57:05 -040034 #[cfg(feature = "extra-traits")]
35 impl ::std::fmt::Debug for $name {
36 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
David Tolnay98942562017-12-26 21:24:35 -050037 f.write_str(stringify!($name))
Nika Layzelld73a3652017-10-24 08:57:05 -040038 }
39 }
40
David Tolnay98942562017-12-26 21:24:35 -050041 #[cfg(feature = "extra-traits")]
42 impl ::std::cmp::Eq for $name {}
43
44 #[cfg(feature = "extra-traits")]
45 impl ::std::cmp::PartialEq for $name {
46 fn eq(&self, _other: &$name) -> bool {
47 true
48 }
49 }
50
51 #[cfg(feature = "extra-traits")]
52 impl ::std::hash::Hash for $name {
53 fn hash<H>(&self, _state: &mut H)
54 where H: ::std::hash::Hasher
55 {}
56 }
57
Alex Crichton7b9e02f2017-05-30 15:54:33 -070058 #[cfg(feature = "printing")]
59 impl ::quote::ToTokens for $name {
60 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
61 printing::op($s, &self.0, tokens);
62 }
63 }
64
65 #[cfg(feature = "parsing")]
66 impl ::Synom for $name {
David Tolnayc5ab8c62017-12-26 16:43:39 -050067 fn parse(tokens: $crate::synom::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -070068 parsing::op($s, tokens, $name)
69 }
70 }
71 }
72}
73
74macro_rules! sym {
75 (pub struct $name:ident => $s:expr) => {
76 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070077 #[derive(Default)]
78 pub struct $name(pub Span);
79
David Tolnay98942562017-12-26 21:24:35 -050080 #[cfg(feature = "extra-traits")]
81 impl ::std::fmt::Debug for $name {
82 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
83 f.write_str(stringify!($name))
84 }
85 }
86
87 #[cfg(feature = "extra-traits")]
88 impl ::std::cmp::Eq for $name {}
89
90 #[cfg(feature = "extra-traits")]
91 impl ::std::cmp::PartialEq for $name {
92 fn eq(&self, _other: &$name) -> bool {
93 true
94 }
95 }
96
97 #[cfg(feature = "extra-traits")]
98 impl ::std::hash::Hash for $name {
99 fn hash<H>(&self, _state: &mut H)
100 where H: ::std::hash::Hasher
101 {}
102 }
103
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700104 #[cfg(feature = "printing")]
105 impl ::quote::ToTokens for $name {
106 fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
107 printing::sym($s, &self.0, tokens);
108 }
109 }
110
111 #[cfg(feature = "parsing")]
112 impl ::Synom for $name {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500113 fn parse(tokens: $crate::synom::Cursor) -> $crate::PResult<$name> {
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700114 parsing::sym($s, tokens, $name)
115 }
116 }
117 }
118}
119
120macro_rules! delim {
121 (pub struct $name:ident => $s:expr) => {
122 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700123 #[derive(Default)]
124 pub struct $name(pub Span);
125
David Tolnay98942562017-12-26 21:24:35 -0500126 #[cfg(feature = "extra-traits")]
127 impl ::std::fmt::Debug for $name {
128 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
129 f.write_str(stringify!($name))
130 }
131 }
132
133 #[cfg(feature = "extra-traits")]
134 impl ::std::cmp::Eq for $name {}
135
136 #[cfg(feature = "extra-traits")]
137 impl ::std::cmp::PartialEq for $name {
138 fn eq(&self, _other: &$name) -> bool {
139 true
140 }
141 }
142
143 #[cfg(feature = "extra-traits")]
144 impl ::std::hash::Hash for $name {
145 fn hash<H>(&self, _state: &mut H)
146 where H: ::std::hash::Hasher
147 {}
148 }
149
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700150 impl $name {
151 #[cfg(feature = "printing")]
152 pub fn surround<F>(&self,
153 tokens: &mut ::quote::Tokens,
154 f: F)
155 where F: FnOnce(&mut ::quote::Tokens)
156 {
157 printing::delim($s, &self.0, tokens, f);
158 }
159
160 #[cfg(feature = "parsing")]
David Tolnayc5ab8c62017-12-26 16:43:39 -0500161 pub fn parse<F, R>(tokens: $crate::synom::Cursor, f: F) -> $crate::PResult<(R, $name)>
162 where F: FnOnce($crate::synom::Cursor) -> $crate::PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700163 {
164 parsing::delim($s, tokens, $name, f)
165 }
166 }
167 }
168}
169
170tokens! {
171 ops: {
172 (pub struct Add([Span; 1]) => "+"),
173 (pub struct AddEq([Span; 2]) => "+="),
174 (pub struct And([Span; 1]) => "&"),
175 (pub struct AndAnd([Span; 2]) => "&&"),
176 (pub struct AndEq([Span; 2]) => "&="),
177 (pub struct At([Span; 1]) => "@"),
178 (pub struct Bang([Span; 1]) => "!"),
179 (pub struct Caret([Span; 1]) => "^"),
180 (pub struct CaretEq([Span; 2]) => "^="),
181 (pub struct Colon([Span; 1]) => ":"),
182 (pub struct Colon2([Span; 2]) => "::"),
183 (pub struct Comma([Span; 1]) => ","),
184 (pub struct Div([Span; 1]) => "/"),
185 (pub struct DivEq([Span; 2]) => "/="),
186 (pub struct Dot([Span; 1]) => "."),
187 (pub struct Dot2([Span; 2]) => ".."),
188 (pub struct Dot3([Span; 3]) => "..."),
David Tolnaybe55d7b2017-12-17 23:41:20 -0800189 (pub struct DotDotEq([Span; 3]) => "..="),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700190 (pub struct Eq([Span; 1]) => "="),
191 (pub struct EqEq([Span; 2]) => "=="),
192 (pub struct Ge([Span; 2]) => ">="),
193 (pub struct Gt([Span; 1]) => ">"),
194 (pub struct Le([Span; 2]) => "<="),
195 (pub struct Lt([Span; 1]) => "<"),
196 (pub struct MulEq([Span; 2]) => "*="),
197 (pub struct Ne([Span; 2]) => "!="),
198 (pub struct Or([Span; 1]) => "|"),
199 (pub struct OrEq([Span; 2]) => "|="),
200 (pub struct OrOr([Span; 2]) => "||"),
201 (pub struct Pound([Span; 1]) => "#"),
202 (pub struct Question([Span; 1]) => "?"),
203 (pub struct RArrow([Span; 2]) => "->"),
Michael Layzellb78f3b52017-06-04 19:03:03 -0400204 (pub struct LArrow([Span; 2]) => "<-"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700205 (pub struct Rem([Span; 1]) => "%"),
206 (pub struct RemEq([Span; 2]) => "%="),
207 (pub struct Rocket([Span; 2]) => "=>"),
208 (pub struct Semi([Span; 1]) => ";"),
209 (pub struct Shl([Span; 2]) => "<<"),
210 (pub struct ShlEq([Span; 3]) => "<<="),
211 (pub struct Shr([Span; 2]) => ">>"),
212 (pub struct ShrEq([Span; 3]) => ">>="),
213 (pub struct Star([Span; 1]) => "*"),
214 (pub struct Sub([Span; 1]) => "-"),
215 (pub struct SubEq([Span; 2]) => "-="),
216 (pub struct Underscore([Span; 1]) => "_"),
217 }
218 delim: {
219 (pub struct Brace => "{"),
220 (pub struct Bracket => "["),
221 (pub struct Paren => "("),
Michael Layzell93c36282017-06-04 20:43:14 -0400222 (pub struct Group => " "),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700223 }
224 syms: {
225 (pub struct As => "as"),
Nika Layzell0dc6e632017-11-18 12:55:25 -0500226 (pub struct Auto => "auto"),
David Tolnayf8db7ba2017-11-11 22:52:16 -0800227 (pub struct Box => "box"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700228 (pub struct Break => "break"),
Alex Crichton954046c2017-05-30 21:49:42 -0700229 (pub struct CapSelf => "Self"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700230 (pub struct Catch => "catch"),
231 (pub struct Const => "const"),
232 (pub struct Continue => "continue"),
233 (pub struct Crate => "crate"),
David Tolnayf8db7ba2017-11-11 22:52:16 -0800234 (pub struct Default => "default"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700235 (pub struct Do => "do"),
David Tolnaye45b59f2017-12-25 18:44:49 -0500236 (pub struct Dyn => "dyn"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700237 (pub struct Else => "else"),
238 (pub struct Enum => "enum"),
239 (pub struct Extern => "extern"),
David Tolnayf8db7ba2017-11-11 22:52:16 -0800240 (pub struct Fn => "fn"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700241 (pub struct For => "for"),
242 (pub struct If => "if"),
243 (pub struct Impl => "impl"),
244 (pub struct In => "in"),
245 (pub struct Let => "let"),
246 (pub struct Loop => "loop"),
David Tolnay500d8322017-12-18 00:32:51 -0800247 (pub struct Macro => "macro"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700248 (pub struct Match => "match"),
249 (pub struct Mod => "mod"),
250 (pub struct Move => "move"),
251 (pub struct Mut => "mut"),
252 (pub struct Pub => "pub"),
253 (pub struct Ref => "ref"),
254 (pub struct Return => "return"),
255 (pub struct Self_ => "self"),
256 (pub struct Static => "static"),
257 (pub struct Struct => "struct"),
Alex Crichton954046c2017-05-30 21:49:42 -0700258 (pub struct Super => "super"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700259 (pub struct Trait => "trait"),
260 (pub struct Type => "type"),
261 (pub struct Union => "union"),
262 (pub struct Unsafe => "unsafe"),
263 (pub struct Use => "use"),
264 (pub struct Where => "where"),
265 (pub struct While => "while"),
Alex Crichtonfe110462017-06-01 12:49:27 -0700266 (pub struct Yield => "yield"),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700267 }
268}
269
David Tolnayf8db7ba2017-11-11 22:52:16 -0800270// Unfortunate duplication due to a rustdoc bug.
271// https://github.com/rust-lang/rust/issues/45939
272#[macro_export]
273macro_rules! Token {
274 (+) => { $crate::tokens::Add };
275 (+=) => { $crate::tokens::AddEq };
276 (&) => { $crate::tokens::And };
277 (&&) => { $crate::tokens::AndAnd };
278 (&=) => { $crate::tokens::AndEq };
279 (@) => { $crate::tokens::At };
280 (!) => { $crate::tokens::Bang };
281 (^) => { $crate::tokens::Caret };
282 (^=) => { $crate::tokens::CaretEq };
283 (:) => { $crate::tokens::Colon };
284 (::) => { $crate::tokens::Colon2 };
285 (,) => { $crate::tokens::Comma };
286 (/) => { $crate::tokens::Div };
287 (/=) => { $crate::tokens::DivEq };
288 (.) => { $crate::tokens::Dot };
289 (..) => { $crate::tokens::Dot2 };
290 (...) => { $crate::tokens::Dot3 };
David Tolnaybe55d7b2017-12-17 23:41:20 -0800291 (..=) => { $crate::tokens::DotDotEq };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800292 (=) => { $crate::tokens::Eq };
293 (==) => { $crate::tokens::EqEq };
294 (>=) => { $crate::tokens::Ge };
295 (>) => { $crate::tokens::Gt };
296 (<=) => { $crate::tokens::Le };
297 (<) => { $crate::tokens::Lt };
298 (*=) => { $crate::tokens::MulEq };
299 (!=) => { $crate::tokens::Ne };
300 (|) => { $crate::tokens::Or };
301 (|=) => { $crate::tokens::OrEq };
302 (||) => { $crate::tokens::OrOr };
303 (#) => { $crate::tokens::Pound };
304 (?) => { $crate::tokens::Question };
305 (->) => { $crate::tokens::RArrow };
306 (<-) => { $crate::tokens::LArrow };
307 (%) => { $crate::tokens::Rem };
308 (%=) => { $crate::tokens::RemEq };
309 (=>) => { $crate::tokens::Rocket };
310 (;) => { $crate::tokens::Semi };
311 (<<) => { $crate::tokens::Shl };
312 (<<=) => { $crate::tokens::ShlEq };
313 (>>) => { $crate::tokens::Shr };
314 (>>=) => { $crate::tokens::ShrEq };
315 (*) => { $crate::tokens::Star };
316 (-) => { $crate::tokens::Sub };
317 (-=) => { $crate::tokens::SubEq };
318 (_) => { $crate::tokens::Underscore };
319 (as) => { $crate::tokens::As };
Nika Layzell0dc6e632017-11-18 12:55:25 -0500320 (auto) => { $crate::tokens::Auto };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 (box) => { $crate::tokens::Box };
322 (break) => { $crate::tokens::Break };
323 (Self) => { $crate::tokens::CapSelf };
324 (catch) => { $crate::tokens::Catch };
325 (const) => { $crate::tokens::Const };
326 (continue) => { $crate::tokens::Continue };
327 (crate) => { $crate::tokens::Crate };
328 (default) => { $crate::tokens::Default };
329 (do) => { $crate::tokens::Do };
David Tolnaye45b59f2017-12-25 18:44:49 -0500330 (dyn) => { $crate::tokens::Dyn };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800331 (else) => { $crate::tokens::Else };
332 (enum) => { $crate::tokens::Enum };
333 (extern) => { $crate::tokens::Extern };
334 (fn) => { $crate::tokens::Fn };
335 (for) => { $crate::tokens::For };
336 (if) => { $crate::tokens::If };
337 (impl) => { $crate::tokens::Impl };
338 (in) => { $crate::tokens::In };
339 (let) => { $crate::tokens::Let };
340 (loop) => { $crate::tokens::Loop };
David Tolnay500d8322017-12-18 00:32:51 -0800341 (macro) => { $crate::tokens::Macro };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800342 (match) => { $crate::tokens::Match };
343 (mod) => { $crate::tokens::Mod };
344 (move) => { $crate::tokens::Move };
345 (mut) => { $crate::tokens::Mut };
346 (pub) => { $crate::tokens::Pub };
347 (ref) => { $crate::tokens::Ref };
348 (return) => { $crate::tokens::Return };
349 (self) => { $crate::tokens::Self_ };
350 (static) => { $crate::tokens::Static };
351 (struct) => { $crate::tokens::Struct };
352 (super) => { $crate::tokens::Super };
353 (trait) => { $crate::tokens::Trait };
354 (type) => { $crate::tokens::Type };
355 (union) => { $crate::tokens::Union };
356 (unsafe) => { $crate::tokens::Unsafe };
357 (use) => { $crate::tokens::Use };
358 (where) => { $crate::tokens::Where };
359 (while) => { $crate::tokens::While };
360 (yield) => { $crate::tokens::Yield };
361}
362
David Tolnay0fbe3282017-12-26 21:46:16 -0500363#[cfg(feature = "parsing")]
David Tolnayf8db7ba2017-11-11 22:52:16 -0800364#[macro_export]
365macro_rules! punct {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500366 ($i:expr, +) => { call!($i, <$crate::tokens::Add as $crate::synom::Synom>::parse) };
367 ($i:expr, +=) => { call!($i, <$crate::tokens::AddEq as $crate::synom::Synom>::parse) };
368 ($i:expr, &) => { call!($i, <$crate::tokens::And as $crate::synom::Synom>::parse) };
369 ($i:expr, &&) => { call!($i, <$crate::tokens::AndAnd as $crate::synom::Synom>::parse) };
370 ($i:expr, &=) => { call!($i, <$crate::tokens::AndEq as $crate::synom::Synom>::parse) };
371 ($i:expr, @) => { call!($i, <$crate::tokens::At as $crate::synom::Synom>::parse) };
372 ($i:expr, !) => { call!($i, <$crate::tokens::Bang as $crate::synom::Synom>::parse) };
373 ($i:expr, ^) => { call!($i, <$crate::tokens::Caret as $crate::synom::Synom>::parse) };
374 ($i:expr, ^=) => { call!($i, <$crate::tokens::CaretEq as $crate::synom::Synom>::parse) };
375 ($i:expr, :) => { call!($i, <$crate::tokens::Colon as $crate::synom::Synom>::parse) };
376 ($i:expr, ::) => { call!($i, <$crate::tokens::Colon2 as $crate::synom::Synom>::parse) };
377 ($i:expr, ,) => { call!($i, <$crate::tokens::Comma as $crate::synom::Synom>::parse) };
378 ($i:expr, /) => { call!($i, <$crate::tokens::Div as $crate::synom::Synom>::parse) };
379 ($i:expr, /=) => { call!($i, <$crate::tokens::DivEq as $crate::synom::Synom>::parse) };
380 ($i:expr, .) => { call!($i, <$crate::tokens::Dot as $crate::synom::Synom>::parse) };
381 ($i:expr, ..) => { call!($i, <$crate::tokens::Dot2 as $crate::synom::Synom>::parse) };
382 ($i:expr, ...) => { call!($i, <$crate::tokens::Dot3 as $crate::synom::Synom>::parse) };
383 ($i:expr, ..=) => { call!($i, <$crate::tokens::DotDotEq as $crate::synom::Synom>::parse) };
384 ($i:expr, =) => { call!($i, <$crate::tokens::Eq as $crate::synom::Synom>::parse) };
385 ($i:expr, ==) => { call!($i, <$crate::tokens::EqEq as $crate::synom::Synom>::parse) };
386 ($i:expr, >=) => { call!($i, <$crate::tokens::Ge as $crate::synom::Synom>::parse) };
387 ($i:expr, >) => { call!($i, <$crate::tokens::Gt as $crate::synom::Synom>::parse) };
388 ($i:expr, <=) => { call!($i, <$crate::tokens::Le as $crate::synom::Synom>::parse) };
389 ($i:expr, <) => { call!($i, <$crate::tokens::Lt as $crate::synom::Synom>::parse) };
390 ($i:expr, *=) => { call!($i, <$crate::tokens::MulEq as $crate::synom::Synom>::parse) };
391 ($i:expr, !=) => { call!($i, <$crate::tokens::Ne as $crate::synom::Synom>::parse) };
392 ($i:expr, |) => { call!($i, <$crate::tokens::Or as $crate::synom::Synom>::parse) };
393 ($i:expr, |=) => { call!($i, <$crate::tokens::OrEq as $crate::synom::Synom>::parse) };
394 ($i:expr, ||) => { call!($i, <$crate::tokens::OrOr as $crate::synom::Synom>::parse) };
395 ($i:expr, #) => { call!($i, <$crate::tokens::Pound as $crate::synom::Synom>::parse) };
396 ($i:expr, ?) => { call!($i, <$crate::tokens::Question as $crate::synom::Synom>::parse) };
397 ($i:expr, ->) => { call!($i, <$crate::tokens::RArrow as $crate::synom::Synom>::parse) };
398 ($i:expr, <-) => { call!($i, <$crate::tokens::LArrow as $crate::synom::Synom>::parse) };
399 ($i:expr, %) => { call!($i, <$crate::tokens::Rem as $crate::synom::Synom>::parse) };
400 ($i:expr, %=) => { call!($i, <$crate::tokens::RemEq as $crate::synom::Synom>::parse) };
401 ($i:expr, =>) => { call!($i, <$crate::tokens::Rocket as $crate::synom::Synom>::parse) };
402 ($i:expr, ;) => { call!($i, <$crate::tokens::Semi as $crate::synom::Synom>::parse) };
403 ($i:expr, <<) => { call!($i, <$crate::tokens::Shl as $crate::synom::Synom>::parse) };
404 ($i:expr, <<=) => { call!($i, <$crate::tokens::ShlEq as $crate::synom::Synom>::parse) };
405 ($i:expr, >>) => { call!($i, <$crate::tokens::Shr as $crate::synom::Synom>::parse) };
406 ($i:expr, >>=) => { call!($i, <$crate::tokens::ShrEq as $crate::synom::Synom>::parse) };
407 ($i:expr, *) => { call!($i, <$crate::tokens::Star as $crate::synom::Synom>::parse) };
408 ($i:expr, -) => { call!($i, <$crate::tokens::Sub as $crate::synom::Synom>::parse) };
409 ($i:expr, -=) => { call!($i, <$crate::tokens::SubEq as $crate::synom::Synom>::parse) };
410 ($i:expr, _) => { call!($i, <$crate::tokens::Underscore as $crate::synom::Synom>::parse) };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800411}
412
David Tolnay0fbe3282017-12-26 21:46:16 -0500413#[cfg(feature = "parsing")]
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414#[macro_export]
415macro_rules! keyword {
David Tolnayc5ab8c62017-12-26 16:43:39 -0500416 ($i:expr, as) => { call!($i, <$crate::tokens::As as $crate::synom::Synom>::parse) };
417 ($i:expr, auto) => { call!($i, <$crate::tokens::Auto as $crate::synom::Synom>::parse) };
418 ($i:expr, box) => { call!($i, <$crate::tokens::Box as $crate::synom::Synom>::parse) };
419 ($i:expr, break) => { call!($i, <$crate::tokens::Break as $crate::synom::Synom>::parse) };
420 ($i:expr, Self) => { call!($i, <$crate::tokens::CapSelf as $crate::synom::Synom>::parse) };
421 ($i:expr, catch) => { call!($i, <$crate::tokens::Catch as $crate::synom::Synom>::parse) };
422 ($i:expr, const) => { call!($i, <$crate::tokens::Const as $crate::synom::Synom>::parse) };
423 ($i:expr, continue) => { call!($i, <$crate::tokens::Continue as $crate::synom::Synom>::parse) };
424 ($i:expr, crate) => { call!($i, <$crate::tokens::Crate as $crate::synom::Synom>::parse) };
425 ($i:expr, default) => { call!($i, <$crate::tokens::Default as $crate::synom::Synom>::parse) };
426 ($i:expr, do) => { call!($i, <$crate::tokens::Do as $crate::synom::Synom>::parse) };
427 ($i:expr, dyn) => { call!($i, <$crate::tokens::Dyn as $crate::synom::Synom>::parse) };
428 ($i:expr, else) => { call!($i, <$crate::tokens::Else as $crate::synom::Synom>::parse) };
429 ($i:expr, enum) => { call!($i, <$crate::tokens::Enum as $crate::synom::Synom>::parse) };
430 ($i:expr, extern) => { call!($i, <$crate::tokens::Extern as $crate::synom::Synom>::parse) };
431 ($i:expr, fn) => { call!($i, <$crate::tokens::Fn as $crate::synom::Synom>::parse) };
432 ($i:expr, for) => { call!($i, <$crate::tokens::For as $crate::synom::Synom>::parse) };
433 ($i:expr, if) => { call!($i, <$crate::tokens::If as $crate::synom::Synom>::parse) };
434 ($i:expr, impl) => { call!($i, <$crate::tokens::Impl as $crate::synom::Synom>::parse) };
435 ($i:expr, in) => { call!($i, <$crate::tokens::In as $crate::synom::Synom>::parse) };
436 ($i:expr, let) => { call!($i, <$crate::tokens::Let as $crate::synom::Synom>::parse) };
437 ($i:expr, loop) => { call!($i, <$crate::tokens::Loop as $crate::synom::Synom>::parse) };
438 ($i:expr, macro) => { call!($i, <$crate::tokens::Macro as $crate::synom::Synom>::parse) };
439 ($i:expr, match) => { call!($i, <$crate::tokens::Match as $crate::synom::Synom>::parse) };
440 ($i:expr, mod) => { call!($i, <$crate::tokens::Mod as $crate::synom::Synom>::parse) };
441 ($i:expr, move) => { call!($i, <$crate::tokens::Move as $crate::synom::Synom>::parse) };
442 ($i:expr, mut) => { call!($i, <$crate::tokens::Mut as $crate::synom::Synom>::parse) };
443 ($i:expr, pub) => { call!($i, <$crate::tokens::Pub as $crate::synom::Synom>::parse) };
444 ($i:expr, ref) => { call!($i, <$crate::tokens::Ref as $crate::synom::Synom>::parse) };
445 ($i:expr, return) => { call!($i, <$crate::tokens::Return as $crate::synom::Synom>::parse) };
446 ($i:expr, self) => { call!($i, <$crate::tokens::Self_ as $crate::synom::Synom>::parse) };
447 ($i:expr, static) => { call!($i, <$crate::tokens::Static as $crate::synom::Synom>::parse) };
448 ($i:expr, struct) => { call!($i, <$crate::tokens::Struct as $crate::synom::Synom>::parse) };
449 ($i:expr, super) => { call!($i, <$crate::tokens::Super as $crate::synom::Synom>::parse) };
450 ($i:expr, trait) => { call!($i, <$crate::tokens::Trait as $crate::synom::Synom>::parse) };
451 ($i:expr, type) => { call!($i, <$crate::tokens::Type as $crate::synom::Synom>::parse) };
452 ($i:expr, union) => { call!($i, <$crate::tokens::Union as $crate::synom::Synom>::parse) };
453 ($i:expr, unsafe) => { call!($i, <$crate::tokens::Unsafe as $crate::synom::Synom>::parse) };
454 ($i:expr, use) => { call!($i, <$crate::tokens::Use as $crate::synom::Synom>::parse) };
455 ($i:expr, where) => { call!($i, <$crate::tokens::Where as $crate::synom::Synom>::parse) };
456 ($i:expr, while) => { call!($i, <$crate::tokens::While as $crate::synom::Synom>::parse) };
457 ($i:expr, yield) => { call!($i, <$crate::tokens::Yield as $crate::synom::Synom>::parse) };
David Tolnayf8db7ba2017-11-11 22:52:16 -0800458}
459
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700460#[cfg(feature = "parsing")]
461mod parsing {
David Tolnay98942562017-12-26 21:24:35 -0500462 use proc_macro2::{Span, Delimiter, Spacing};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700463
David Tolnayc5ab8c62017-12-26 16:43:39 -0500464 use cursor::Cursor;
David Tolnay98942562017-12-26 21:24:35 -0500465 use {PResult, parse_error};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700466
467 pub trait FromSpans: Sized {
468 fn from_spans(spans: &[Span]) -> Self;
469 }
470
471 impl FromSpans for [Span; 1] {
472 fn from_spans(spans: &[Span]) -> Self {
473 [spans[0]]
474 }
475 }
476
477 impl FromSpans for [Span; 2] {
478 fn from_spans(spans: &[Span]) -> Self {
479 [spans[0], spans[1]]
480 }
481 }
482
483 impl FromSpans for [Span; 3] {
484 fn from_spans(spans: &[Span]) -> Self {
485 [spans[0], spans[1], spans[2]]
486 }
487 }
488
489 pub fn op<'a, T, R>(s: &str,
Michael Layzell0a1a6632017-06-02 18:07:43 -0400490 mut tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700491 new: fn(T) -> R)
Michael Layzell760fd662017-05-31 22:46:05 -0400492 -> PResult<'a, R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700493 where T: FromSpans,
494 {
495 let mut spans = [Span::default(); 3];
Alex Crichton954046c2017-05-30 21:49:42 -0700496 assert!(s.len() <= spans.len());
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700497 let chars = s.chars();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700498
Alex Crichton954046c2017-05-30 21:49:42 -0700499 for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400500 match tokens.op() {
501 Some((rest, span, c, kind)) if c == ch => {
502 if i != s.len() - 1 {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700503 match kind {
504 Spacing::Joint => {}
505 _ => return parse_error(),
Michael Layzell0a1a6632017-06-02 18:07:43 -0400506 }
507 }
David Tolnay98942562017-12-26 21:24:35 -0500508 *slot = span;
Michael Layzell0a1a6632017-06-02 18:07:43 -0400509 tokens = rest;
Alex Crichton954046c2017-05-30 21:49:42 -0700510 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400511 _ => return parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700512 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700513 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400514 Ok((tokens, new(T::from_spans(&spans))))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700515 }
516
517 pub fn sym<'a, T>(sym: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400518 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700519 new: fn(Span) -> T)
Michael Layzell760fd662017-05-31 22:46:05 -0400520 -> PResult<'a, T>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700521 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400522 if let Some((rest, span, s)) = tokens.word() {
523 if s.as_str() == sym {
David Tolnay98942562017-12-26 21:24:35 -0500524 return Ok((rest, new(span)));
Michael Layzell0a1a6632017-06-02 18:07:43 -0400525 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700526 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400527 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700528 }
529
530 pub fn delim<'a, F, R, T>(delim: &str,
Michael Layzell760fd662017-05-31 22:46:05 -0400531 tokens: Cursor<'a>,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700532 new: fn(Span) -> T,
533 f: F)
Michael Layzell760fd662017-05-31 22:46:05 -0400534 -> PResult<'a, (R, T)>
535 where F: FnOnce(Cursor) -> PResult<R>
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700536 {
Michael Layzell0a1a6632017-06-02 18:07:43 -0400537 // NOTE: We should support none-delimited sequences here.
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700538 let delim = match delim {
539 "(" => Delimiter::Parenthesis,
540 "{" => Delimiter::Brace,
541 "[" => Delimiter::Bracket,
Michael Layzell93c36282017-06-04 20:43:14 -0400542 " " => Delimiter::None,
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700543 _ => panic!("unknown delimiter: {}", delim),
544 };
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700545
Michael Layzell0a1a6632017-06-02 18:07:43 -0400546 if let Some(seqinfo) = tokens.seq(delim) {
547 match f(seqinfo.inside) {
548 Ok((remaining, ret)) => {
549 if remaining.eof() {
David Tolnay98942562017-12-26 21:24:35 -0500550 return Ok((seqinfo.outside, (ret, new(seqinfo.span))));
Michael Layzell0a1a6632017-06-02 18:07:43 -0400551 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700552 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400553 Err(err) => return Err(err),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700554 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700555 }
Michael Layzell0a1a6632017-06-02 18:07:43 -0400556 parse_error()
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700557 }
558}
559
560#[cfg(feature = "printing")]
561mod printing {
David Tolnay98942562017-12-26 21:24:35 -0500562 use proc_macro2::{Span, TokenTree, TokenNode, Spacing, Term};
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700563 use quote::Tokens;
564
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700565 pub fn op(s: &str, spans: &[Span], tokens: &mut Tokens) {
566 assert_eq!(s.len(), spans.len());
567
568 let mut chars = s.chars();
569 let mut spans = spans.iter();
570 let ch = chars.next_back().unwrap();
571 let span = spans.next_back().unwrap();
572 for (ch, span) in chars.zip(spans) {
573 tokens.append(TokenTree {
David Tolnay98942562017-12-26 21:24:35 -0500574 span: *span,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700575 kind: TokenNode::Op(ch, Spacing::Joint),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700576 });
577 }
578
579 tokens.append(TokenTree {
David Tolnay98942562017-12-26 21:24:35 -0500580 span: *span,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700581 kind: TokenNode::Op(ch, Spacing::Alone),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700582 });
583 }
584
585 pub fn sym(s: &str, span: &Span, tokens: &mut Tokens) {
586 tokens.append(TokenTree {
David Tolnay98942562017-12-26 21:24:35 -0500587 span: *span,
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700588 kind: TokenNode::Term(Term::intern(s)),
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700589 });
590 }
591
592 pub fn delim<F>(s: &str, span: &Span, tokens: &mut Tokens, f: F)
593 where F: FnOnce(&mut Tokens)
594 {
David Tolnay98942562017-12-26 21:24:35 -0500595 tokens.append_delimited(s, *span, f)
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700596 }
597}