1 #[cfg(feature = "parsing")]
3 #[cfg(feature = "parsing")]
4 use crate::parse
::{Parse, Parser}
;
5 use crate::{Error, Result}
;
6 #[cfg(feature = "printing")]
7 use proc_macro2
::Ident
;
8 #[cfg(feature = "parsing")]
9 use proc_macro2
::TokenStream
;
10 use proc_macro2
::TokenTree
;
11 use proc_macro2
::{Literal, Span}
;
12 use std
::fmt
::{self, Display}
;
13 #[cfg(feature = "extra-traits")]
14 use std
::hash
::{Hash, Hasher}
;
15 use std
::str::{self, FromStr}
;
17 ast_enum_of_structs
! {
18 /// A Rust literal such as a string or integer or boolean.
20 /// # Syntax tree enum
22 /// This type is a [syntax tree enum].
24 /// [syntax tree enum]: crate::Expr#syntax-tree-enums
26 /// A UTF-8 string literal: `"foo"`.
29 /// A byte string literal: `b"foo"`.
32 /// A byte literal: `b'f'`.
35 /// A character literal: `'a'`.
38 /// An integer literal: `1` or `1u16`.
41 /// A floating point literal: `1f64` or `1.0e10f64`.
43 /// Must be finite. May not be infinite or NaN.
46 /// A boolean literal: `true` or `false`.
49 /// A raw token literal not interpreted by Syn.
55 /// A UTF-8 string literal: `"foo"`.
62 /// A byte string literal: `b"foo"`.
63 pub struct LitByteStr
{
69 /// A byte literal: `b'f'`.
76 /// A character literal: `'a'`.
88 /// An integer literal: `1` or `1u16`.
90 repr
: Box
<LitIntRepr
>,
101 /// A floating point literal: `1f64` or `1.0e10f64`.
103 /// Must be finite. May not be infinite or NaN.
104 pub struct LitFloat
{
105 repr
: Box
<LitFloatRepr
>,
109 struct LitFloatRepr
{
116 /// A boolean literal: `true` or `false`.
124 pub fn new(value
: &str, span
: Span
) -> Self {
125 let mut token
= Literal
::string(value
);
126 token
.set_span(span
);
128 repr
: Box
::new(LitRepr
{
130 suffix
: Box
::<str>::default(),
135 pub fn value(&self) -> String
{
136 let repr
= self.repr
.token
.to_string();
137 let (value
, _suffix
) = value
::parse_lit_str(&repr
);
141 /// Parse a syntax tree node from the content of this string literal.
143 /// All spans in the syntax tree will point to the span of this `LitStr`.
148 /// use proc_macro2::Span;
149 /// use syn::{Attribute, Error, Ident, Lit, Meta, MetaNameValue, Path, Result};
151 /// // Parses the path from an attribute that looks like:
153 /// // #[path = "a::b::c"]
155 /// // or returns `None` if the input is some other attribute.
156 /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
157 /// if !attr.path.is_ident("path") {
161 /// match attr.parse_meta()? {
162 /// Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
163 /// lit_str.parse().map(Some)
166 /// let message = "expected #[path = \"...\"]";
167 /// Err(Error::new_spanned(attr, message))
172 #[cfg(feature = "parsing")]
173 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
174 pub fn parse
<T
: Parse
>(&self) -> Result
<T
> {
175 self.parse_with(T
::parse
)
178 /// Invoke parser on the content of this string literal.
180 /// All spans in the syntax tree will point to the span of this `LitStr`.
185 /// # use proc_macro2::Span;
186 /// # use syn::{LitStr, Result};
188 /// # fn main() -> Result<()> {
189 /// # let lit_str = LitStr::new("a::b::c", Span::call_site());
191 /// # const IGNORE: &str = stringify! {
192 /// let lit_str: LitStr = /* ... */;
195 /// // Parse a string literal like "a::b::c" into a Path, not allowing
196 /// // generic arguments on any of the path segments.
197 /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
202 #[cfg(feature = "parsing")]
203 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
204 pub fn parse_with
<F
: Parser
>(&self, parser
: F
) -> Result
<F
::Output
> {
205 use proc_macro2
::Group
;
207 // Token stream with every span replaced by the given one.
208 fn respan_token_stream(stream
: TokenStream
, span
: Span
) -> TokenStream
{
211 .map(|token
| respan_token_tree(token
, span
))
215 // Token tree with every span replaced by the given one.
216 fn respan_token_tree(mut token
: TokenTree
, span
: Span
) -> TokenTree
{
218 TokenTree
::Group(g
) => {
219 let stream
= respan_token_stream(g
.stream(), span
);
220 *g
= Group
::new(g
.delimiter(), stream
);
223 other
=> other
.set_span(span
),
228 // Parse string literal into a token stream with every span equal to the
229 // original literal's span.
230 let mut tokens
= crate::parse_str(&self.value())?
;
231 tokens
= respan_token_stream(tokens
, self.span());
233 parser
.parse2(tokens
)
236 pub fn span(&self) -> Span
{
237 self.repr
.token
.span()
240 pub fn set_span(&mut self, span
: Span
) {
241 self.repr
.token
.set_span(span
);
244 pub fn suffix(&self) -> &str {
250 pub fn new(value
: &[u8], span
: Span
) -> Self {
251 let mut token
= Literal
::byte_string(value
);
252 token
.set_span(span
);
254 repr
: Box
::new(LitRepr
{
256 suffix
: Box
::<str>::default(),
261 pub fn value(&self) -> Vec
<u8> {
262 let repr
= self.repr
.token
.to_string();
263 let (value
, _suffix
) = value
::parse_lit_byte_str(&repr
);
267 pub fn span(&self) -> Span
{
268 self.repr
.token
.span()
271 pub fn set_span(&mut self, span
: Span
) {
272 self.repr
.token
.set_span(span
);
275 pub fn suffix(&self) -> &str {
281 pub fn new(value
: u8, span
: Span
) -> Self {
282 let mut token
= Literal
::u8_suffixed(value
);
283 token
.set_span(span
);
285 repr
: Box
::new(LitRepr
{
287 suffix
: Box
::<str>::default(),
292 pub fn value(&self) -> u8 {
293 let repr
= self.repr
.token
.to_string();
294 let (value
, _suffix
) = value
::parse_lit_byte(&repr
);
298 pub fn span(&self) -> Span
{
299 self.repr
.token
.span()
302 pub fn set_span(&mut self, span
: Span
) {
303 self.repr
.token
.set_span(span
);
306 pub fn suffix(&self) -> &str {
312 pub fn new(value
: char, span
: Span
) -> Self {
313 let mut token
= Literal
::character(value
);
314 token
.set_span(span
);
316 repr
: Box
::new(LitRepr
{
318 suffix
: Box
::<str>::default(),
323 pub fn value(&self) -> char {
324 let repr
= self.repr
.token
.to_string();
325 let (value
, _suffix
) = value
::parse_lit_char(&repr
);
329 pub fn span(&self) -> Span
{
330 self.repr
.token
.span()
333 pub fn set_span(&mut self, span
: Span
) {
334 self.repr
.token
.set_span(span
);
337 pub fn suffix(&self) -> &str {
343 pub fn new(repr
: &str, span
: Span
) -> Self {
344 let (digits
, suffix
) = match value
::parse_lit_int(repr
) {
345 Some(parse
) => parse
,
346 None
=> panic
!("Not an integer literal: `{}`", repr
),
349 let mut token
= match value
::to_literal(repr
, &digits
, &suffix
) {
350 Some(token
) => token
,
351 None
=> panic
!("Unsupported integer literal: `{}`", repr
),
354 token
.set_span(span
);
356 repr
: Box
::new(LitIntRepr
{
364 pub fn base10_digits(&self) -> &str {
368 /// Parses the literal into a selected number type.
370 /// This is equivalent to `lit.base10_digits().parse()` except that the
371 /// resulting errors will be correctly spanned to point to the literal token
372 /// in the macro input.
376 /// use syn::parse::{Parse, ParseStream, Result};
382 /// impl Parse for Port {
383 /// fn parse(input: ParseStream) -> Result<Self> {
384 /// let lit: LitInt = input.parse()?;
385 /// let value = lit.base10_parse::<u16>()?;
386 /// Ok(Port { value })
390 pub fn base10_parse
<N
>(&self) -> Result
<N
>
397 .map_err(|err
| Error
::new(self.span(), err
))
400 pub fn suffix(&self) -> &str {
404 pub fn span(&self) -> Span
{
405 self.repr
.token
.span()
408 pub fn set_span(&mut self, span
: Span
) {
409 self.repr
.token
.set_span(span
);
413 impl From
<Literal
> for LitInt
{
414 fn from(token
: Literal
) -> Self {
415 let repr
= token
.to_string();
416 if let Some((digits
, suffix
)) = value
::parse_lit_int(&repr
) {
418 repr
: Box
::new(LitIntRepr
{
425 panic
!("Not an integer literal: `{}`", repr
);
430 impl Display
for LitInt
{
431 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
432 self.repr
.token
.fmt(formatter
)
437 pub fn new(repr
: &str, span
: Span
) -> Self {
438 let (digits
, suffix
) = match value
::parse_lit_float(repr
) {
439 Some(parse
) => parse
,
440 None
=> panic
!("Not a float literal: `{}`", repr
),
443 let mut token
= match value
::to_literal(repr
, &digits
, &suffix
) {
444 Some(token
) => token
,
445 None
=> panic
!("Unsupported float literal: `{}`", repr
),
448 token
.set_span(span
);
450 repr
: Box
::new(LitFloatRepr
{
458 pub fn base10_digits(&self) -> &str {
462 pub fn base10_parse
<N
>(&self) -> Result
<N
>
469 .map_err(|err
| Error
::new(self.span(), err
))
472 pub fn suffix(&self) -> &str {
476 pub fn span(&self) -> Span
{
477 self.repr
.token
.span()
480 pub fn set_span(&mut self, span
: Span
) {
481 self.repr
.token
.set_span(span
);
485 impl From
<Literal
> for LitFloat
{
486 fn from(token
: Literal
) -> Self {
487 let repr
= token
.to_string();
488 if let Some((digits
, suffix
)) = value
::parse_lit_float(&repr
) {
490 repr
: Box
::new(LitFloatRepr
{
497 panic
!("Not a float literal: `{}`", repr
);
502 impl Display
for LitFloat
{
503 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
504 self.repr
.token
.fmt(formatter
)
509 pub fn new(value
: bool
, span
: Span
) -> Self {
510 LitBool { value, span }
513 pub fn value(&self) -> bool
{
517 pub fn span(&self) -> Span
{
521 pub fn set_span(&mut self, span
: Span
) {
526 #[cfg(feature = "extra-traits")]
529 use std
::fmt
::{self, Debug}
;
531 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
532 impl Debug
for LitStr
{
533 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
535 .debug_struct("LitStr")
536 .field("token", &format_args
!("{}", self.repr
.token
))
541 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
542 impl Debug
for LitByteStr
{
543 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
545 .debug_struct("LitByteStr")
546 .field("token", &format_args
!("{}", self.repr
.token
))
551 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
552 impl Debug
for LitByte
{
553 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
555 .debug_struct("LitByte")
556 .field("token", &format_args
!("{}", self.repr
.token
))
561 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
562 impl Debug
for LitChar
{
563 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
565 .debug_struct("LitChar")
566 .field("token", &format_args
!("{}", self.repr
.token
))
571 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
572 impl Debug
for LitInt
{
573 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
575 .debug_struct("LitInt")
576 .field("token", &format_args
!("{}", self.repr
.token
))
581 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
582 impl Debug
for LitFloat
{
583 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
585 .debug_struct("LitFloat")
586 .field("token", &format_args
!("{}", self.repr
.token
))
591 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
592 impl Debug
for LitBool
{
593 fn fmt(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
595 .debug_struct("LitBool")
596 .field("value", &self.value
)
602 #[cfg(feature = "clone-impls")]
603 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
604 impl Clone
for LitRepr
{
605 fn clone(&self) -> Self {
607 token
: self.token
.clone(),
608 suffix
: self.suffix
.clone(),
613 #[cfg(feature = "clone-impls")]
614 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
615 impl Clone
for LitIntRepr
{
616 fn clone(&self) -> Self {
618 token
: self.token
.clone(),
619 digits
: self.digits
.clone(),
620 suffix
: self.suffix
.clone(),
625 #[cfg(feature = "clone-impls")]
626 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
627 impl Clone
for LitFloatRepr
{
628 fn clone(&self) -> Self {
630 token
: self.token
.clone(),
631 digits
: self.digits
.clone(),
632 suffix
: self.suffix
.clone(),
637 macro_rules
! lit_extra_traits
{
639 #[cfg(feature = "clone-impls")]
640 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
642 fn clone(&self) -> Self {
644 repr
: self.repr
.clone(),
649 #[cfg(feature = "extra-traits")]
650 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
651 impl PartialEq
for $ty
{
652 fn eq(&self, other
: &Self) -> bool
{
653 self.repr
.token
.to_string() == other
.repr
.token
.to_string()
657 #[cfg(feature = "extra-traits")]
658 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
660 fn hash
<H
>(&self, state
: &mut H
)
664 self.repr
.token
.to_string().hash(state
);
668 #[cfg(feature = "parsing")]
670 #[allow(non_snake_case)]
671 pub fn $
ty(marker
: lookahead
::TokenMarker
) -> $ty
{
677 lit_extra_traits
!(LitStr
);
678 lit_extra_traits
!(LitByteStr
);
679 lit_extra_traits
!(LitByte
);
680 lit_extra_traits
!(LitChar
);
681 lit_extra_traits
!(LitInt
);
682 lit_extra_traits
!(LitFloat
);
684 #[cfg(feature = "parsing")]
686 #[allow(non_snake_case)]
687 pub fn LitBool(marker
: lookahead
::TokenMarker
) -> LitBool
{
692 /// The style of a string literal, either plain quoted or a raw string like
694 pub enum StrStyle
#no_visit {
695 /// An ordinary string like `"data"`.
697 /// A raw string like `r##"data"##`.
699 /// The unsigned integer is the number of `#` symbols used.
704 #[cfg(feature = "parsing")]
706 #[allow(non_snake_case)]
707 pub fn Lit(marker
: lookahead
::TokenMarker
) -> Lit
{
711 #[cfg(feature = "parsing")]
714 use crate::buffer
::Cursor
;
715 use crate::parse
::{Parse, ParseStream, Result}
;
716 use proc_macro2
::Punct
;
718 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
720 fn parse(input
: ParseStream
) -> Result
<Self> {
721 input
.step(|cursor
| {
722 if let Some((lit
, rest
)) = cursor
.literal() {
723 return Ok((Lit
::new(lit
), rest
));
726 if let Some((ident
, rest
)) = cursor
.ident() {
727 let value
= ident
== "true";
728 if value
|| ident
== "false" {
729 let lit_bool
= LitBool
{
733 return Ok((Lit
::Bool(lit_bool
), rest
));
737 if let Some((punct
, rest
)) = cursor
.punct() {
738 if punct
.as_char() == '
-'
{
739 if let Some((lit
, rest
)) = parse_negative_lit(punct
, rest
) {
740 return Ok((lit
, rest
));
745 Err(cursor
.error("expected literal"))
750 fn parse_negative_lit(neg
: Punct
, cursor
: Cursor
) -> Option
<(Lit
, Cursor
)> {
751 let (lit
, rest
) = cursor
.literal()?
;
753 let mut span
= neg
.span();
754 span
= span
.join(lit
.span()).unwrap_or(span
);
756 let mut repr
= lit
.to_string();
759 if let Some((digits
, suffix
)) = value
::parse_lit_int(&repr
) {
760 if let Some(mut token
) = value
::to_literal(&repr
, &digits
, &suffix
) {
761 token
.set_span(span
);
764 repr
: Box
::new(LitIntRepr
{
775 let (digits
, suffix
) = value
::parse_lit_float(&repr
)?
;
776 let mut token
= value
::to_literal(&repr
, &digits
, &suffix
)?
;
777 token
.set_span(span
);
779 Lit
::Float(LitFloat
{
780 repr
: Box
::new(LitFloatRepr
{
790 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
791 impl Parse
for LitStr
{
792 fn parse(input
: ParseStream
) -> Result
<Self> {
793 let head
= input
.fork();
794 match input
.parse() {
795 Ok(Lit
::Str(lit
)) => Ok(lit
),
796 _
=> Err(head
.error("expected string literal")),
801 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
802 impl Parse
for LitByteStr
{
803 fn parse(input
: ParseStream
) -> Result
<Self> {
804 let head
= input
.fork();
805 match input
.parse() {
806 Ok(Lit
::ByteStr(lit
)) => Ok(lit
),
807 _
=> Err(head
.error("expected byte string literal")),
812 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
813 impl Parse
for LitByte
{
814 fn parse(input
: ParseStream
) -> Result
<Self> {
815 let head
= input
.fork();
816 match input
.parse() {
817 Ok(Lit
::Byte(lit
)) => Ok(lit
),
818 _
=> Err(head
.error("expected byte literal")),
823 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
824 impl Parse
for LitChar
{
825 fn parse(input
: ParseStream
) -> Result
<Self> {
826 let head
= input
.fork();
827 match input
.parse() {
828 Ok(Lit
::Char(lit
)) => Ok(lit
),
829 _
=> Err(head
.error("expected character literal")),
834 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
835 impl Parse
for LitInt
{
836 fn parse(input
: ParseStream
) -> Result
<Self> {
837 let head
= input
.fork();
838 match input
.parse() {
839 Ok(Lit
::Int(lit
)) => Ok(lit
),
840 _
=> Err(head
.error("expected integer literal")),
845 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
846 impl Parse
for LitFloat
{
847 fn parse(input
: ParseStream
) -> Result
<Self> {
848 let head
= input
.fork();
849 match input
.parse() {
850 Ok(Lit
::Float(lit
)) => Ok(lit
),
851 _
=> Err(head
.error("expected floating point literal")),
856 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
857 impl Parse
for LitBool
{
858 fn parse(input
: ParseStream
) -> Result
<Self> {
859 let head
= input
.fork();
860 match input
.parse() {
861 Ok(Lit
::Bool(lit
)) => Ok(lit
),
862 _
=> Err(head
.error("expected boolean literal")),
868 #[cfg(feature = "printing")]
871 use proc_macro2
::TokenStream
;
872 use quote
::{ToTokens, TokenStreamExt}
;
874 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
875 impl ToTokens
for LitStr
{
876 fn to_tokens(&self, tokens
: &mut TokenStream
) {
877 self.repr
.token
.to_tokens(tokens
);
881 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
882 impl ToTokens
for LitByteStr
{
883 fn to_tokens(&self, tokens
: &mut TokenStream
) {
884 self.repr
.token
.to_tokens(tokens
);
888 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
889 impl ToTokens
for LitByte
{
890 fn to_tokens(&self, tokens
: &mut TokenStream
) {
891 self.repr
.token
.to_tokens(tokens
);
895 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
896 impl ToTokens
for LitChar
{
897 fn to_tokens(&self, tokens
: &mut TokenStream
) {
898 self.repr
.token
.to_tokens(tokens
);
902 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
903 impl ToTokens
for LitInt
{
904 fn to_tokens(&self, tokens
: &mut TokenStream
) {
905 self.repr
.token
.to_tokens(tokens
);
909 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
910 impl ToTokens
for LitFloat
{
911 fn to_tokens(&self, tokens
: &mut TokenStream
) {
912 self.repr
.token
.to_tokens(tokens
);
916 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
917 impl ToTokens
for LitBool
{
918 fn to_tokens(&self, tokens
: &mut TokenStream
) {
919 let s
= if self.value { "true" }
else { "false" }
;
920 tokens
.append(Ident
::new(s
, self.span
));
927 use crate::bigint
::BigInt
;
928 use proc_macro2
::TokenStream
;
930 use std
::ops
::{Index, RangeFrom}
;
933 /// Interpret a Syn literal from a proc-macro2 literal.
934 pub fn new(token
: Literal
) -> Self {
935 let repr
= token
.to_string();
937 match byte(&repr
, 0) {
939 let (_, suffix) = parse_lit_str(&repr);
940 return Lit::Str(LitStr {
941 repr: Box::new(LitRepr { token, suffix }),
944 b'b' => match byte(&repr, 1) {
946 let (_
, suffix
) = parse_lit_byte_str(&repr
);
947 return Lit
::ByteStr(LitByteStr
{
948 repr
: Box
::new(LitRepr { token, suffix }
),
952 let (_
, suffix
) = parse_lit_byte(&repr
);
953 return Lit
::Byte(LitByte
{
954 repr
: Box
::new(LitRepr { token, suffix }
),
960 let (_
, suffix
) = parse_lit_char(&repr
);
961 return Lit
::Char(LitChar
{
962 repr
: Box
::new(LitRepr { token, suffix }
),
965 b'
0'
..=b'
9'
| b'
-'
=> {
966 if let Some((digits
, suffix
)) = parse_lit_int(&repr
) {
967 return Lit
::Int(LitInt
{
968 repr
: Box
::new(LitIntRepr
{
975 if let Some((digits
, suffix
)) = parse_lit_float(&repr
) {
976 return Lit
::Float(LitFloat
{
977 repr
: Box
::new(LitFloatRepr
{
986 if repr
== "true" || repr
== "false" {
987 return Lit
::Bool(LitBool
{
988 value
: repr
== "true",
996 panic
!("Unrecognized literal: `{}`", repr
);
999 pub fn suffix(&self) -> &str {
1001 Lit
::Str(lit
) => lit
.suffix(),
1002 Lit
::ByteStr(lit
) => lit
.suffix(),
1003 Lit
::Byte(lit
) => lit
.suffix(),
1004 Lit
::Char(lit
) => lit
.suffix(),
1005 Lit
::Int(lit
) => lit
.suffix(),
1006 Lit
::Float(lit
) => lit
.suffix(),
1007 Lit
::Bool(_
) | Lit
::Verbatim(_
) => "",
1011 pub fn span(&self) -> Span
{
1013 Lit
::Str(lit
) => lit
.span(),
1014 Lit
::ByteStr(lit
) => lit
.span(),
1015 Lit
::Byte(lit
) => lit
.span(),
1016 Lit
::Char(lit
) => lit
.span(),
1017 Lit
::Int(lit
) => lit
.span(),
1018 Lit
::Float(lit
) => lit
.span(),
1019 Lit
::Bool(lit
) => lit
.span
,
1020 Lit
::Verbatim(lit
) => lit
.span(),
1024 pub fn set_span(&mut self, span
: Span
) {
1026 Lit
::Str(lit
) => lit
.set_span(span
),
1027 Lit
::ByteStr(lit
) => lit
.set_span(span
),
1028 Lit
::Byte(lit
) => lit
.set_span(span
),
1029 Lit
::Char(lit
) => lit
.set_span(span
),
1030 Lit
::Int(lit
) => lit
.set_span(span
),
1031 Lit
::Float(lit
) => lit
.set_span(span
),
1032 Lit
::Bool(lit
) => lit
.span
= span
,
1033 Lit
::Verbatim(lit
) => lit
.set_span(span
),
1038 /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
1039 /// past the end of the input buffer.
1040 pub fn byte
<S
: AsRef
<[u8]> + ?Sized
>(s
: &S
, idx
: usize) -> u8 {
1049 fn next_chr(s
: &str) -> char {
1050 s
.chars().next().unwrap_or('
\0'
)
1053 // Returns (content, suffix).
1054 pub fn parse_lit_str(s
: &str) -> (Box
<str>, Box
<str>) {
1056 b'
"' => parse_lit_str_cooked(s),
1057 b'r' => parse_lit_str_raw(s),
1058 _ => unreachable!(),
1062 // Clippy false positive
1063 // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1064 #[allow(clippy::needless_continue)]
1065 fn parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>) {
1066 assert_eq!(byte(s, 0), b'"'
);
1069 let mut content
= String
::new();
1071 let ch
= match byte(s
, 0) {
1078 let (byte, rest) = backslash_x(s);
1080 assert!(byte <= 0x80, "Invalid
\\x byte
in string literal
");
1081 char::from_u32(u32::from(byte)).unwrap()
1084 let (chr, rest) = backslash_u(s);
1095 b'\r' | b'\n' => loop {
1096 let ch = next_chr(s);
1097 if ch.is_whitespace() {
1098 s = &s[ch.len_utf8()..];
1103 b => panic!("unexpected byte {:?} after
\\ character
in byte literal
", b),
1107 assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed
in string
");
1112 let ch = next_chr(s);
1113 s = &s[ch.len_utf8()..];
1120 assert!(s.starts_with('"'
));
1121 let content
= content
.into_boxed_str();
1122 let suffix
= s
[1..].to_owned().into_boxed_str();
1126 fn parse_lit_str_raw(mut s
: &str) -> (Box
<str>, Box
<str>) {
1127 assert_eq
!(byte(s
, 0), b'r'
);
1131 while byte(s
, pounds
) == b'
#' {
1134 assert_eq
!(byte(s
, pounds
), b'
"');
1135 let close = s.rfind('"'
).unwrap();
1136 for end
in s
[close
+ 1..close
+ 1 + pounds
].bytes() {
1137 assert_eq
!(end
, b'
#');
1140 let content
= s
[pounds
+ 1..close
].to_owned().into_boxed_str();
1141 let suffix
= s
[close
+ 1 + pounds
..].to_owned().into_boxed_str();
1145 // Returns (content, suffix).
1146 pub fn parse_lit_byte_str(s
: &str) -> (Vec
<u8>, Box
<str>) {
1147 assert_eq
!(byte(s
, 0), b'b'
);
1149 b'
"' => parse_lit_byte_str_cooked(s),
1150 b'r' => parse_lit_byte_str_raw(s),
1151 _ => unreachable!(),
1155 // Clippy false positive
1156 // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
1157 #[allow(clippy::needless_continue)]
1158 fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>) {
1159 assert_eq!(byte(s, 0), b'b');
1160 assert_eq!(byte(s, 1), b'"'
);
1163 // We're going to want to have slices which don't respect codepoint boundaries.
1164 let mut v
= s
.as_bytes();
1166 let mut out
= Vec
::new();
1168 let byte
= match byte(v
, 0) {
1175 let (b, rest) = backslash_x(v);
1186 b'\r' | b'\n' => loop {
1187 let byte = byte(v, 0);
1188 let ch = char::from_u32(u32::from(byte)).unwrap();
1189 if ch.is_whitespace() {
1195 b => panic!("unexpected byte {:?} after
\\ character
in byte literal
", b),
1199 assert_eq!(byte(v, 1), b'\n', "Bare CR not allowed
in string
");
1211 assert_eq!(byte(v, 0), b'"'
);
1212 let suffix
= s
[s
.len() - v
.len() + 1..].to_owned().into_boxed_str();
1216 fn parse_lit_byte_str_raw(s
: &str) -> (Vec
<u8>, Box
<str>) {
1217 assert_eq
!(byte(s
, 0), b'b'
);
1218 let (value
, suffix
) = parse_lit_str_raw(&s
[1..]);
1219 (String
::from(value
).into_bytes(), suffix
)
1222 // Returns (value, suffix).
1223 pub fn parse_lit_byte(s
: &str) -> (u8, Box
<str>) {
1224 assert_eq
!(byte(s
, 0), b'b'
);
1225 assert_eq
!(byte(s
, 1), b'
\''
);
1227 // We're going to want to have slices which don't respect codepoint boundaries.
1228 let mut v
= s
[2..].as_bytes();
1230 let b
= match byte(v
, 0) {
1236 let (b
, rest
) = backslash_x(v
);
1247 b
=> panic
!("unexpected byte {:?} after \\ character in byte literal", b
),
1256 assert_eq
!(byte(v
, 0), b'
\''
);
1257 let suffix
= s
[s
.len() - v
.len() + 1..].to_owned().into_boxed_str();
1261 // Returns (value, suffix).
1262 pub fn parse_lit_char(mut s
: &str) -> (char, Box
<str>) {
1263 assert_eq
!(byte(s
, 0), b'
\''
);
1266 let ch
= match byte(s
, 0) {
1272 let (byte
, rest
) = backslash_x(s
);
1274 assert
!(byte
<= 0x80, "Invalid \\x byte in string literal");
1275 char::from_u32(u32::from(byte
)).unwrap()
1278 let (chr
, rest
) = backslash_u(s
);
1289 b
=> panic
!("unexpected byte {:?} after \\ character in byte literal", b
),
1293 let ch
= next_chr(s
);
1294 s
= &s
[ch
.len_utf8()..];
1298 assert_eq
!(byte(s
, 0), b'
\''
);
1299 let suffix
= s
[1..].to_owned().into_boxed_str();
1303 fn backslash_x
<S
>(s
: &S
) -> (u8, &S
)
1305 S
: Index
<RangeFrom
<usize>, Output
= S
> + AsRef
<[u8]> + ?Sized
,
1308 let b0
= byte(s
, 0);
1309 let b1
= byte(s
, 1);
1312 b'
0'
..=b'
9'
=> b0
- b'
0'
,
1313 b'a'
..=b'f'
=> 10 + (b0
- b'a'
),
1314 b'A'
..=b'F'
=> 10 + (b0
- b'A'
),
1315 _
=> panic
!("unexpected non-hex character after \\x"),
1318 b'
0'
..=b'
9'
=> b1
- b'
0'
,
1319 b'a'
..=b'f'
=> 10 + (b1
- b'a'
),
1320 b'A'
..=b'F'
=> 10 + (b1
- b'A'
),
1321 _
=> panic
!("unexpected non-hex character after \\x"),
1326 fn backslash_u(mut s
: &str) -> (char, &str) {
1327 if byte(s
, 0) != b'
{'
{
1328 panic
!("{}", "expected { after \\u");
1336 let digit
= match b
{
1337 b'
0'
..=b'
9'
=> b
- b'
0'
,
1338 b'a'
..=b'f'
=> 10 + b
- b'a'
,
1339 b'A'
..=b'F'
=> 10 + b
- b'A'
,
1340 b'_'
if digits
> 0 => {
1344 b'
}'
if digits
== 0 => panic
!("invalid empty unicode escape"),
1346 _
=> panic
!("unexpected non-hex character after \\u"),
1349 panic
!("overlong unicode escape (must have at most 6 hex digits)");
1352 ch
+= u32::from(digit
);
1356 assert
!(byte(s
, 0) == b'
}'
);
1359 if let Some(ch
) = char::from_u32(ch
) {
1362 panic
!("character code {:x} is not a valid unicode character", ch
);
1366 // Returns base 10 digits and suffix.
1367 pub fn parse_lit_int(mut s
: &str) -> Option
<(Box
<str>, Box
<str>)> {
1368 let negative
= byte(s
, 0) == b'
-'
;
1373 let base
= match (byte(s
, 0), byte(s
, 1)) {
1386 (b'
0'
..=b'
9'
, _
) => 10,
1390 let mut value
= BigInt
::new();
1393 let digit
= match b
{
1394 b'
0'
..=b'
9'
=> b
- b'
0'
,
1395 b'a'
..=b'f'
if base
> 10 => b
- b'a'
+ 10,
1396 b'A'
..=b'F'
if base
> 10 => b
- b'A'
+ 10,
1401 // If looking at a floating point literal, we don't want to
1402 // consider it an integer.
1403 b'
.'
if base
== 10 => return None
,
1404 b'e'
| b'E'
if base
== 10 => {
1405 let mut has_exp
= false;
1406 for (i
, b
) in s
[1..].bytes().enumerate() {
1409 b'
-'
| b'
+'
=> return None
,
1410 b'
0'
..=b'
9'
=> has_exp
= true,
1412 let suffix
= &s
[1 + i
..];
1413 if has_exp
&& crate::ident
::xid_ok(suffix
) {
1440 if suffix
.is_empty() || crate::ident
::xid_ok(suffix
) {
1441 let mut repr
= value
.to_string();
1443 repr
.insert(0, '
-'
);
1445 Some((repr
.into_boxed_str(), suffix
.to_owned().into_boxed_str()))
1451 // Returns base 10 digits and suffix.
1452 pub fn parse_lit_float(input
: &str) -> Option
<(Box
<str>, Box
<str>)> {
1453 // Rust's floating point literals are very similar to the ones parsed by
1454 // the standard library, except that rust's literals can contain
1455 // ignorable underscores. Let's remove those underscores.
1457 let mut bytes
= input
.to_owned().into_bytes();
1459 let start
= (*bytes
.get(0)?
== b'
-'
) as usize;
1460 match bytes
.get(start
)?
{
1465 let mut read
= start
;
1466 let mut write
= start
;
1467 let mut has_dot
= false;
1468 let mut has_e
= false;
1469 let mut has_sign
= false;
1470 let mut has_exponent
= false;
1471 while read
< bytes
.len() {
1474 // Don't increase write
1480 has_exponent
= true;
1482 bytes
[write
] = bytes
[read
];
1485 if has_e
|| has_dot
{
1489 bytes
[write
] = b'
.'
;
1492 match bytes
[read
+ 1..]
1494 .find(|b
| **b
!= b'_'
)
1497 b'
-'
| b'
+'
| b'
0'
..=b'
9'
=> {}
1508 bytes
[write
] = b'e'
;
1511 if has_sign
|| has_exponent
|| !has_e
{
1515 if bytes
[read
] == b'
-'
{
1516 bytes
[write
] = bytes
[read
];
1529 if has_e
&& !has_exponent
{
1533 let mut digits
= String
::from_utf8(bytes
).unwrap();
1534 let suffix
= digits
.split_off(read
);
1535 digits
.truncate(write
);
1536 if suffix
.is_empty() || crate::ident
::xid_ok(&suffix
) {
1537 Some((digits
.into_boxed_str(), suffix
.into_boxed_str()))
1543 pub fn to_literal(repr
: &str, digits
: &str, suffix
: &str) -> Option
<Literal
> {
1544 if repr
.starts_with('
-'
) {
1545 let f64_parse_finite
= || digits
.parse().ok().filter(|x
: &f64| x
.is_finite());
1546 let f32_parse_finite
= || digits
.parse().ok().filter(|x
: &f32| x
.is_finite());
1547 if suffix
== "f64" {
1548 f64_parse_finite().map(Literal
::f64_suffixed
)
1549 } else if suffix
== "f32" {
1550 f32_parse_finite().map(Literal
::f32_suffixed
)
1551 } else if suffix
== "i64" {
1552 digits
.parse().ok().map(Literal
::i64_suffixed
)
1553 } else if suffix
== "i32" {
1554 digits
.parse().ok().map(Literal
::i32_suffixed
)
1555 } else if suffix
== "i16" {
1556 digits
.parse().ok().map(Literal
::i16_suffixed
)
1557 } else if suffix
== "i8" {
1558 digits
.parse().ok().map(Literal
::i8_suffixed
)
1559 } else if !suffix
.is_empty() {
1561 } else if digits
.contains('
.'
) {
1562 f64_parse_finite().map(Literal
::f64_unsuffixed
)
1564 digits
.parse().ok().map(Literal
::i64_unsuffixed
)
1567 let stream
= repr
.parse
::<TokenStream
>().unwrap();
1568 match stream
.into_iter().next().unwrap() {
1569 TokenTree
::Literal(l
) => Some(l
),
1570 _
=> unreachable
!(),