standalone_syn/
lit.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
9use proc_macro2::{Literal, Span, TokenNode};
10use std::str;
11
12#[cfg(feature = "printing")]
13use proc_macro2::Term;
14
15#[cfg(feature = "parsing")]
16use proc_macro2::TokenStream;
17#[cfg(feature = "parsing")]
18use {ParseError, Synom};
19
20#[cfg(any(feature = "printing", feature = "parsing"))]
21use proc_macro2::TokenTree;
22
23#[cfg(feature = "extra-traits")]
24use std::hash::{Hash, Hasher};
25
26ast_enum_of_structs! {
27    /// A Rust literal such as a string or integer or boolean.
28    ///
29    /// *This type is available if Syn is built with the `"derive"` or `"full"`
30    /// feature.*
31    ///
32    /// # Syntax tree enum
33    ///
34    /// This type is a [syntax tree enum].
35    ///
36    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
37    pub enum Lit {
38        /// A UTF-8 string literal: `"foo"`.
39        ///
40        /// *This type is available if Syn is built with the `"derive"` or
41        /// `"full"` feature.*
42        pub Str(LitStr #manual_extra_traits {
43            token: Literal,
44            pub span: Span,
45        }),
46
47        /// A byte string literal: `b"foo"`.
48        ///
49        /// *This type is available if Syn is built with the `"derive"` or
50        /// `"full"` feature.*
51        pub ByteStr(LitByteStr #manual_extra_traits {
52            token: Literal,
53            pub span: Span,
54        }),
55
56        /// A byte literal: `b'f'`.
57        ///
58        /// *This type is available if Syn is built with the `"derive"` or
59        /// `"full"` feature.*
60        pub Byte(LitByte #manual_extra_traits {
61            token: Literal,
62            pub span: Span,
63        }),
64
65        /// A character literal: `'a'`.
66        ///
67        /// *This type is available if Syn is built with the `"derive"` or
68        /// `"full"` feature.*
69        pub Char(LitChar #manual_extra_traits {
70            token: Literal,
71            pub span: Span,
72        }),
73
74        /// An integer literal: `1` or `1u16`.
75        ///
76        /// Holds up to 64 bits of data. Use `LitVerbatim` for any larger
77        /// integer literal.
78        ///
79        /// *This type is available if Syn is built with the `"derive"` or
80        /// `"full"` feature.*
81        pub Int(LitInt #manual_extra_traits {
82            token: Literal,
83            pub span: Span,
84        }),
85
86        /// A floating point literal: `1f64` or `1.0e10f64`.
87        ///
88        /// Must be finite. May not be infinte or NaN.
89        ///
90        /// *This type is available if Syn is built with the `"derive"` or
91        /// `"full"` feature.*
92        pub Float(LitFloat #manual_extra_traits {
93            token: Literal,
94            pub span: Span,
95        }),
96
97        /// A boolean literal: `true` or `false`.
98        ///
99        /// *This type is available if Syn is built with the `"derive"` or
100        /// `"full"` feature.*
101        pub Bool(LitBool #manual_extra_traits {
102            pub value: bool,
103            pub span: Span,
104        }),
105
106        /// A raw token literal not interpreted by Syn, possibly because it
107        /// represents an integer larger than 64 bits.
108        ///
109        /// *This type is available if Syn is built with the `"derive"` or
110        /// `"full"` feature.*
111        pub Verbatim(LitVerbatim #manual_extra_traits {
112            pub token: Literal,
113            pub span: Span,
114        }),
115    }
116}
117
118impl LitStr {
119    pub fn new(value: &str, span: Span) -> Self {
120        LitStr {
121            token: Literal::string(value),
122            span: span,
123        }
124    }
125
126    pub fn value(&self) -> String {
127        value::parse_lit_str(&self.token.to_string())
128    }
129
130    /// Parse a syntax tree node from the content of this string literal.
131    ///
132    /// All spans in the syntax tree will point to the span of this `LitStr`.
133    #[cfg(feature = "parsing")]
134    pub fn parse<T: Synom>(&self) -> Result<T, ParseError> {
135        // Parse string literal into a token stream with every span equal to the
136        // original literal's span.
137        fn spanned_tokens(s: &LitStr) -> Result<TokenStream, ParseError> {
138            let stream = ::parse_str(&s.value())?;
139            Ok(respan_token_stream(stream, s.span))
140        }
141
142        // Token stream with every span replaced by the given one.
143        fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
144            stream.into_iter().map(|token| respan_token_tree(token, span)).collect()
145        }
146
147        // Token tree with every span replaced by the given one.
148        fn respan_token_tree(token: TokenTree, span: Span) -> TokenTree {
149            TokenTree {
150                span: span,
151                kind: match token.kind {
152                    TokenNode::Group(delimiter, nested) => {
153                        TokenNode::Group(delimiter, respan_token_stream(nested, span))
154                    }
155                    other => other,
156                },
157            }
158        }
159
160        spanned_tokens(self).and_then(::parse2)
161    }
162}
163
164impl LitByteStr {
165    pub fn new(value: &[u8], span: Span) -> Self {
166        LitByteStr {
167            token: Literal::byte_string(value),
168            span: span,
169        }
170    }
171
172    pub fn value(&self) -> Vec<u8> {
173        value::parse_lit_byte_str(&self.token.to_string())
174    }
175}
176
177impl LitByte {
178    pub fn new(value: u8, span: Span) -> Self {
179        LitByte {
180            token: Literal::byte_char(value),
181            span: span,
182        }
183    }
184
185    pub fn value(&self) -> u8 {
186        value::parse_lit_byte(&self.token.to_string())
187    }
188}
189
190impl LitChar {
191    pub fn new(value: char, span: Span) -> Self {
192        LitChar {
193            token: Literal::character(value),
194            span: span,
195        }
196    }
197
198    pub fn value(&self) -> char {
199        value::parse_lit_char(&self.token.to_string())
200    }
201}
202
203impl LitInt {
204    pub fn new(value: u64, suffix: IntSuffix, span: Span) -> Self {
205        LitInt {
206            token: match suffix {
207                IntSuffix::Isize => Literal::isize(value as isize),
208                IntSuffix::I8 => Literal::i8(value as i8),
209                IntSuffix::I16 => Literal::i16(value as i16),
210                IntSuffix::I32 => Literal::i32(value as i32),
211                IntSuffix::I64 => Literal::i64(value as i64),
212                IntSuffix::I128 => value::to_literal(&format!("{}i128", value)),
213                IntSuffix::Usize => Literal::usize(value as usize),
214                IntSuffix::U8 => Literal::u8(value as u8),
215                IntSuffix::U16 => Literal::u16(value as u16),
216                IntSuffix::U32 => Literal::u32(value as u32),
217                IntSuffix::U64 => Literal::u64(value),
218                IntSuffix::U128 => value::to_literal(&format!("{}u128", value)),
219                IntSuffix::None => Literal::integer(value as i64),
220            },
221            span: span,
222        }
223    }
224
225    pub fn value(&self) -> u64 {
226        value::parse_lit_int(&self.token.to_string()).unwrap()
227    }
228
229    pub fn suffix(&self) -> IntSuffix {
230        let value = self.token.to_string();
231        for (s, suffix) in vec![
232            ("i8", IntSuffix::I8),
233            ("i16", IntSuffix::I16),
234            ("i32", IntSuffix::I32),
235            ("i64", IntSuffix::I64),
236            ("i128", IntSuffix::I128),
237            ("isize", IntSuffix::Isize),
238            ("u8", IntSuffix::U8),
239            ("u16", IntSuffix::U16),
240            ("u32", IntSuffix::U32),
241            ("u64", IntSuffix::U64),
242            ("u128", IntSuffix::U128),
243            ("usize", IntSuffix::Usize),
244        ] {
245            if value.ends_with(s) {
246                return suffix;
247            }
248        }
249        IntSuffix::None
250    }
251}
252
253impl LitFloat {
254    pub fn new(value: f64, suffix: FloatSuffix, span: Span) -> Self {
255        LitFloat {
256            token: match suffix {
257                FloatSuffix::F32 => Literal::f32(value as f32),
258                FloatSuffix::F64 => Literal::f64(value),
259                FloatSuffix::None => Literal::float(value),
260            },
261            span: span,
262        }
263    }
264
265    pub fn value(&self) -> f64 {
266        value::parse_lit_float(&self.token.to_string())
267    }
268
269    pub fn suffix(&self) -> FloatSuffix {
270        let value = self.token.to_string();
271        for (s, suffix) in vec![("f32", FloatSuffix::F32), ("f64", FloatSuffix::F64)] {
272            if value.ends_with(s) {
273                return suffix;
274            }
275        }
276        FloatSuffix::None
277    }
278}
279
280macro_rules! lit_extra_traits {
281    ($ty:ident, $field:ident) => {
282        #[cfg(feature = "extra-traits")]
283        impl Eq for $ty {}
284
285        #[cfg(feature = "extra-traits")]
286        impl PartialEq for $ty {
287            fn eq(&self, other: &Self) -> bool {
288                self.$field.to_string() == other.$field.to_string()
289            }
290        }
291
292        #[cfg(feature = "extra-traits")]
293        impl Hash for $ty {
294            fn hash<H>(&self, state: &mut H)
295            where
296                H: Hasher,
297            {
298                self.$field.to_string().hash(state);
299            }
300        }
301    }
302}
303
304lit_extra_traits!(LitStr, token);
305lit_extra_traits!(LitByteStr, token);
306lit_extra_traits!(LitByte, token);
307lit_extra_traits!(LitChar, token);
308lit_extra_traits!(LitInt, token);
309lit_extra_traits!(LitFloat, token);
310lit_extra_traits!(LitBool, value);
311lit_extra_traits!(LitVerbatim, token);
312
313ast_enum! {
314    /// The style of a string literal, either plain quoted or a raw string like
315    /// `r##"data"##`.
316    ///
317    /// *This type is available if Syn is built with the `"derive"` or `"full"`
318    /// feature.*
319    pub enum StrStyle #no_visit {
320        /// An ordinary string like `"data"`.
321        Cooked,
322        /// A raw string like `r##"data"##`.
323        ///
324        /// The unsigned integer is the number of `#` symbols used.
325        Raw(usize),
326    }
327}
328
329ast_enum! {
330    /// The suffix on an integer literal if any, like the `u8` in `127u8`.
331    ///
332    /// *This type is available if Syn is built with the `"derive"` or `"full"`
333    /// feature.*
334    pub enum IntSuffix #no_visit {
335        I8,
336        I16,
337        I32,
338        I64,
339        I128,
340        Isize,
341        U8,
342        U16,
343        U32,
344        U64,
345        U128,
346        Usize,
347        None,
348    }
349}
350
351ast_enum! {
352    /// The suffix on a floating point literal if any, like the `f32` in
353    /// `1.0f32`.
354    ///
355    /// *This type is available if Syn is built with the `"derive"` or `"full"`
356    /// feature.*
357    pub enum FloatSuffix #no_visit {
358        F32,
359        F64,
360        None,
361    }
362}
363
364#[cfg(feature = "parsing")]
365pub mod parsing {
366    use super::*;
367    use synom::Synom;
368    use buffer::Cursor;
369    use parse_error;
370    use synom::PResult;
371
372    impl Synom for Lit {
373        fn parse(input: Cursor) -> PResult<Self> {
374            match input.literal() {
375                Some((span, lit, rest)) => {
376                    if lit.to_string().starts_with('/') {
377                        // Doc comment literal which is not a Syn literal
378                        parse_error()
379                    } else {
380                        Ok((Lit::new(lit, span), rest))
381                    }
382                }
383                _ => match input.term() {
384                    Some((span, term, rest)) => Ok((
385                        Lit::Bool(LitBool {
386                            value: if term.as_str() == "true" {
387                                true
388                            } else if term.as_str() == "false" {
389                                false
390                            } else {
391                                return parse_error();
392                            },
393                            span: span,
394                        }),
395                        rest,
396                    )),
397                    _ => parse_error(),
398                },
399            }
400        }
401
402        fn description() -> Option<&'static str> {
403            Some("literal")
404        }
405    }
406
407    impl_synom!(LitStr "string literal" switch!(
408        syn!(Lit),
409        Lit::Str(lit) => value!(lit)
410        |
411        _ => reject!()
412    ));
413
414    impl_synom!(LitByteStr "byte string literal" switch!(
415        syn!(Lit),
416        Lit::ByteStr(lit) => value!(lit)
417        |
418        _ => reject!()
419    ));
420
421    impl_synom!(LitByte "byte literal" switch!(
422        syn!(Lit),
423        Lit::Byte(lit) => value!(lit)
424        |
425        _ => reject!()
426    ));
427
428    impl_synom!(LitChar "character literal" switch!(
429        syn!(Lit),
430        Lit::Char(lit) => value!(lit)
431        |
432        _ => reject!()
433    ));
434
435    impl_synom!(LitInt "integer literal" switch!(
436        syn!(Lit),
437        Lit::Int(lit) => value!(lit)
438        |
439        _ => reject!()
440    ));
441
442    impl_synom!(LitFloat "floating point literal" switch!(
443        syn!(Lit),
444        Lit::Float(lit) => value!(lit)
445        |
446        _ => reject!()
447    ));
448
449    impl_synom!(LitBool "boolean literal" switch!(
450        syn!(Lit),
451        Lit::Bool(lit) => value!(lit)
452        |
453        _ => reject!()
454    ));
455}
456
457#[cfg(feature = "printing")]
458mod printing {
459    use super::*;
460    use quote::{ToTokens, Tokens};
461
462    impl ToTokens for LitStr {
463        fn to_tokens(&self, tokens: &mut Tokens) {
464            tokens.append(TokenTree {
465                span: self.span,
466                kind: TokenNode::Literal(self.token.clone()),
467            });
468        }
469    }
470
471    impl ToTokens for LitByteStr {
472        fn to_tokens(&self, tokens: &mut Tokens) {
473            tokens.append(TokenTree {
474                span: self.span,
475                kind: TokenNode::Literal(self.token.clone()),
476            });
477        }
478    }
479
480    impl ToTokens for LitByte {
481        fn to_tokens(&self, tokens: &mut Tokens) {
482            tokens.append(TokenTree {
483                span: self.span,
484                kind: TokenNode::Literal(self.token.clone()),
485            });
486        }
487    }
488
489    impl ToTokens for LitChar {
490        fn to_tokens(&self, tokens: &mut Tokens) {
491            tokens.append(TokenTree {
492                span: self.span,
493                kind: TokenNode::Literal(self.token.clone()),
494            });
495        }
496    }
497
498    impl ToTokens for LitInt {
499        fn to_tokens(&self, tokens: &mut Tokens) {
500            tokens.append(TokenTree {
501                span: self.span,
502                kind: TokenNode::Literal(self.token.clone()),
503            });
504        }
505    }
506
507    impl ToTokens for LitFloat {
508        fn to_tokens(&self, tokens: &mut Tokens) {
509            tokens.append(TokenTree {
510                span: self.span,
511                kind: TokenNode::Literal(self.token.clone()),
512            });
513        }
514    }
515
516    impl ToTokens for LitBool {
517        fn to_tokens(&self, tokens: &mut Tokens) {
518            tokens.append(TokenTree {
519                span: self.span,
520                kind: TokenNode::Term(Term::intern(if self.value { "true" } else { "false" })),
521            });
522        }
523    }
524
525    impl ToTokens for LitVerbatim {
526        fn to_tokens(&self, tokens: &mut Tokens) {
527            tokens.append(TokenTree {
528                span: self.span,
529                kind: TokenNode::Literal(self.token.clone()),
530            });
531        }
532    }
533}
534
535mod value {
536    use super::*;
537    use std::char;
538    use std::ops::{Index, RangeFrom};
539    use proc_macro2::TokenStream;
540
541    impl Lit {
542        /// Interpret a Syn literal from a proc-macro2 literal.
543        ///
544        /// Not all proc-macro2 literals are valid Syn literals. In particular,
545        /// doc comments are considered by proc-macro2 to be literals but in Syn
546        /// they are [`Attribute`].
547        ///
548        /// [`Attribute`]: struct.Attribute.html
549        ///
550        /// # Panics
551        ///
552        /// Panics if the input is a doc comment literal.
553        pub fn new(token: Literal, span: Span) -> Self {
554            let value = token.to_string();
555
556            match value::byte(&value, 0) {
557                b'"' | b'r' => {
558                    return Lit::Str(LitStr {
559                        token: token,
560                        span: span,
561                    })
562                }
563                b'b' => match value::byte(&value, 1) {
564                    b'"' | b'r' => {
565                        return Lit::ByteStr(LitByteStr {
566                            token: token,
567                            span: span,
568                        })
569                    }
570                    b'\'' => {
571                        return Lit::Byte(LitByte {
572                            token: token,
573                            span: span,
574                        })
575                    }
576                    _ => {}
577                },
578                b'\'' => {
579                    return Lit::Char(LitChar {
580                        token: token,
581                        span: span,
582                    })
583                }
584                b'0'...b'9' => if number_is_int(&value) {
585                    return Lit::Int(LitInt {
586                        token: token,
587                        span: span,
588                    });
589                } else if number_is_float(&value) {
590                    return Lit::Float(LitFloat {
591                        token: token,
592                        span: span,
593                    });
594                } else {
595                    // number overflow
596                    return Lit::Verbatim(LitVerbatim {
597                        token: token,
598                        span: span,
599                    });
600                },
601                _ => if value == "true" || value == "false" {
602                    return Lit::Bool(LitBool {
603                        value: value == "true",
604                        span: span,
605                    });
606                },
607            }
608
609            panic!("Unrecognized literal: {}", value);
610        }
611    }
612
613    fn number_is_int(value: &str) -> bool {
614        if number_is_float(value) {
615            false
616        } else {
617            value::parse_lit_int(value).is_some()
618        }
619    }
620
621    fn number_is_float(value: &str) -> bool {
622        if value.contains('.') {
623            true
624        } else if value.starts_with("0x") || value.ends_with("size") {
625            false
626        } else {
627            value.contains('e') || value.contains('E')
628        }
629    }
630
631    /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
632    /// past the end of the input buffer.
633    pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
634        let s = s.as_ref();
635        if idx < s.len() {
636            s[idx]
637        } else {
638            0
639        }
640    }
641
642    fn next_chr(s: &str) -> char {
643        s.chars().next().unwrap_or('\0')
644    }
645
646    pub fn parse_lit_str(s: &str) -> String {
647        match byte(s, 0) {
648            b'"' => parse_lit_str_cooked(s),
649            b'r' => parse_lit_str_raw(s),
650            _ => unreachable!(),
651        }
652    }
653
654    // Clippy false positive
655    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
656    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
657    fn parse_lit_str_cooked(mut s: &str) -> String {
658        assert_eq!(byte(s, 0), b'"');
659        s = &s[1..];
660
661        let mut out = String::new();
662        'outer: loop {
663            let ch = match byte(s, 0) {
664                b'"' => break,
665                b'\\' => {
666                    let b = byte(s, 1);
667                    s = &s[2..];
668                    match b {
669                        b'x' => {
670                            let (byte, rest) = backslash_x(s);
671                            s = rest;
672                            assert!(byte <= 0x80, "Invalid \\x byte in string literal");
673                            char::from_u32(u32::from(byte)).unwrap()
674                        }
675                        b'u' => {
676                            let (chr, rest) = backslash_u(s);
677                            s = rest;
678                            chr
679                        }
680                        b'n' => '\n',
681                        b'r' => '\r',
682                        b't' => '\t',
683                        b'\\' => '\\',
684                        b'0' => '\0',
685                        b'\'' => '\'',
686                        b'"' => '"',
687                        b'\r' | b'\n' => loop {
688                            let ch = next_chr(s);
689                            if ch.is_whitespace() {
690                                s = &s[ch.len_utf8()..];
691                            } else {
692                                continue 'outer;
693                            }
694                        },
695                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
696                    }
697                }
698                b'\r' => {
699                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
700                    s = &s[2..];
701                    '\n'
702                }
703                _ => {
704                    let ch = next_chr(s);
705                    s = &s[ch.len_utf8()..];
706                    ch
707                }
708            };
709            out.push(ch);
710        }
711
712        assert_eq!(s, "\"");
713        out
714    }
715
716    fn parse_lit_str_raw(mut s: &str) -> String {
717        assert_eq!(byte(s, 0), b'r');
718        s = &s[1..];
719
720        let mut pounds = 0;
721        while byte(s, pounds) == b'#' {
722            pounds += 1;
723        }
724        assert_eq!(byte(s, pounds), b'"');
725        assert_eq!(byte(s, s.len() - pounds - 1), b'"');
726        for end in s[s.len() - pounds..].bytes() {
727            assert_eq!(end, b'#');
728        }
729
730        s[pounds + 1..s.len() - pounds - 1].to_owned()
731    }
732
733    pub fn parse_lit_byte_str(s: &str) -> Vec<u8> {
734        assert_eq!(byte(s, 0), b'b');
735        match byte(s, 1) {
736            b'"' => parse_lit_byte_str_cooked(s),
737            b'r' => parse_lit_byte_str_raw(s),
738            _ => unreachable!(),
739        }
740    }
741
742    // Clippy false positive
743    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
744    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
745    fn parse_lit_byte_str_cooked(mut s: &str) -> Vec<u8> {
746        assert_eq!(byte(s, 0), b'b');
747        assert_eq!(byte(s, 1), b'"');
748        s = &s[2..];
749
750        // We're going to want to have slices which don't respect codepoint boundaries.
751        let mut s = s.as_bytes();
752
753        let mut out = Vec::new();
754        'outer: loop {
755            let byte = match byte(s, 0) {
756                b'"' => break,
757                b'\\' => {
758                    let b = byte(s, 1);
759                    s = &s[2..];
760                    match b {
761                        b'x' => {
762                            let (b, rest) = backslash_x(s);
763                            s = rest;
764                            b
765                        }
766                        b'n' => b'\n',
767                        b'r' => b'\r',
768                        b't' => b'\t',
769                        b'\\' => b'\\',
770                        b'0' => b'\0',
771                        b'\'' => b'\'',
772                        b'"' => b'"',
773                        b'\r' | b'\n' => loop {
774                            let byte = byte(s, 0);
775                            let ch = char::from_u32(u32::from(byte)).unwrap();
776                            if ch.is_whitespace() {
777                                s = &s[1..];
778                            } else {
779                                continue 'outer;
780                            }
781                        },
782                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
783                    }
784                }
785                b'\r' => {
786                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
787                    s = &s[2..];
788                    b'\n'
789                }
790                b => {
791                    s = &s[1..];
792                    b
793                }
794            };
795            out.push(byte);
796        }
797
798        assert_eq!(s, b"\"");
799        out
800    }
801
802    fn parse_lit_byte_str_raw(s: &str) -> Vec<u8> {
803        assert_eq!(byte(s, 0), b'b');
804        parse_lit_str_raw(&s[1..]).into_bytes()
805    }
806
807    pub fn parse_lit_byte(s: &str) -> u8 {
808        assert_eq!(byte(s, 0), b'b');
809        assert_eq!(byte(s, 1), b'\'');
810
811        // We're going to want to have slices which don't respect codepoint boundaries.
812        let mut s = s[2..].as_bytes();
813
814        let b = match byte(s, 0) {
815            b'\\' => {
816                let b = byte(s, 1);
817                s = &s[2..];
818                match b {
819                    b'x' => {
820                        let (b, rest) = backslash_x(s);
821                        s = rest;
822                        b
823                    }
824                    b'n' => b'\n',
825                    b'r' => b'\r',
826                    b't' => b'\t',
827                    b'\\' => b'\\',
828                    b'0' => b'\0',
829                    b'\'' => b'\'',
830                    b'"' => b'"',
831                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
832                }
833            }
834            b => {
835                s = &s[1..];
836                b
837            }
838        };
839
840        assert_eq!(byte(s, 0), b'\'');
841        b
842    }
843
844    pub fn parse_lit_char(mut s: &str) -> char {
845        assert_eq!(byte(s, 0), b'\'');
846        s = &s[1..];
847
848        let ch = match byte(s, 0) {
849            b'\\' => {
850                let b = byte(s, 1);
851                s = &s[2..];
852                match b {
853                    b'x' => {
854                        let (byte, rest) = backslash_x(s);
855                        s = rest;
856                        assert!(byte <= 0x80, "Invalid \\x byte in string literal");
857                        char::from_u32(u32::from(byte)).unwrap()
858                    }
859                    b'u' => {
860                        let (chr, rest) = backslash_u(s);
861                        s = rest;
862                        chr
863                    }
864                    b'n' => '\n',
865                    b'r' => '\r',
866                    b't' => '\t',
867                    b'\\' => '\\',
868                    b'0' => '\0',
869                    b'\'' => '\'',
870                    b'"' => '"',
871                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
872                }
873            }
874            _ => {
875                let ch = next_chr(s);
876                s = &s[ch.len_utf8()..];
877                ch
878            }
879        };
880        assert_eq!(s, "\'", "Expected end of char literal");
881        ch
882    }
883
884    fn backslash_x<S>(s: &S) -> (u8, &S)
885    where
886        S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
887    {
888        let mut ch = 0;
889        let b0 = byte(s, 0);
890        let b1 = byte(s, 1);
891        ch += 0x10 * match b0 {
892            b'0'...b'9' => b0 - b'0',
893            b'a'...b'f' => 10 + (b0 - b'a'),
894            b'A'...b'F' => 10 + (b0 - b'A'),
895            _ => panic!("unexpected non-hex character after \\x"),
896        };
897        ch += match b1 {
898            b'0'...b'9' => b1 - b'0',
899            b'a'...b'f' => 10 + (b1 - b'a'),
900            b'A'...b'F' => 10 + (b1 - b'A'),
901            _ => panic!("unexpected non-hex character after \\x"),
902        };
903        (ch, &s[2..])
904    }
905
906    fn backslash_u(mut s: &str) -> (char, &str) {
907        if byte(s, 0) != b'{' {
908            panic!("expected {{ after \\u");
909        }
910        s = &s[1..];
911
912        let mut ch = 0;
913        for _ in 0..6 {
914            let b = byte(s, 0);
915            match b {
916                b'0'...b'9' => {
917                    ch *= 0x10;
918                    ch += u32::from(b - b'0');
919                    s = &s[1..];
920                }
921                b'a'...b'f' => {
922                    ch *= 0x10;
923                    ch += u32::from(10 + b - b'a');
924                    s = &s[1..];
925                }
926                b'A'...b'F' => {
927                    ch *= 0x10;
928                    ch += u32::from(10 + b - b'A');
929                    s = &s[1..];
930                }
931                b'}' => break,
932                _ => panic!("unexpected non-hex character after \\u"),
933            }
934        }
935        assert!(byte(s, 0) == b'}');
936        s = &s[1..];
937
938        if let Some(ch) = char::from_u32(ch) {
939            (ch, s)
940        } else {
941            panic!("character code {:x} is not a valid unicode character", ch);
942        }
943    }
944
945    pub fn parse_lit_int(mut s: &str) -> Option<u64> {
946        let base = match (byte(s, 0), byte(s, 1)) {
947            (b'0', b'x') => {
948                s = &s[2..];
949                16
950            }
951            (b'0', b'o') => {
952                s = &s[2..];
953                8
954            }
955            (b'0', b'b') => {
956                s = &s[2..];
957                2
958            }
959            (b'0'...b'9', _) => 10,
960            _ => unreachable!(),
961        };
962
963        let mut value = 0u64;
964        loop {
965            let b = byte(s, 0);
966            let digit = match b {
967                b'0'...b'9' => u64::from(b - b'0'),
968                b'a'...b'f' if base > 10 => 10 + u64::from(b - b'a'),
969                b'A'...b'F' if base > 10 => 10 + u64::from(b - b'A'),
970                b'_' => {
971                    s = &s[1..];
972                    continue;
973                }
974                // NOTE: Looking at a floating point literal, we don't want to
975                // consider these integers.
976                b'.' if base == 10 => return None,
977                b'e' | b'E' if base == 10 => return None,
978                _ => break,
979            };
980
981            if digit >= base {
982                panic!("Unexpected digit {:x} out of base range", digit);
983            }
984
985            value = match value.checked_mul(base) {
986                Some(value) => value,
987                None => return None,
988            };
989            value = match value.checked_add(digit) {
990                Some(value) => value,
991                None => return None,
992            };
993            s = &s[1..];
994        }
995
996        Some(value)
997    }
998
999    pub fn parse_lit_float(input: &str) -> f64 {
1000        // Rust's floating point literals are very similar to the ones parsed by
1001        // the standard library, except that rust's literals can contain
1002        // ignorable underscores. Let's remove those underscores.
1003        let mut bytes = input.to_owned().into_bytes();
1004        let mut write = 0;
1005        for read in 0..bytes.len() {
1006            if bytes[read] == b'_' {
1007                continue; // Don't increase write
1008            }
1009            if write != read {
1010                let x = bytes[read];
1011                bytes[write] = x;
1012            }
1013            write += 1;
1014        }
1015        bytes.truncate(write);
1016        let input = String::from_utf8(bytes).unwrap();
1017        let end = input.find('f').unwrap_or_else(|| input.len());
1018        input[..end].parse().unwrap()
1019    }
1020
1021    pub fn to_literal(s: &str) -> Literal {
1022        let stream = s.parse::<TokenStream>().unwrap();
1023        match stream.into_iter().next().unwrap().kind {
1024            TokenNode::Literal(l) => l,
1025            _ => unreachable!(),
1026        }
1027    }
1028}