token.rs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. //! Tokens representing Rust punctuation, keywords, and delimiters.
  3. //!
  4. //! The type names in this module can be difficult to keep straight, so we
  5. //! prefer to use the [`Token!`] macro instead. This is a type-macro that
  6. //! expands to the token type of the given token.
  7. //!
  8. //! [`Token!`]: crate::Token
  9. //!
  10. //! # Example
  11. //!
  12. //! The [`ItemStatic`] syntax tree node is defined like this.
  13. //!
  14. //! [`ItemStatic`]: crate::ItemStatic
  15. //!
  16. //! ```
  17. //! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
  18. //! #
  19. //! pub struct ItemStatic {
  20. //! pub attrs: Vec<Attribute>,
  21. //! pub vis: Visibility,
  22. //! pub static_token: Token![static],
  23. //! pub mutability: Option<Token![mut]>,
  24. //! pub ident: Ident,
  25. //! pub colon_token: Token![:],
  26. //! pub ty: Box<Type>,
  27. //! pub eq_token: Token![=],
  28. //! pub expr: Box<Expr>,
  29. //! pub semi_token: Token![;],
  30. //! }
  31. //! ```
  32. //!
  33. //! # Parsing
  34. //!
  35. //! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
  36. //! method. Delimiter tokens are parsed using the [`parenthesized!`],
  37. //! [`bracketed!`] and [`braced!`] macros.
  38. //!
  39. //! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse()
  40. //! [`parenthesized!`]: crate::parenthesized!
  41. //! [`bracketed!`]: crate::bracketed!
  42. //! [`braced!`]: crate::braced!
  43. //!
  44. //! ```
  45. //! use syn::{Attribute, Result};
  46. //! use syn::parse::{Parse, ParseStream};
  47. //! #
  48. //! # enum ItemStatic {}
  49. //!
  50. //! // Parse the ItemStatic struct shown above.
  51. //! impl Parse for ItemStatic {
  52. //! fn parse(input: ParseStream) -> Result<Self> {
  53. //! # use syn::ItemStatic;
  54. //! # fn parse(input: ParseStream) -> Result<ItemStatic> {
  55. //! Ok(ItemStatic {
  56. //! attrs: input.call(Attribute::parse_outer)?,
  57. //! vis: input.parse()?,
  58. //! static_token: input.parse()?,
  59. //! mutability: input.parse()?,
  60. //! ident: input.parse()?,
  61. //! colon_token: input.parse()?,
  62. //! ty: input.parse()?,
  63. //! eq_token: input.parse()?,
  64. //! expr: input.parse()?,
  65. //! semi_token: input.parse()?,
  66. //! })
  67. //! # }
  68. //! # unimplemented!()
  69. //! }
  70. //! }
  71. //! ```
  72. //!
  73. //! # Other operations
  74. //!
  75. //! Every keyword and punctuation token supports the following operations.
  76. //!
  77. //! - [Peeking] — `input.peek(Token![...])`
  78. //!
  79. //! - [Parsing] — `input.parse::<Token![...]>()?`
  80. //!
  81. //! - [Printing] — `quote!( ... #the_token ... )`
  82. //!
  83. //! - Construction from a [`Span`] — `let the_token = Token![...](sp)`
  84. //!
  85. //! - Field access to its span — `let sp = the_token.span`
  86. //!
  87. //! [Peeking]: crate::parse::ParseBuffer::peek()
  88. //! [Parsing]: crate::parse::ParseBuffer::parse()
  89. //! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
  90. //! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html
  91. #[cfg(feature = "parsing")]
  92. pub(crate) use self::private::CustomToken;
  93. use self::private::WithSpan;
  94. #[cfg(feature = "parsing")]
  95. use crate::buffer::Cursor;
  96. #[cfg(feature = "parsing")]
  97. use crate::error::Result;
  98. #[cfg(feature = "parsing")]
  99. use crate::lifetime::Lifetime;
  100. #[cfg(feature = "parsing")]
  101. use crate::parse::{Parse, ParseStream};
  102. use crate::span::IntoSpans;
  103. use proc_macro2::extra::DelimSpan;
  104. use proc_macro2::Span;
  105. #[cfg(feature = "printing")]
  106. use proc_macro2::TokenStream;
  107. #[cfg(any(feature = "parsing", feature = "printing"))]
  108. use proc_macro2::{Delimiter, Ident};
  109. #[cfg(feature = "parsing")]
  110. use proc_macro2::{Literal, Punct, TokenTree};
  111. #[cfg(feature = "printing")]
  112. use quote::{ToTokens, TokenStreamExt};
  113. #[cfg(feature = "extra-traits")]
  114. use std::cmp;
  115. #[cfg(feature = "extra-traits")]
  116. use std::fmt::{self, Debug};
  117. #[cfg(feature = "extra-traits")]
  118. use std::hash::{Hash, Hasher};
  119. use std::ops::{Deref, DerefMut};
  120. /// Marker trait for types that represent single tokens.
  121. ///
  122. /// This trait is sealed and cannot be implemented for types outside of Syn.
  123. #[cfg(feature = "parsing")]
  124. pub trait Token: private::Sealed {
  125. // Not public API.
  126. #[doc(hidden)]
  127. fn peek(cursor: Cursor) -> bool;
  128. // Not public API.
  129. #[doc(hidden)]
  130. fn display() -> &'static str;
  131. }
  132. pub(crate) mod private {
  133. #[cfg(feature = "parsing")]
  134. use crate::buffer::Cursor;
  135. use proc_macro2::Span;
  136. #[cfg(feature = "parsing")]
  137. pub trait Sealed {}
  138. /// Support writing `token.span` rather than `token.spans[0]` on tokens that
  139. /// hold a single span.
  140. #[repr(transparent)]
  141. #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
  142. pub struct WithSpan {
  143. pub span: Span,
  144. }
  145. // Not public API.
  146. #[doc(hidden)]
  147. #[cfg(feature = "parsing")]
  148. pub trait CustomToken {
  149. fn peek(cursor: Cursor) -> bool;
  150. fn display() -> &'static str;
  151. }
  152. }
  153. #[cfg(feature = "parsing")]
  154. impl private::Sealed for Ident {}
  155. macro_rules! impl_low_level_token {
  156. ($display:literal $($path:ident)::+ $get:ident) => {
  157. #[cfg(feature = "parsing")]
  158. impl Token for $($path)::+ {
  159. fn peek(cursor: Cursor) -> bool {
  160. cursor.$get().is_some()
  161. }
  162. fn display() -> &'static str {
  163. $display
  164. }
  165. }
  166. #[cfg(feature = "parsing")]
  167. impl private::Sealed for $($path)::+ {}
  168. };
  169. }
  170. impl_low_level_token!("punctuation token" Punct punct);
  171. impl_low_level_token!("literal" Literal literal);
  172. impl_low_level_token!("token" TokenTree token_tree);
  173. impl_low_level_token!("group token" proc_macro2::Group any_group);
  174. impl_low_level_token!("lifetime" Lifetime lifetime);
  175. #[cfg(feature = "parsing")]
  176. impl<T: CustomToken> private::Sealed for T {}
  177. #[cfg(feature = "parsing")]
  178. impl<T: CustomToken> Token for T {
  179. fn peek(cursor: Cursor) -> bool {
  180. <Self as CustomToken>::peek(cursor)
  181. }
  182. fn display() -> &'static str {
  183. <Self as CustomToken>::display()
  184. }
  185. }
  186. macro_rules! define_keywords {
  187. ($($token:literal pub struct $name:ident)*) => {
  188. $(
  189. #[doc = concat!('`', $token, '`')]
  190. ///
  191. /// Don't try to remember the name of this type &mdash; use the
  192. /// [`Token!`] macro instead.
  193. ///
  194. /// [`Token!`]: crate::token
  195. pub struct $name {
  196. pub span: Span,
  197. }
  198. #[doc(hidden)]
  199. #[allow(non_snake_case)]
  200. pub fn $name<S: IntoSpans<Span>>(span: S) -> $name {
  201. $name {
  202. span: span.into_spans(),
  203. }
  204. }
  205. impl std::default::Default for $name {
  206. fn default() -> Self {
  207. $name {
  208. span: Span::call_site(),
  209. }
  210. }
  211. }
  212. #[cfg(feature = "clone-impls")]
  213. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  214. impl Copy for $name {}
  215. #[cfg(feature = "clone-impls")]
  216. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  217. impl Clone for $name {
  218. fn clone(&self) -> Self {
  219. *self
  220. }
  221. }
  222. #[cfg(feature = "extra-traits")]
  223. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  224. impl Debug for $name {
  225. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  226. f.write_str(stringify!($name))
  227. }
  228. }
  229. #[cfg(feature = "extra-traits")]
  230. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  231. impl cmp::Eq for $name {}
  232. #[cfg(feature = "extra-traits")]
  233. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  234. impl PartialEq for $name {
  235. fn eq(&self, _other: &$name) -> bool {
  236. true
  237. }
  238. }
  239. #[cfg(feature = "extra-traits")]
  240. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  241. impl Hash for $name {
  242. fn hash<H: Hasher>(&self, _state: &mut H) {}
  243. }
  244. #[cfg(feature = "printing")]
  245. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  246. impl ToTokens for $name {
  247. fn to_tokens(&self, tokens: &mut TokenStream) {
  248. printing::keyword($token, self.span, tokens);
  249. }
  250. }
  251. #[cfg(feature = "parsing")]
  252. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  253. impl Parse for $name {
  254. fn parse(input: ParseStream) -> Result<Self> {
  255. Ok($name {
  256. span: parsing::keyword(input, $token)?,
  257. })
  258. }
  259. }
  260. #[cfg(feature = "parsing")]
  261. impl Token for $name {
  262. fn peek(cursor: Cursor) -> bool {
  263. parsing::peek_keyword(cursor, $token)
  264. }
  265. fn display() -> &'static str {
  266. concat!("`", $token, "`")
  267. }
  268. }
  269. #[cfg(feature = "parsing")]
  270. impl private::Sealed for $name {}
  271. )*
  272. };
  273. }
  274. macro_rules! impl_deref_if_len_is_1 {
  275. ($name:ident/1) => {
  276. impl Deref for $name {
  277. type Target = WithSpan;
  278. fn deref(&self) -> &Self::Target {
  279. unsafe { &*(self as *const Self).cast::<WithSpan>() }
  280. }
  281. }
  282. impl DerefMut for $name {
  283. fn deref_mut(&mut self) -> &mut Self::Target {
  284. unsafe { &mut *(self as *mut Self).cast::<WithSpan>() }
  285. }
  286. }
  287. };
  288. ($name:ident/$len:literal) => {};
  289. }
  290. macro_rules! define_punctuation_structs {
  291. ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
  292. $(
  293. #[cfg_attr(not(doc), repr(transparent))]
  294. #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
  295. #[doc = concat!('`', $token, '`')]
  296. ///
  297. /// Usage:
  298. #[doc = concat!($usage, '.')]
  299. ///
  300. /// Don't try to remember the name of this type &mdash; use the
  301. /// [`Token!`] macro instead.
  302. ///
  303. /// [`Token!`]: crate::token
  304. pub struct $name {
  305. pub spans: [Span; $len],
  306. }
  307. #[doc(hidden)]
  308. #[allow(non_snake_case)]
  309. pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
  310. $name {
  311. spans: spans.into_spans(),
  312. }
  313. }
  314. impl std::default::Default for $name {
  315. fn default() -> Self {
  316. $name {
  317. spans: [Span::call_site(); $len],
  318. }
  319. }
  320. }
  321. #[cfg(feature = "clone-impls")]
  322. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  323. impl Copy for $name {}
  324. #[cfg(feature = "clone-impls")]
  325. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  326. impl Clone for $name {
  327. fn clone(&self) -> Self {
  328. *self
  329. }
  330. }
  331. #[cfg(feature = "extra-traits")]
  332. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  333. impl Debug for $name {
  334. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  335. f.write_str(stringify!($name))
  336. }
  337. }
  338. #[cfg(feature = "extra-traits")]
  339. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  340. impl cmp::Eq for $name {}
  341. #[cfg(feature = "extra-traits")]
  342. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  343. impl PartialEq for $name {
  344. fn eq(&self, _other: &$name) -> bool {
  345. true
  346. }
  347. }
  348. #[cfg(feature = "extra-traits")]
  349. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  350. impl Hash for $name {
  351. fn hash<H: Hasher>(&self, _state: &mut H) {}
  352. }
  353. impl_deref_if_len_is_1!($name/$len);
  354. )*
  355. };
  356. }
  357. macro_rules! define_punctuation {
  358. ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
  359. $(
  360. define_punctuation_structs! {
  361. $token pub struct $name/$len #[doc = $usage]
  362. }
  363. #[cfg(feature = "printing")]
  364. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  365. impl ToTokens for $name {
  366. fn to_tokens(&self, tokens: &mut TokenStream) {
  367. printing::punct($token, &self.spans, tokens);
  368. }
  369. }
  370. #[cfg(feature = "parsing")]
  371. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  372. impl Parse for $name {
  373. fn parse(input: ParseStream) -> Result<Self> {
  374. Ok($name {
  375. spans: parsing::punct(input, $token)?,
  376. })
  377. }
  378. }
  379. #[cfg(feature = "parsing")]
  380. impl Token for $name {
  381. fn peek(cursor: Cursor) -> bool {
  382. parsing::peek_punct(cursor, $token)
  383. }
  384. fn display() -> &'static str {
  385. concat!("`", $token, "`")
  386. }
  387. }
  388. #[cfg(feature = "parsing")]
  389. impl private::Sealed for $name {}
  390. )*
  391. };
  392. }
  393. macro_rules! define_delimiters {
  394. ($($delim:ident pub struct $name:ident #[$doc:meta])*) => {
  395. $(
  396. #[$doc]
  397. pub struct $name {
  398. pub span: DelimSpan,
  399. }
  400. #[doc(hidden)]
  401. #[allow(non_snake_case)]
  402. pub fn $name<S: IntoSpans<DelimSpan>>(span: S) -> $name {
  403. $name {
  404. span: span.into_spans(),
  405. }
  406. }
  407. impl std::default::Default for $name {
  408. fn default() -> Self {
  409. $name(Span::call_site())
  410. }
  411. }
  412. #[cfg(feature = "clone-impls")]
  413. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  414. impl Copy for $name {}
  415. #[cfg(feature = "clone-impls")]
  416. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  417. impl Clone for $name {
  418. fn clone(&self) -> Self {
  419. *self
  420. }
  421. }
  422. #[cfg(feature = "extra-traits")]
  423. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  424. impl Debug for $name {
  425. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  426. f.write_str(stringify!($name))
  427. }
  428. }
  429. #[cfg(feature = "extra-traits")]
  430. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  431. impl cmp::Eq for $name {}
  432. #[cfg(feature = "extra-traits")]
  433. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  434. impl PartialEq for $name {
  435. fn eq(&self, _other: &$name) -> bool {
  436. true
  437. }
  438. }
  439. #[cfg(feature = "extra-traits")]
  440. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  441. impl Hash for $name {
  442. fn hash<H: Hasher>(&self, _state: &mut H) {}
  443. }
  444. impl $name {
  445. #[cfg(feature = "printing")]
  446. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  447. pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
  448. where
  449. F: FnOnce(&mut TokenStream),
  450. {
  451. let mut inner = TokenStream::new();
  452. f(&mut inner);
  453. printing::delim(Delimiter::$delim, self.span.join(), tokens, inner);
  454. }
  455. }
  456. #[cfg(feature = "parsing")]
  457. impl private::Sealed for $name {}
  458. )*
  459. };
  460. }
  461. define_punctuation_structs! {
  462. "_" pub struct Underscore/1 /// wildcard patterns, inferred types, unnamed items in constants, extern crates, use declarations, and destructuring assignment
  463. }
  464. #[cfg(feature = "printing")]
  465. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  466. impl ToTokens for Underscore {
  467. fn to_tokens(&self, tokens: &mut TokenStream) {
  468. tokens.append(Ident::new("_", self.span));
  469. }
  470. }
  471. #[cfg(feature = "parsing")]
  472. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  473. impl Parse for Underscore {
  474. fn parse(input: ParseStream) -> Result<Self> {
  475. input.step(|cursor| {
  476. if let Some((ident, rest)) = cursor.ident() {
  477. if ident == "_" {
  478. return Ok((Underscore(ident.span()), rest));
  479. }
  480. }
  481. if let Some((punct, rest)) = cursor.punct() {
  482. if punct.as_char() == '_' {
  483. return Ok((Underscore(punct.span()), rest));
  484. }
  485. }
  486. Err(cursor.error("expected `_`"))
  487. })
  488. }
  489. }
  490. #[cfg(feature = "parsing")]
  491. impl Token for Underscore {
  492. fn peek(cursor: Cursor) -> bool {
  493. if let Some((ident, _rest)) = cursor.ident() {
  494. return ident == "_";
  495. }
  496. if let Some((punct, _rest)) = cursor.punct() {
  497. return punct.as_char() == '_';
  498. }
  499. false
  500. }
  501. fn display() -> &'static str {
  502. "`_`"
  503. }
  504. }
  505. #[cfg(feature = "parsing")]
  506. impl private::Sealed for Underscore {}
  507. /// None-delimited group
  508. pub struct Group {
  509. pub span: Span,
  510. }
  511. #[doc(hidden)]
  512. #[allow(non_snake_case)]
  513. pub fn Group<S: IntoSpans<Span>>(span: S) -> Group {
  514. Group {
  515. span: span.into_spans(),
  516. }
  517. }
  518. impl std::default::Default for Group {
  519. fn default() -> Self {
  520. Group {
  521. span: Span::call_site(),
  522. }
  523. }
  524. }
  525. #[cfg(feature = "clone-impls")]
  526. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  527. impl Copy for Group {}
  528. #[cfg(feature = "clone-impls")]
  529. #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
  530. impl Clone for Group {
  531. fn clone(&self) -> Self {
  532. *self
  533. }
  534. }
  535. #[cfg(feature = "extra-traits")]
  536. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  537. impl Debug for Group {
  538. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  539. f.write_str("Group")
  540. }
  541. }
  542. #[cfg(feature = "extra-traits")]
  543. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  544. impl cmp::Eq for Group {}
  545. #[cfg(feature = "extra-traits")]
  546. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  547. impl PartialEq for Group {
  548. fn eq(&self, _other: &Group) -> bool {
  549. true
  550. }
  551. }
  552. #[cfg(feature = "extra-traits")]
  553. #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
  554. impl Hash for Group {
  555. fn hash<H: Hasher>(&self, _state: &mut H) {}
  556. }
  557. impl Group {
  558. #[cfg(feature = "printing")]
  559. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  560. pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
  561. where
  562. F: FnOnce(&mut TokenStream),
  563. {
  564. let mut inner = TokenStream::new();
  565. f(&mut inner);
  566. printing::delim(Delimiter::None, self.span, tokens, inner);
  567. }
  568. }
  569. #[cfg(feature = "parsing")]
  570. impl private::Sealed for Group {}
  571. #[cfg(feature = "parsing")]
  572. impl Token for Paren {
  573. fn peek(cursor: Cursor) -> bool {
  574. cursor.group(Delimiter::Parenthesis).is_some()
  575. }
  576. fn display() -> &'static str {
  577. "parentheses"
  578. }
  579. }
  580. #[cfg(feature = "parsing")]
  581. impl Token for Brace {
  582. fn peek(cursor: Cursor) -> bool {
  583. cursor.group(Delimiter::Brace).is_some()
  584. }
  585. fn display() -> &'static str {
  586. "curly braces"
  587. }
  588. }
  589. #[cfg(feature = "parsing")]
  590. impl Token for Bracket {
  591. fn peek(cursor: Cursor) -> bool {
  592. cursor.group(Delimiter::Bracket).is_some()
  593. }
  594. fn display() -> &'static str {
  595. "square brackets"
  596. }
  597. }
  598. #[cfg(feature = "parsing")]
  599. impl Token for Group {
  600. fn peek(cursor: Cursor) -> bool {
  601. cursor.group(Delimiter::None).is_some()
  602. }
  603. fn display() -> &'static str {
  604. "invisible group"
  605. }
  606. }
  607. define_keywords! {
  608. "abstract" pub struct Abstract
  609. "as" pub struct As
  610. "async" pub struct Async
  611. "auto" pub struct Auto
  612. "await" pub struct Await
  613. "become" pub struct Become
  614. "box" pub struct Box
  615. "break" pub struct Break
  616. "const" pub struct Const
  617. "continue" pub struct Continue
  618. "crate" pub struct Crate
  619. "default" pub struct Default
  620. "do" pub struct Do
  621. "dyn" pub struct Dyn
  622. "else" pub struct Else
  623. "enum" pub struct Enum
  624. "extern" pub struct Extern
  625. "final" pub struct Final
  626. "fn" pub struct Fn
  627. "for" pub struct For
  628. "if" pub struct If
  629. "impl" pub struct Impl
  630. "in" pub struct In
  631. "let" pub struct Let
  632. "loop" pub struct Loop
  633. "macro" pub struct Macro
  634. "match" pub struct Match
  635. "mod" pub struct Mod
  636. "move" pub struct Move
  637. "mut" pub struct Mut
  638. "override" pub struct Override
  639. "priv" pub struct Priv
  640. "pub" pub struct Pub
  641. "raw" pub struct Raw
  642. "ref" pub struct Ref
  643. "return" pub struct Return
  644. "Self" pub struct SelfType
  645. "self" pub struct SelfValue
  646. "static" pub struct Static
  647. "struct" pub struct Struct
  648. "super" pub struct Super
  649. "trait" pub struct Trait
  650. "try" pub struct Try
  651. "type" pub struct Type
  652. "typeof" pub struct Typeof
  653. "union" pub struct Union
  654. "unsafe" pub struct Unsafe
  655. "unsized" pub struct Unsized
  656. "use" pub struct Use
  657. "virtual" pub struct Virtual
  658. "where" pub struct Where
  659. "while" pub struct While
  660. "yield" pub struct Yield
  661. }
  662. define_punctuation! {
  663. "&" pub struct And/1 /// bitwise and logical AND, borrow, references, reference patterns
  664. "&&" pub struct AndAnd/2 /// lazy AND, borrow, references, reference patterns
  665. "&=" pub struct AndEq/2 /// bitwise AND assignment
  666. "@" pub struct At/1 /// subpattern binding
  667. "^" pub struct Caret/1 /// bitwise and logical XOR
  668. "^=" pub struct CaretEq/2 /// bitwise XOR assignment
  669. ":" pub struct Colon/1 /// various separators
  670. "," pub struct Comma/1 /// various separators
  671. "$" pub struct Dollar/1 /// macros
  672. "." pub struct Dot/1 /// field access, tuple index
  673. ".." pub struct DotDot/2 /// range, struct expressions, patterns, range patterns
  674. "..." pub struct DotDotDot/3 /// variadic functions, range patterns
  675. "..=" pub struct DotDotEq/3 /// inclusive range, range patterns
  676. "=" pub struct Eq/1 /// assignment, attributes, various type definitions
  677. "==" pub struct EqEq/2 /// equal
  678. "=>" pub struct FatArrow/2 /// match arms, macros
  679. ">=" pub struct Ge/2 /// greater than or equal to, generics
  680. ">" pub struct Gt/1 /// greater than, generics, paths
  681. "<-" pub struct LArrow/2 /// unused
  682. "<=" pub struct Le/2 /// less than or equal to
  683. "<" pub struct Lt/1 /// less than, generics, paths
  684. "-" pub struct Minus/1 /// subtraction, negation
  685. "-=" pub struct MinusEq/2 /// subtraction assignment
  686. "!=" pub struct Ne/2 /// not equal
  687. "!" pub struct Not/1 /// bitwise and logical NOT, macro calls, inner attributes, never type, negative impls
  688. "|" pub struct Or/1 /// bitwise and logical OR, closures, patterns in match, if let, and while let
  689. "|=" pub struct OrEq/2 /// bitwise OR assignment
  690. "||" pub struct OrOr/2 /// lazy OR, closures
  691. "::" pub struct PathSep/2 /// path separator
  692. "%" pub struct Percent/1 /// remainder
  693. "%=" pub struct PercentEq/2 /// remainder assignment
  694. "+" pub struct Plus/1 /// addition, trait bounds, macro Kleene matcher
  695. "+=" pub struct PlusEq/2 /// addition assignment
  696. "#" pub struct Pound/1 /// attributes
  697. "?" pub struct Question/1 /// question mark operator, questionably sized, macro Kleene matcher
  698. "->" pub struct RArrow/2 /// function return type, closure return type, function pointer type
  699. ";" pub struct Semi/1 /// terminator for various items and statements, array types
  700. "<<" pub struct Shl/2 /// shift left, nested generics
  701. "<<=" pub struct ShlEq/3 /// shift left assignment
  702. ">>" pub struct Shr/2 /// shift right, nested generics
  703. ">>=" pub struct ShrEq/3 /// shift right assignment, nested generics
  704. "/" pub struct Slash/1 /// division
  705. "/=" pub struct SlashEq/2 /// division assignment
  706. "*" pub struct Star/1 /// multiplication, dereference, raw pointers, macro Kleene matcher, use wildcards
  707. "*=" pub struct StarEq/2 /// multiplication assignment
  708. "~" pub struct Tilde/1 /// unused since before Rust 1.0
  709. }
  710. define_delimiters! {
  711. Brace pub struct Brace /// `{`&hellip;`}`
  712. Bracket pub struct Bracket /// `[`&hellip;`]`
  713. Parenthesis pub struct Paren /// `(`&hellip;`)`
  714. }
  715. /// A type-macro that expands to the name of the Rust type representation of a
  716. /// given token.
  717. ///
  718. /// As a type, `Token!` is commonly used in the type of struct fields, the type
  719. /// of a `let` statement, or in turbofish for a `parse` function.
  720. ///
  721. /// ```
  722. /// use syn::{Ident, Token};
  723. /// use syn::parse::{Parse, ParseStream, Result};
  724. ///
  725. /// // `struct Foo;`
  726. /// pub struct UnitStruct {
  727. /// struct_token: Token![struct],
  728. /// ident: Ident,
  729. /// semi_token: Token![;],
  730. /// }
  731. ///
  732. /// impl Parse for UnitStruct {
  733. /// fn parse(input: ParseStream) -> Result<Self> {
  734. /// let struct_token: Token![struct] = input.parse()?;
  735. /// let ident: Ident = input.parse()?;
  736. /// let semi_token = input.parse::<Token![;]>()?;
  737. /// Ok(UnitStruct { struct_token, ident, semi_token })
  738. /// }
  739. /// }
  740. /// ```
  741. ///
  742. /// As an expression, `Token!` is used for peeking tokens or instantiating
  743. /// tokens from a span.
  744. ///
  745. /// ```
  746. /// # use syn::{Ident, Token};
  747. /// # use syn::parse::{Parse, ParseStream, Result};
  748. /// #
  749. /// # struct UnitStruct {
  750. /// # struct_token: Token![struct],
  751. /// # ident: Ident,
  752. /// # semi_token: Token![;],
  753. /// # }
  754. /// #
  755. /// # impl Parse for UnitStruct {
  756. /// # fn parse(input: ParseStream) -> Result<Self> {
  757. /// # unimplemented!()
  758. /// # }
  759. /// # }
  760. /// #
  761. /// fn make_unit_struct(name: Ident) -> UnitStruct {
  762. /// let span = name.span();
  763. /// UnitStruct {
  764. /// struct_token: Token![struct](span),
  765. /// ident: name,
  766. /// semi_token: Token![;](span),
  767. /// }
  768. /// }
  769. ///
  770. /// # fn parse(input: ParseStream) -> Result<()> {
  771. /// if input.peek(Token![struct]) {
  772. /// let unit_struct: UnitStruct = input.parse()?;
  773. /// /* ... */
  774. /// }
  775. /// # Ok(())
  776. /// # }
  777. /// ```
  778. ///
  779. /// See the [token module] documentation for details and examples.
  780. ///
  781. /// [token module]: crate::token
  782. #[macro_export]
  783. macro_rules! Token {
  784. [abstract] => { $crate::token::Abstract };
  785. [as] => { $crate::token::As };
  786. [async] => { $crate::token::Async };
  787. [auto] => { $crate::token::Auto };
  788. [await] => { $crate::token::Await };
  789. [become] => { $crate::token::Become };
  790. [box] => { $crate::token::Box };
  791. [break] => { $crate::token::Break };
  792. [const] => { $crate::token::Const };
  793. [continue] => { $crate::token::Continue };
  794. [crate] => { $crate::token::Crate };
  795. [default] => { $crate::token::Default };
  796. [do] => { $crate::token::Do };
  797. [dyn] => { $crate::token::Dyn };
  798. [else] => { $crate::token::Else };
  799. [enum] => { $crate::token::Enum };
  800. [extern] => { $crate::token::Extern };
  801. [final] => { $crate::token::Final };
  802. [fn] => { $crate::token::Fn };
  803. [for] => { $crate::token::For };
  804. [if] => { $crate::token::If };
  805. [impl] => { $crate::token::Impl };
  806. [in] => { $crate::token::In };
  807. [let] => { $crate::token::Let };
  808. [loop] => { $crate::token::Loop };
  809. [macro] => { $crate::token::Macro };
  810. [match] => { $crate::token::Match };
  811. [mod] => { $crate::token::Mod };
  812. [move] => { $crate::token::Move };
  813. [mut] => { $crate::token::Mut };
  814. [override] => { $crate::token::Override };
  815. [priv] => { $crate::token::Priv };
  816. [pub] => { $crate::token::Pub };
  817. [raw] => { $crate::token::Raw };
  818. [ref] => { $crate::token::Ref };
  819. [return] => { $crate::token::Return };
  820. [Self] => { $crate::token::SelfType };
  821. [self] => { $crate::token::SelfValue };
  822. [static] => { $crate::token::Static };
  823. [struct] => { $crate::token::Struct };
  824. [super] => { $crate::token::Super };
  825. [trait] => { $crate::token::Trait };
  826. [try] => { $crate::token::Try };
  827. [type] => { $crate::token::Type };
  828. [typeof] => { $crate::token::Typeof };
  829. [union] => { $crate::token::Union };
  830. [unsafe] => { $crate::token::Unsafe };
  831. [unsized] => { $crate::token::Unsized };
  832. [use] => { $crate::token::Use };
  833. [virtual] => { $crate::token::Virtual };
  834. [where] => { $crate::token::Where };
  835. [while] => { $crate::token::While };
  836. [yield] => { $crate::token::Yield };
  837. [&] => { $crate::token::And };
  838. [&&] => { $crate::token::AndAnd };
  839. [&=] => { $crate::token::AndEq };
  840. [@] => { $crate::token::At };
  841. [^] => { $crate::token::Caret };
  842. [^=] => { $crate::token::CaretEq };
  843. [:] => { $crate::token::Colon };
  844. [,] => { $crate::token::Comma };
  845. [$] => { $crate::token::Dollar };
  846. [.] => { $crate::token::Dot };
  847. [..] => { $crate::token::DotDot };
  848. [...] => { $crate::token::DotDotDot };
  849. [..=] => { $crate::token::DotDotEq };
  850. [=] => { $crate::token::Eq };
  851. [==] => { $crate::token::EqEq };
  852. [=>] => { $crate::token::FatArrow };
  853. [>=] => { $crate::token::Ge };
  854. [>] => { $crate::token::Gt };
  855. [<-] => { $crate::token::LArrow };
  856. [<=] => { $crate::token::Le };
  857. [<] => { $crate::token::Lt };
  858. [-] => { $crate::token::Minus };
  859. [-=] => { $crate::token::MinusEq };
  860. [!=] => { $crate::token::Ne };
  861. [!] => { $crate::token::Not };
  862. [|] => { $crate::token::Or };
  863. [|=] => { $crate::token::OrEq };
  864. [||] => { $crate::token::OrOr };
  865. [::] => { $crate::token::PathSep };
  866. [%] => { $crate::token::Percent };
  867. [%=] => { $crate::token::PercentEq };
  868. [+] => { $crate::token::Plus };
  869. [+=] => { $crate::token::PlusEq };
  870. [#] => { $crate::token::Pound };
  871. [?] => { $crate::token::Question };
  872. [->] => { $crate::token::RArrow };
  873. [;] => { $crate::token::Semi };
  874. [<<] => { $crate::token::Shl };
  875. [<<=] => { $crate::token::ShlEq };
  876. [>>] => { $crate::token::Shr };
  877. [>>=] => { $crate::token::ShrEq };
  878. [/] => { $crate::token::Slash };
  879. [/=] => { $crate::token::SlashEq };
  880. [*] => { $crate::token::Star };
  881. [*=] => { $crate::token::StarEq };
  882. [~] => { $crate::token::Tilde };
  883. [_] => { $crate::token::Underscore };
  884. }
  885. // Not public API.
  886. #[doc(hidden)]
  887. #[cfg(feature = "parsing")]
  888. pub(crate) mod parsing {
  889. use crate::buffer::Cursor;
  890. use crate::error::{Error, Result};
  891. use crate::parse::ParseStream;
  892. use proc_macro2::{Spacing, Span};
  893. pub(crate) fn keyword(input: ParseStream, token: &str) -> Result<Span> {
  894. input.step(|cursor| {
  895. if let Some((ident, rest)) = cursor.ident() {
  896. if ident == token {
  897. return Ok((ident.span(), rest));
  898. }
  899. }
  900. Err(cursor.error(format!("expected `{}`", token)))
  901. })
  902. }
  903. pub(crate) fn peek_keyword(cursor: Cursor, token: &str) -> bool {
  904. if let Some((ident, _rest)) = cursor.ident() {
  905. ident == token
  906. } else {
  907. false
  908. }
  909. }
  910. #[doc(hidden)]
  911. pub fn punct<const N: usize>(input: ParseStream, token: &str) -> Result<[Span; N]> {
  912. let mut spans = [input.span(); N];
  913. punct_helper(input, token, &mut spans)?;
  914. Ok(spans)
  915. }
  916. fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span]) -> Result<()> {
  917. input.step(|cursor| {
  918. let mut cursor = *cursor;
  919. assert_eq!(token.len(), spans.len());
  920. for (i, ch) in token.chars().enumerate() {
  921. match cursor.punct() {
  922. Some((punct, rest)) => {
  923. spans[i] = punct.span();
  924. if punct.as_char() != ch {
  925. break;
  926. } else if i == token.len() - 1 {
  927. return Ok(((), rest));
  928. } else if punct.spacing() != Spacing::Joint {
  929. break;
  930. }
  931. cursor = rest;
  932. }
  933. None => break,
  934. }
  935. }
  936. Err(Error::new(spans[0], format!("expected `{}`", token)))
  937. })
  938. }
  939. #[doc(hidden)]
  940. pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
  941. for (i, ch) in token.chars().enumerate() {
  942. match cursor.punct() {
  943. Some((punct, rest)) => {
  944. if punct.as_char() != ch {
  945. break;
  946. } else if i == token.len() - 1 {
  947. return true;
  948. } else if punct.spacing() != Spacing::Joint {
  949. break;
  950. }
  951. cursor = rest;
  952. }
  953. None => break,
  954. }
  955. }
  956. false
  957. }
  958. }
  959. // Not public API.
  960. #[doc(hidden)]
  961. #[cfg(feature = "printing")]
  962. pub(crate) mod printing {
  963. use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
  964. use quote::TokenStreamExt;
  965. #[doc(hidden)]
  966. pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
  967. assert_eq!(s.len(), spans.len());
  968. let mut chars = s.chars();
  969. let mut spans = spans.iter();
  970. let ch = chars.next_back().unwrap();
  971. let span = spans.next_back().unwrap();
  972. for (ch, span) in chars.zip(spans) {
  973. let mut op = Punct::new(ch, Spacing::Joint);
  974. op.set_span(*span);
  975. tokens.append(op);
  976. }
  977. let mut op = Punct::new(ch, Spacing::Alone);
  978. op.set_span(*span);
  979. tokens.append(op);
  980. }
  981. pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
  982. tokens.append(Ident::new(s, span));
  983. }
  984. pub(crate) fn delim(
  985. delim: Delimiter,
  986. span: Span,
  987. tokens: &mut TokenStream,
  988. inner: TokenStream,
  989. ) {
  990. let mut g = Group::new(delim, inner);
  991. g.set_span(span);
  992. tokens.append(g);
  993. }
  994. }