]> git.proxmox.com Git - rustc.git/blob - src/vendor/syn-0.13.11/src/lib.rs
New upstream version 1.29.0+dfsg1
[rustc.git] / src / vendor / syn-0.13.11 / src / lib.rs
1 // Copyright 2018 Syn Developers
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 //! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
10 //! tree of Rust source code.
11 //!
12 //! Currently this library is geared toward the [custom derive] use case but
13 //! contains some APIs that may be useful for Rust procedural macros more
14 //! generally.
15 //!
16 //! [custom derive]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
17 //!
18 //! - **Data structures** — Syn provides a complete syntax tree that can
19 //! represent any valid Rust source code. The syntax tree is rooted at
20 //! [`syn::File`] which represents a full source file, but there are other
21 //! entry points that may be useful to procedural macros including
22 //! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
23 //!
24 //! - **Custom derives** — Of particular interest to custom derives is
25 //! [`syn::DeriveInput`] which is any of the three legal input items to a
26 //! derive macro. An example below shows using this type in a library that can
27 //! derive implementations of a trait of your own.
28 //!
29 //! - **Parser combinators** — Parsing in Syn is built on a suite of public
30 //! parser combinator macros that you can use for parsing any token-based
31 //! syntax you dream up within a `functionlike!(...)` procedural macro. Every
32 //! syntax tree node defined by Syn is individually parsable and may be used
33 //! as a building block for custom syntaxes, or you may do it all yourself
34 //! working from the most primitive tokens.
35 //!
36 //! - **Location information** — Every token parsed by Syn is associated with a
37 //! `Span` that tracks line and column information back to the source of that
38 //! token. These spans allow a procedural macro to display detailed error
39 //! messages pointing to all the right places in the user's code. There is an
40 //! example of this below.
41 //!
42 //! - **Feature flags** — Functionality is aggressively feature gated so your
43 //! procedural macros enable only what they need, and do not pay in compile
44 //! time for all the rest.
45 //!
46 //! [`syn::File`]: struct.File.html
47 //! [`syn::Item`]: enum.Item.html
48 //! [`syn::Expr`]: enum.Expr.html
49 //! [`syn::Type`]: enum.Type.html
50 //! [`syn::DeriveInput`]: struct.DeriveInput.html
51 //!
52 //! *Version requirement: Syn supports any compiler version back to Rust's very
53 //! first support for procedural macros in Rust 1.15.0. Some features especially
54 //! around error reporting are only available in newer compilers or on the
55 //! nightly channel.*
56 //!
57 //! ## Example of a custom derive
58 //!
59 //! The canonical custom derive using Syn looks like this. We write an ordinary
60 //! Rust function tagged with a `proc_macro_derive` attribute and the name of
61 //! the trait we are deriving. Any time that derive appears in the user's code,
62 //! the Rust compiler passes their data structure as tokens into our macro. We
63 //! get to execute arbitrary Rust code to figure out what to do with those
64 //! tokens, then hand some tokens back to the compiler to compile into the
65 //! user's crate.
66 //!
67 //! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
68 //!
69 //! ```toml
70 //! [dependencies]
71 //! syn = "0.13"
72 //! quote = "0.5"
73 //!
74 //! [lib]
75 //! proc-macro = true
76 //! ```
77 //!
78 //! ```rust
79 //! extern crate proc_macro;
80 //! extern crate syn;
81 //!
82 //! #[macro_use]
83 //! extern crate quote;
84 //!
85 //! use proc_macro::TokenStream;
86 //! use syn::DeriveInput;
87 //!
88 //! # const IGNORE_TOKENS: &str = stringify! {
89 //! #[proc_macro_derive(MyMacro)]
90 //! # };
91 //! pub fn my_macro(input: TokenStream) -> TokenStream {
92 //! // Parse the input tokens into a syntax tree
93 //! let input: DeriveInput = syn::parse(input).unwrap();
94 //!
95 //! // Build the output, possibly using quasi-quotation
96 //! let expanded = quote! {
97 //! // ...
98 //! };
99 //!
100 //! // Hand the output tokens back to the compiler
101 //! expanded.into()
102 //! }
103 //! #
104 //! # fn main() {}
105 //! ```
106 //!
107 //! The [`heapsize`] example directory shows a complete working Macros 1.1
108 //! implementation of a custom derive. It works on any Rust compiler \>=1.15.0.
109 //! The example derives a `HeapSize` trait which computes an estimate of the
110 //! amount of heap memory owned by a value.
111 //!
112 //! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
113 //!
114 //! ```rust
115 //! pub trait HeapSize {
116 //! /// Total number of bytes of heap memory owned by `self`.
117 //! fn heap_size_of_children(&self) -> usize;
118 //! }
119 //! ```
120 //!
121 //! The custom derive allows users to write `#[derive(HeapSize)]` on data
122 //! structures in their program.
123 //!
124 //! ```rust
125 //! # const IGNORE_TOKENS: &str = stringify! {
126 //! #[derive(HeapSize)]
127 //! # };
128 //! struct Demo<'a, T: ?Sized> {
129 //! a: Box<T>,
130 //! b: u8,
131 //! c: &'a str,
132 //! d: String,
133 //! }
134 //! ```
135 //!
136 //! ## Spans and error reporting
137 //!
138 //! The [`heapsize2`] example directory is an extension of the `heapsize`
139 //! example that demonstrates some of the hygiene and error reporting properties
140 //! of Macros 2.0. This example currently requires a nightly Rust compiler
141 //! \>=1.24.0-nightly but we are working to stabilize all of the APIs involved.
142 //!
143 //! [`heapsize2`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize2
144 //!
145 //! The token-based procedural macro API provides great control over where the
146 //! compiler's error messages are displayed in user code. Consider the error the
147 //! user sees if one of their field types does not implement `HeapSize`.
148 //!
149 //! ```rust
150 //! # const IGNORE_TOKENS: &str = stringify! {
151 //! #[derive(HeapSize)]
152 //! # };
153 //! struct Broken {
154 //! ok: String,
155 //! bad: std::thread::Thread,
156 //! }
157 //! ```
158 //!
159 //! In the Macros 1.1 string-based procedural macro world, the resulting error
160 //! would point unhelpfully to the invocation of the derive macro and not to the
161 //! actual problematic field.
162 //!
163 //! ```text
164 //! error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
165 //! --> src/main.rs:4:10
166 //! |
167 //! 4 | #[derive(HeapSize)]
168 //! | ^^^^^^^^
169 //! ```
170 //!
171 //! By tracking span information all the way through the expansion of a
172 //! procedural macro as shown in the `heapsize2` example, token-based macros in
173 //! Syn are able to trigger errors that directly pinpoint the source of the
174 //! problem.
175 //!
176 //! ```text
177 //! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
178 //! --> src/main.rs:7:5
179 //! |
180 //! 7 | bad: std::thread::Thread,
181 //! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
182 //! ```
183 //!
184 //! ## Parsing a custom syntax using combinators
185 //!
186 //! The [`lazy-static`] example directory shows the implementation of a
187 //! `functionlike!(...)` procedural macro in which the input tokens are parsed
188 //! using [`nom`]-style parser combinators.
189 //!
190 //! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
191 //! [`nom`]: https://github.com/Geal/nom
192 //!
193 //! The example reimplements the popular `lazy_static` crate from crates.io as a
194 //! procedural macro.
195 //!
196 //! ```
197 //! # macro_rules! lazy_static {
198 //! # ($($tt:tt)*) => {}
199 //! # }
200 //! #
201 //! lazy_static! {
202 //! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
203 //! }
204 //! ```
205 //!
206 //! The implementation shows how to trigger custom warnings and error messages
207 //! on the macro input.
208 //!
209 //! ```text
210 //! warning: come on, pick a more creative name
211 //! --> src/main.rs:10:16
212 //! |
213 //! 10 | static ref FOO: String = "lazy_static".to_owned();
214 //! | ^^^
215 //! ```
216 //!
217 //! ## Debugging
218 //!
219 //! When developing a procedural macro it can be helpful to look at what the
220 //! generated code looks like. Use `cargo rustc -- -Zunstable-options
221 //! --pretty=expanded` or the [`cargo expand`] subcommand.
222 //!
223 //! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
224 //!
225 //! To show the expanded code for some crate that uses your procedural macro,
226 //! run `cargo expand` from that crate. To show the expanded code for one of
227 //! your own test cases, run `cargo expand --test the_test_case` where the last
228 //! argument is the name of the test file without the `.rs` extension.
229 //!
230 //! This write-up by Brandon W Maister discusses debugging in more detail:
231 //! [Debugging Rust's new Custom Derive system][debugging].
232 //!
233 //! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
234 //!
235 //! ## Optional features
236 //!
237 //! Syn puts a lot of functionality behind optional features in order to
238 //! optimize compile time for the most common use cases. The following features
239 //! are available.
240 //!
241 //! - **`derive`** *(enabled by default)* — Data structures for representing the
242 //! possible input to a custom derive, including structs and enums and types.
243 //! - **`full`** — Data structures for representing the syntax tree of all valid
244 //! Rust source code, including items and expressions.
245 //! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
246 //! a syntax tree node of a chosen type.
247 //! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
248 //! node as tokens of Rust source code.
249 //! - **`visit`** — Trait for traversing a syntax tree.
250 //! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
251 //! tree.
252 //! - **`fold`** — Trait for transforming an owned syntax tree.
253 //! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
254 //! types.
255 //! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
256 //! types.
257 //! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
258 //! dynamic library libproc_macro from rustc toolchain.
259
260 // Syn types in rustdoc of other crates get linked to here.
261 #![doc(html_root_url = "https://docs.rs/syn/0.13.11")]
262 #![cfg_attr(
263 feature = "cargo-clippy",
264 allow(
265 const_static_lifetime, doc_markdown, large_enum_variant, match_bool, redundant_closure,
266 needless_pass_by_value, redundant_field_names
267 )
268 )]
269
270 #[cfg(feature = "proc-macro")]
271 extern crate proc_macro;
272 extern crate proc_macro2;
273 extern crate unicode_xid;
274
275 #[cfg(feature = "printing")]
276 extern crate quote;
277
278 #[cfg(feature = "parsing")]
279 #[macro_use]
280 #[doc(hidden)]
281 pub mod parsers;
282
283 #[macro_use]
284 mod macros;
285
286 #[macro_use]
287 pub mod token;
288
289 #[cfg(any(feature = "full", feature = "derive"))]
290 mod attr;
291 #[cfg(any(feature = "full", feature = "derive"))]
292 pub use attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue, NestedMeta};
293
294 #[cfg(any(feature = "full", feature = "derive"))]
295 mod data;
296 #[cfg(any(feature = "full", feature = "derive"))]
297 pub use data::{
298 Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
299 Visibility,
300 };
301
302 #[cfg(any(feature = "full", feature = "derive"))]
303 mod expr;
304 #[cfg(any(feature = "full", feature = "derive"))]
305 pub use expr::{
306 Expr, ExprArray, ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox, ExprBreak, ExprCall,
307 ExprCast, ExprCatch, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup, ExprIf,
308 ExprIfLet, ExprInPlace, ExprIndex, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall,
309 ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
310 ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim, ExprWhile, ExprWhileLet, ExprYield,
311 Index, Member,
312 };
313
314 #[cfg(feature = "full")]
315 pub use expr::{
316 Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
317 PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
318 PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
319 };
320
321 #[cfg(any(feature = "full", feature = "derive"))]
322 mod generics;
323 #[cfg(any(feature = "full", feature = "derive"))]
324 pub use generics::{
325 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
326 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
327 WhereClause, WherePredicate,
328 };
329 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
330 pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
331
332 mod ident;
333 pub use ident::Ident;
334
335 #[cfg(feature = "full")]
336 mod item;
337 #[cfg(feature = "full")]
338 pub use item::{
339 ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemStatic,
340 ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst, ImplItemMacro, ImplItemMethod,
341 ImplItemType, ImplItemVerbatim, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
342 ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait,
343 ItemType, ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst,
344 TraitItemMacro, TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName,
345 UsePath, UseRename, UseTree,
346 };
347
348 #[cfg(feature = "full")]
349 mod file;
350 #[cfg(feature = "full")]
351 pub use file::File;
352
353 #[cfg(any(feature = "full", feature = "derive"))]
354 mod lifetime;
355 #[cfg(any(feature = "full", feature = "derive"))]
356 pub use lifetime::Lifetime;
357
358 #[cfg(any(feature = "full", feature = "derive"))]
359 mod lit;
360 #[cfg(any(feature = "full", feature = "derive"))]
361 pub use lit::{
362 FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
363 LitVerbatim, StrStyle,
364 };
365
366 #[cfg(any(feature = "full", feature = "derive"))]
367 mod mac;
368 #[cfg(any(feature = "full", feature = "derive"))]
369 pub use mac::{Macro, MacroDelimiter};
370
371 #[cfg(any(feature = "full", feature = "derive"))]
372 mod derive;
373 #[cfg(feature = "derive")]
374 pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
375
376 #[cfg(any(feature = "full", feature = "derive"))]
377 mod op;
378 #[cfg(any(feature = "full", feature = "derive"))]
379 pub use op::{BinOp, UnOp};
380
381 #[cfg(any(feature = "full", feature = "derive"))]
382 mod ty;
383 #[cfg(any(feature = "full", feature = "derive"))]
384 pub use ty::{
385 Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
386 TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
387 TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
388 };
389
390 #[cfg(any(feature = "full", feature = "derive"))]
391 mod path;
392 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
393 pub use path::PathTokens;
394 #[cfg(any(feature = "full", feature = "derive"))]
395 pub use path::{
396 AngleBracketedGenericArguments, Binding, GenericArgument, ParenthesizedGenericArguments, Path,
397 PathArguments, PathSegment, QSelf,
398 };
399
400 #[cfg(feature = "parsing")]
401 pub mod buffer;
402 pub mod punctuated;
403 #[cfg(feature = "parsing")]
404 pub mod synom;
405 #[cfg(any(feature = "full", feature = "derive"))]
406 mod tt;
407
408 // Not public API except the `parse_quote!` macro.
409 #[cfg(feature = "parsing")]
410 #[doc(hidden)]
411 pub mod parse_quote;
412
413 #[cfg(all(feature = "parsing", feature = "printing"))]
414 pub mod spanned;
415
416 mod gen {
417 /// Syntax tree traversal to walk a shared borrow of a syntax tree.
418 ///
419 /// Each method of the [`Visit`] trait is a hook that can be overridden to
420 /// customize the behavior when visiting the corresponding type of node. By
421 /// default, every method recursively visits the substructure of the input
422 /// by invoking the right visitor method of each of its fields.
423 ///
424 /// [`Visit`]: trait.Visit.html
425 ///
426 /// ```rust
427 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
428 /// #
429 /// pub trait Visit<'ast> {
430 /// /* ... */
431 ///
432 /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
433 /// for attr in &node.attrs {
434 /// self.visit_attribute(attr);
435 /// }
436 /// self.visit_expr(&*node.left);
437 /// self.visit_bin_op(&node.op);
438 /// self.visit_expr(&*node.right);
439 /// }
440 ///
441 /// /* ... */
442 /// # fn visit_attribute(&mut self, node: &'ast Attribute);
443 /// # fn visit_expr(&mut self, node: &'ast Expr);
444 /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
445 /// }
446 /// ```
447 ///
448 /// *This module is available if Syn is built with the `"visit"` feature.*
449 #[cfg(feature = "visit")]
450 pub mod visit;
451
452 /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
453 /// place.
454 ///
455 /// Each method of the [`VisitMut`] trait is a hook that can be overridden
456 /// to customize the behavior when mutating the corresponding type of node.
457 /// By default, every method recursively visits the substructure of the
458 /// input by invoking the right visitor method of each of its fields.
459 ///
460 /// [`VisitMut`]: trait.VisitMut.html
461 ///
462 /// ```rust
463 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
464 /// #
465 /// pub trait VisitMut {
466 /// /* ... */
467 ///
468 /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
469 /// for attr in &mut node.attrs {
470 /// self.visit_attribute_mut(attr);
471 /// }
472 /// self.visit_expr_mut(&mut *node.left);
473 /// self.visit_bin_op_mut(&mut node.op);
474 /// self.visit_expr_mut(&mut *node.right);
475 /// }
476 ///
477 /// /* ... */
478 /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
479 /// # fn visit_expr_mut(&mut self, node: &mut Expr);
480 /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
481 /// }
482 /// ```
483 ///
484 /// *This module is available if Syn is built with the `"visit-mut"`
485 /// feature.*
486 #[cfg(feature = "visit-mut")]
487 pub mod visit_mut;
488
489 /// Syntax tree traversal to transform the nodes of an owned syntax tree.
490 ///
491 /// Each method of the [`Fold`] trait is a hook that can be overridden to
492 /// customize the behavior when transforming the corresponding type of node.
493 /// By default, every method recursively visits the substructure of the
494 /// input by invoking the right visitor method of each of its fields.
495 ///
496 /// [`Fold`]: trait.Fold.html
497 ///
498 /// ```rust
499 /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
500 /// #
501 /// pub trait Fold {
502 /// /* ... */
503 ///
504 /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
505 /// ExprBinary {
506 /// attrs: node.attrs
507 /// .into_iter()
508 /// .map(|attr| self.fold_attribute(attr))
509 /// .collect(),
510 /// left: Box::new(self.fold_expr(*node.left)),
511 /// op: self.fold_bin_op(node.op),
512 /// right: Box::new(self.fold_expr(*node.right)),
513 /// }
514 /// }
515 ///
516 /// /* ... */
517 /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
518 /// # fn fold_expr(&mut self, node: Expr) -> Expr;
519 /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
520 /// }
521 /// ```
522 ///
523 /// *This module is available if Syn is built with the `"fold"` feature.*
524 #[cfg(feature = "fold")]
525 pub mod fold;
526
527 #[cfg(any(feature = "full", feature = "derive"))]
528 #[path = "../gen_helper.rs"]
529 mod helper;
530 }
531 pub use gen::*;
532
533 ////////////////////////////////////////////////////////////////////////////////
534
535 #[cfg(feature = "parsing")]
536 use synom::{Parser, Synom};
537
538 #[cfg(feature = "parsing")]
539 mod error;
540 #[cfg(feature = "parsing")]
541 use error::ParseError;
542
543 // Not public API.
544 #[cfg(feature = "parsing")]
545 #[doc(hidden)]
546 pub use error::parse_error;
547
548 /// Parse tokens of source code into the chosen syntax tree node.
549 ///
550 /// This is preferred over parsing a string because tokens are able to preserve
551 /// information about where in the user's code they were originally written (the
552 /// "span" of the token), possibly allowing the compiler to produce better error
553 /// messages.
554 ///
555 /// This function parses a `proc_macro::TokenStream` which is the type used for
556 /// interop with the compiler in a procedural macro. To parse a
557 /// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
558 ///
559 /// [`syn::parse2`]: fn.parse2.html
560 ///
561 /// *This function is available if Syn is built with both the `"parsing"` and
562 /// `"proc-macro"` features.*
563 ///
564 /// # Examples
565 ///
566 /// ```rust
567 /// extern crate proc_macro;
568 /// use proc_macro::TokenStream;
569 ///
570 /// extern crate syn;
571 ///
572 /// #[macro_use]
573 /// extern crate quote;
574 ///
575 /// use syn::DeriveInput;
576 ///
577 /// # const IGNORE_TOKENS: &str = stringify! {
578 /// #[proc_macro_derive(MyMacro)]
579 /// # };
580 /// pub fn my_macro(input: TokenStream) -> TokenStream {
581 /// // Parse the tokens into a syntax tree
582 /// let ast: DeriveInput = syn::parse(input).unwrap();
583 ///
584 /// // Build the output, possibly using quasi-quotation
585 /// let expanded = quote! {
586 /// /* ... */
587 /// };
588 ///
589 /// // Convert into a token stream and return it
590 /// expanded.into()
591 /// }
592 /// #
593 /// # fn main() {}
594 /// ```
595 #[cfg(all(feature = "parsing", feature = "proc-macro"))]
596 pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, ParseError>
597 where
598 T: Synom,
599 {
600 parse2(tokens.into())
601 }
602
603 /// Parse a proc-macro2 token stream into the chosen syntax tree node.
604 ///
605 /// This function parses a `proc_macro2::TokenStream` which is commonly useful
606 /// when the input comes from a node of the Syn syntax tree, for example the tts
607 /// of a [`Macro`] node. When in a procedural macro parsing the
608 /// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
609 /// instead.
610 ///
611 /// [`Macro`]: struct.Macro.html
612 /// [`syn::parse`]: fn.parse.html
613 ///
614 /// *This function is available if Syn is built with the `"parsing"` feature.*
615 #[cfg(feature = "parsing")]
616 pub fn parse2<T>(tokens: proc_macro2::TokenStream) -> Result<T, ParseError>
617 where
618 T: Synom,
619 {
620 let parser = T::parse;
621 parser.parse2(tokens).map_err(|err| match T::description() {
622 Some(s) => ParseError::new(format!("failed to parse {}: {}", s, err)),
623 None => err,
624 })
625 }
626
627 /// Parse a string of Rust code into the chosen syntax tree node.
628 ///
629 /// *This function is available if Syn is built with the `"parsing"` feature.*
630 ///
631 /// # Hygiene
632 ///
633 /// Every span in the resulting syntax tree will be set to resolve at the macro
634 /// call site.
635 ///
636 /// # Examples
637 ///
638 /// ```rust
639 /// extern crate syn;
640 /// #
641 /// #
642 /// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
643 ///
644 /// use syn::Expr;
645 ///
646 /// fn run() -> Result<()> {
647 /// let code = "assert_eq!(u8::max_value(), 255)";
648 /// let expr = syn::parse_str::<Expr>(code)?;
649 /// println!("{:#?}", expr);
650 /// Ok(())
651 /// }
652 /// #
653 /// # fn main() { run().unwrap() }
654 /// ```
655 #[cfg(feature = "parsing")]
656 pub fn parse_str<T: Synom>(s: &str) -> Result<T, ParseError> {
657 match s.parse() {
658 Ok(tts) => parse2(tts),
659 Err(_) => Err(ParseError::new("error while lexing input string")),
660 }
661 }
662
663 // FIXME the name parse_file makes it sound like you might pass in a path to a
664 // file, rather than the content.
665 /// Parse the content of a file of Rust code.
666 ///
667 /// This is different from `syn::parse_str::<File>(content)` in two ways:
668 ///
669 /// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
670 /// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
671 ///
672 /// If present, either of these would be an error using `from_str`.
673 ///
674 /// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
675 ///
676 /// # Examples
677 ///
678 /// ```rust,no_run
679 /// extern crate syn;
680 /// #
681 /// #
682 /// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
683 ///
684 /// use std::fs::File;
685 /// use std::io::Read;
686 ///
687 /// fn run() -> Result<()> {
688 /// let mut file = File::open("path/to/code.rs")?;
689 /// let mut content = String::new();
690 /// file.read_to_string(&mut content)?;
691 ///
692 /// let ast = syn::parse_file(&content)?;
693 /// if let Some(shebang) = ast.shebang {
694 /// println!("{}", shebang);
695 /// }
696 /// println!("{} items", ast.items.len());
697 ///
698 /// Ok(())
699 /// }
700 /// #
701 /// # fn main() { run().unwrap() }
702 /// ```
703 #[cfg(all(feature = "parsing", feature = "full"))]
704 pub fn parse_file(mut content: &str) -> Result<File, ParseError> {
705 // Strip the BOM if it is present
706 const BOM: &'static str = "\u{feff}";
707 if content.starts_with(BOM) {
708 content = &content[BOM.len()..];
709 }
710
711 let mut shebang = None;
712 if content.starts_with("#!") && !content.starts_with("#![") {
713 if let Some(idx) = content.find('\n') {
714 shebang = Some(content[..idx].to_string());
715 content = &content[idx..];
716 } else {
717 shebang = Some(content.to_string());
718 content = "";
719 }
720 }
721
722 let mut file: File = parse_str(content)?;
723 file.shebang = shebang;
724 Ok(file)
725 }
726
727 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
728 struct TokensOrDefault<'a, T: 'a>(&'a Option<T>);
729
730 #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
731 impl<'a, T> quote::ToTokens for TokensOrDefault<'a, T>
732 where
733 T: quote::ToTokens + Default,
734 {
735 fn to_tokens(&self, tokens: &mut quote::Tokens) {
736 match *self.0 {
737 Some(ref t) => t.to_tokens(tokens),
738 None => T::default().to_tokens(tokens),
739 }
740 }
741 }