Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/lit.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
#[cfg(feature = "parsing")]
4
use crate::lookahead;
5
#[cfg(feature = "parsing")]
6
use crate::parse::{Parse, Parser};
7
use crate::{Error, Result};
8
use proc_macro2::{Ident, Literal, Span};
9
#[cfg(feature = "parsing")]
10
use proc_macro2::{TokenStream, TokenTree};
11
use std::ffi::{CStr, CString};
12
use std::fmt::{self, Display};
13
#[cfg(feature = "extra-traits")]
14
use std::hash::{Hash, Hasher};
15
use std::str::{self, FromStr};
16
17
ast_enum_of_structs! {
18
/// A Rust literal such as a string or integer or boolean.
19
///
20
/// # Syntax tree enum
21
///
22
/// This type is a [syntax tree enum].
23
///
24
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
25
#[non_exhaustive]
26
pub enum Lit {
27
/// A UTF-8 string literal: `"foo"`.
28
Str(LitStr),
29
30
/// A byte string literal: `b"foo"`.
31
ByteStr(LitByteStr),
32
33
/// A nul-terminated C-string literal: `c"foo"`.
34
CStr(LitCStr),
35
36
/// A byte literal: `b'f'`.
37
Byte(LitByte),
38
39
/// A character literal: `'a'`.
40
Char(LitChar),
41
42
/// An integer literal: `1` or `1u16`.
43
Int(LitInt),
44
45
/// A floating point literal: `1f64` or `1.0e10f64`.
46
///
47
/// Must be finite. May not be infinite or NaN.
48
Float(LitFloat),
49
50
/// A boolean literal: `true` or `false`.
51
Bool(LitBool),
52
53
/// A raw token literal not interpreted by Syn.
54
Verbatim(Literal),
55
}
56
}
57
58
ast_struct! {
59
/// A UTF-8 string literal: `"foo"`.
60
pub struct LitStr {
61
repr: Box<LitRepr>,
62
}
63
}
64
65
ast_struct! {
66
/// A byte string literal: `b"foo"`.
67
pub struct LitByteStr {
68
repr: Box<LitRepr>,
69
}
70
}
71
72
ast_struct! {
73
/// A nul-terminated C-string literal: `c"foo"`.
74
pub struct LitCStr {
75
repr: Box<LitRepr>,
76
}
77
}
78
79
ast_struct! {
80
/// A byte literal: `b'f'`.
81
pub struct LitByte {
82
repr: Box<LitRepr>,
83
}
84
}
85
86
ast_struct! {
87
/// A character literal: `'a'`.
88
pub struct LitChar {
89
repr: Box<LitRepr>,
90
}
91
}
92
93
struct LitRepr {
94
token: Literal,
95
suffix: Box<str>,
96
}
97
98
ast_struct! {
99
/// An integer literal: `1` or `1u16`.
100
pub struct LitInt {
101
repr: Box<LitIntRepr>,
102
}
103
}
104
105
struct LitIntRepr {
106
token: Literal,
107
digits: Box<str>,
108
suffix: Box<str>,
109
}
110
111
ast_struct! {
112
/// A floating point literal: `1f64` or `1.0e10f64`.
113
///
114
/// Must be finite. May not be infinite or NaN.
115
pub struct LitFloat {
116
repr: Box<LitFloatRepr>,
117
}
118
}
119
120
struct LitFloatRepr {
121
token: Literal,
122
digits: Box<str>,
123
suffix: Box<str>,
124
}
125
126
ast_struct! {
127
/// A boolean literal: `true` or `false`.
128
pub struct LitBool {
129
pub value: bool,
130
pub span: Span,
131
}
132
}
133
134
impl LitStr {
135
pub fn new(value: &str, span: Span) -> Self {
136
let mut token = Literal::string(value);
137
token.set_span(span);
138
LitStr {
139
repr: Box::new(LitRepr {
140
token,
141
suffix: Box::<str>::default(),
142
}),
143
}
144
}
145
146
pub fn value(&self) -> String {
147
let repr = self.repr.token.to_string();
148
let (value, _suffix) = value::parse_lit_str(&repr);
149
String::from(value)
150
}
151
152
/// Parse a syntax tree node from the content of this string literal.
153
///
154
/// All spans in the syntax tree will point to the span of this `LitStr`.
155
///
156
/// # Example
157
///
158
/// ```
159
/// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result};
160
///
161
/// // Parses the path from an attribute that looks like:
162
/// //
163
/// // #[path = "a::b::c"]
164
/// //
165
/// // or returns `None` if the input is some other attribute.
166
/// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
167
/// if !attr.path().is_ident("path") {
168
/// return Ok(None);
169
/// }
170
///
171
/// if let Meta::NameValue(meta) = &attr.meta {
172
/// if let Expr::Lit(expr) = &meta.value {
173
/// if let Lit::Str(lit_str) = &expr.lit {
174
/// return lit_str.parse().map(Some);
175
/// }
176
/// }
177
/// }
178
///
179
/// let message = "expected #[path = \"...\"]";
180
/// Err(Error::new_spanned(attr, message))
181
/// }
182
/// ```
183
#[cfg(feature = "parsing")]
184
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
185
pub fn parse<T: Parse>(&self) -> Result<T> {
186
self.parse_with(T::parse)
187
}
188
189
/// Invoke parser on the content of this string literal.
190
///
191
/// All spans in the syntax tree will point to the span of this `LitStr`.
192
///
193
/// # Example
194
///
195
/// ```
196
/// # use proc_macro2::Span;
197
/// # use syn::{LitStr, Result};
198
/// #
199
/// # fn main() -> Result<()> {
200
/// # let lit_str = LitStr::new("a::b::c", Span::call_site());
201
/// #
202
/// # const IGNORE: &str = stringify! {
203
/// let lit_str: LitStr = /* ... */;
204
/// # };
205
///
206
/// // Parse a string literal like "a::b::c" into a Path, not allowing
207
/// // generic arguments on any of the path segments.
208
/// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
209
/// #
210
/// # Ok(())
211
/// # }
212
/// ```
213
#[cfg(feature = "parsing")]
214
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
215
pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
216
use proc_macro2::Group;
217
218
// Token stream with every span replaced by the given one.
219
fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
220
stream
221
.into_iter()
222
.map(|token| respan_token_tree(token, span))
223
.collect()
224
}
225
226
// Token tree with every span replaced by the given one.
227
fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
228
match &mut token {
229
TokenTree::Group(g) => {
230
let stream = respan_token_stream(g.stream(), span);
231
*g = Group::new(g.delimiter(), stream);
232
g.set_span(span);
233
}
234
other => other.set_span(span),
235
}
236
token
237
}
238
239
// Parse string literal into a token stream with every span equal to the
240
// original literal's span.
241
let span = self.span();
242
let mut tokens = TokenStream::from_str(&self.value())?;
243
tokens = respan_token_stream(tokens, span);
244
245
let result = crate::parse::parse_scoped(parser, span, tokens)?;
246
247
let suffix = self.suffix();
248
if !suffix.is_empty() {
249
return Err(Error::new(
250
self.span(),
251
format!("unexpected suffix `{}` on string literal", suffix),
252
));
253
}
254
255
Ok(result)
256
}
257
258
pub fn span(&self) -> Span {
259
self.repr.token.span()
260
}
261
262
pub fn set_span(&mut self, span: Span) {
263
self.repr.token.set_span(span);
264
}
265
266
pub fn suffix(&self) -> &str {
267
&self.repr.suffix
268
}
269
270
pub fn token(&self) -> Literal {
271
self.repr.token.clone()
272
}
273
}
274
275
impl LitByteStr {
276
pub fn new(value: &[u8], span: Span) -> Self {
277
let mut token = Literal::byte_string(value);
278
token.set_span(span);
279
LitByteStr {
280
repr: Box::new(LitRepr {
281
token,
282
suffix: Box::<str>::default(),
283
}),
284
}
285
}
286
287
pub fn value(&self) -> Vec<u8> {
288
let repr = self.repr.token.to_string();
289
let (value, _suffix) = value::parse_lit_byte_str(&repr);
290
value
291
}
292
293
pub fn span(&self) -> Span {
294
self.repr.token.span()
295
}
296
297
pub fn set_span(&mut self, span: Span) {
298
self.repr.token.set_span(span);
299
}
300
301
pub fn suffix(&self) -> &str {
302
&self.repr.suffix
303
}
304
305
pub fn token(&self) -> Literal {
306
self.repr.token.clone()
307
}
308
}
309
310
impl LitCStr {
311
pub fn new(value: &CStr, span: Span) -> Self {
312
let mut token = Literal::c_string(value);
313
token.set_span(span);
314
LitCStr {
315
repr: Box::new(LitRepr {
316
token,
317
suffix: Box::<str>::default(),
318
}),
319
}
320
}
321
322
pub fn value(&self) -> CString {
323
let repr = self.repr.token.to_string();
324
let (value, _suffix) = value::parse_lit_c_str(&repr);
325
value
326
}
327
328
pub fn span(&self) -> Span {
329
self.repr.token.span()
330
}
331
332
pub fn set_span(&mut self, span: Span) {
333
self.repr.token.set_span(span);
334
}
335
336
pub fn suffix(&self) -> &str {
337
&self.repr.suffix
338
}
339
340
pub fn token(&self) -> Literal {
341
self.repr.token.clone()
342
}
343
}
344
345
impl LitByte {
346
pub fn new(value: u8, span: Span) -> Self {
347
let mut token = Literal::u8_suffixed(value);
348
token.set_span(span);
349
LitByte {
350
repr: Box::new(LitRepr {
351
token,
352
suffix: Box::<str>::default(),
353
}),
354
}
355
}
356
357
pub fn value(&self) -> u8 {
358
let repr = self.repr.token.to_string();
359
let (value, _suffix) = value::parse_lit_byte(&repr);
360
value
361
}
362
363
pub fn span(&self) -> Span {
364
self.repr.token.span()
365
}
366
367
pub fn set_span(&mut self, span: Span) {
368
self.repr.token.set_span(span);
369
}
370
371
pub fn suffix(&self) -> &str {
372
&self.repr.suffix
373
}
374
375
pub fn token(&self) -> Literal {
376
self.repr.token.clone()
377
}
378
}
379
380
impl LitChar {
381
pub fn new(value: char, span: Span) -> Self {
382
let mut token = Literal::character(value);
383
token.set_span(span);
384
LitChar {
385
repr: Box::new(LitRepr {
386
token,
387
suffix: Box::<str>::default(),
388
}),
389
}
390
}
391
392
pub fn value(&self) -> char {
393
let repr = self.repr.token.to_string();
394
let (value, _suffix) = value::parse_lit_char(&repr);
395
value
396
}
397
398
pub fn span(&self) -> Span {
399
self.repr.token.span()
400
}
401
402
pub fn set_span(&mut self, span: Span) {
403
self.repr.token.set_span(span);
404
}
405
406
pub fn suffix(&self) -> &str {
407
&self.repr.suffix
408
}
409
410
pub fn token(&self) -> Literal {
411
self.repr.token.clone()
412
}
413
}
414
415
impl LitInt {
416
pub fn new(repr: &str, span: Span) -> Self {
417
let (digits, suffix) = match value::parse_lit_int(repr) {
418
Some(parse) => parse,
419
None => panic!("not an integer literal: `{}`", repr),
420
};
421
422
let mut token: Literal = repr.parse().unwrap();
423
token.set_span(span);
424
LitInt {
425
repr: Box::new(LitIntRepr {
426
token,
427
digits,
428
suffix,
429
}),
430
}
431
}
432
433
pub fn base10_digits(&self) -> &str {
434
&self.repr.digits
435
}
436
437
/// Parses the literal into a selected number type.
438
///
439
/// This is equivalent to `lit.base10_digits().parse()` except that the
440
/// resulting errors will be correctly spanned to point to the literal token
441
/// in the macro input.
442
///
443
/// ```
444
/// use syn::LitInt;
445
/// use syn::parse::{Parse, ParseStream, Result};
446
///
447
/// struct Port {
448
/// value: u16,
449
/// }
450
///
451
/// impl Parse for Port {
452
/// fn parse(input: ParseStream) -> Result<Self> {
453
/// let lit: LitInt = input.parse()?;
454
/// let value = lit.base10_parse::<u16>()?;
455
/// Ok(Port { value })
456
/// }
457
/// }
458
/// ```
459
pub fn base10_parse<N>(&self) -> Result<N>
460
where
461
N: FromStr,
462
N::Err: Display,
463
{
464
self.base10_digits()
465
.parse()
466
.map_err(|err| Error::new(self.span(), err))
467
}
468
469
pub fn suffix(&self) -> &str {
470
&self.repr.suffix
471
}
472
473
pub fn span(&self) -> Span {
474
self.repr.token.span()
475
}
476
477
pub fn set_span(&mut self, span: Span) {
478
self.repr.token.set_span(span);
479
}
480
481
pub fn token(&self) -> Literal {
482
self.repr.token.clone()
483
}
484
}
485
486
impl From<Literal> for LitInt {
487
fn from(token: Literal) -> Self {
488
let repr = token.to_string();
489
if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
490
LitInt {
491
repr: Box::new(LitIntRepr {
492
token,
493
digits,
494
suffix,
495
}),
496
}
497
} else {
498
panic!("not an integer literal: `{}`", repr);
499
}
500
}
501
}
502
503
impl Display for LitInt {
504
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
505
self.repr.token.fmt(formatter)
506
}
507
}
508
509
impl LitFloat {
510
pub fn new(repr: &str, span: Span) -> Self {
511
let (digits, suffix) = match value::parse_lit_float(repr) {
512
Some(parse) => parse,
513
None => panic!("not a float literal: `{}`", repr),
514
};
515
516
let mut token: Literal = repr.parse().unwrap();
517
token.set_span(span);
518
LitFloat {
519
repr: Box::new(LitFloatRepr {
520
token,
521
digits,
522
suffix,
523
}),
524
}
525
}
526
527
pub fn base10_digits(&self) -> &str {
528
&self.repr.digits
529
}
530
531
pub fn base10_parse<N>(&self) -> Result<N>
532
where
533
N: FromStr,
534
N::Err: Display,
535
{
536
self.base10_digits()
537
.parse()
538
.map_err(|err| Error::new(self.span(), err))
539
}
540
541
pub fn suffix(&self) -> &str {
542
&self.repr.suffix
543
}
544
545
pub fn span(&self) -> Span {
546
self.repr.token.span()
547
}
548
549
pub fn set_span(&mut self, span: Span) {
550
self.repr.token.set_span(span);
551
}
552
553
pub fn token(&self) -> Literal {
554
self.repr.token.clone()
555
}
556
}
557
558
impl From<Literal> for LitFloat {
559
fn from(token: Literal) -> Self {
560
let repr = token.to_string();
561
if let Some((digits, suffix)) = value::parse_lit_float(&repr) {
562
LitFloat {
563
repr: Box::new(LitFloatRepr {
564
token,
565
digits,
566
suffix,
567
}),
568
}
569
} else {
570
panic!("not a float literal: `{}`", repr);
571
}
572
}
573
}
574
575
impl Display for LitFloat {
576
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
577
self.repr.token.fmt(formatter)
578
}
579
}
580
581
impl LitBool {
582
pub fn new(value: bool, span: Span) -> Self {
583
LitBool { value, span }
584
}
585
586
pub fn value(&self) -> bool {
587
self.value
588
}
589
590
pub fn span(&self) -> Span {
591
self.span
592
}
593
594
pub fn set_span(&mut self, span: Span) {
595
self.span = span;
596
}
597
598
pub fn token(&self) -> Ident {
599
let s = if self.value { "true" } else { "false" };
600
Ident::new(s, self.span)
601
}
602
}
603
604
#[cfg(feature = "extra-traits")]
605
mod debug_impls {
606
use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
607
use std::fmt::{self, Debug};
608
609
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
610
impl Debug for LitStr {
611
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
612
self.debug(formatter, "LitStr")
613
}
614
}
615
616
impl LitStr {
617
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
618
formatter
619
.debug_struct(name)
620
.field("token", &format_args!("{}", self.repr.token))
621
.finish()
622
}
623
}
624
625
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
626
impl Debug for LitByteStr {
627
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
628
self.debug(formatter, "LitByteStr")
629
}
630
}
631
632
impl LitByteStr {
633
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
634
formatter
635
.debug_struct(name)
636
.field("token", &format_args!("{}", self.repr.token))
637
.finish()
638
}
639
}
640
641
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
642
impl Debug for LitCStr {
643
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
644
self.debug(formatter, "LitCStr")
645
}
646
}
647
648
impl LitCStr {
649
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
650
formatter
651
.debug_struct(name)
652
.field("token", &format_args!("{}", self.repr.token))
653
.finish()
654
}
655
}
656
657
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
658
impl Debug for LitByte {
659
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
660
self.debug(formatter, "LitByte")
661
}
662
}
663
664
impl LitByte {
665
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
666
formatter
667
.debug_struct(name)
668
.field("token", &format_args!("{}", self.repr.token))
669
.finish()
670
}
671
}
672
673
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
674
impl Debug for LitChar {
675
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
676
self.debug(formatter, "LitChar")
677
}
678
}
679
680
impl LitChar {
681
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
682
formatter
683
.debug_struct(name)
684
.field("token", &format_args!("{}", self.repr.token))
685
.finish()
686
}
687
}
688
689
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
690
impl Debug for LitInt {
691
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
692
self.debug(formatter, "LitInt")
693
}
694
}
695
696
impl LitInt {
697
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
698
formatter
699
.debug_struct(name)
700
.field("token", &format_args!("{}", self.repr.token))
701
.finish()
702
}
703
}
704
705
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
706
impl Debug for LitFloat {
707
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
708
self.debug(formatter, "LitFloat")
709
}
710
}
711
712
impl LitFloat {
713
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
714
formatter
715
.debug_struct(name)
716
.field("token", &format_args!("{}", self.repr.token))
717
.finish()
718
}
719
}
720
721
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
722
impl Debug for LitBool {
723
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
724
self.debug(formatter, "LitBool")
725
}
726
}
727
728
impl LitBool {
729
pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
730
formatter
731
.debug_struct(name)
732
.field("value", &self.value)
733
.finish()
734
}
735
}
736
}
737
738
#[cfg(feature = "clone-impls")]
739
#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
740
impl Clone for LitRepr {
741
fn clone(&self) -> Self {
742
LitRepr {
743
token: self.token.clone(),
744
suffix: self.suffix.clone(),
745
}
746
}
747
}
748
749
#[cfg(feature = "clone-impls")]
750
#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
751
impl Clone for LitIntRepr {
752
fn clone(&self) -> Self {
753
LitIntRepr {
754
token: self.token.clone(),
755
digits: self.digits.clone(),
756
suffix: self.suffix.clone(),
757
}
758
}
759
}
760
761
#[cfg(feature = "clone-impls")]
762
#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
763
impl Clone for LitFloatRepr {
764
fn clone(&self) -> Self {
765
LitFloatRepr {
766
token: self.token.clone(),
767
digits: self.digits.clone(),
768
suffix: self.suffix.clone(),
769
}
770
}
771
}
772
773
macro_rules! lit_extra_traits {
774
($ty:ident) => {
775
#[cfg(feature = "clone-impls")]
776
#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
777
impl Clone for $ty {
778
fn clone(&self) -> Self {
779
$ty {
780
repr: self.repr.clone(),
781
}
782
}
783
}
784
785
#[cfg(feature = "extra-traits")]
786
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
787
impl PartialEq for $ty {
788
fn eq(&self, other: &Self) -> bool {
789
self.repr.token.to_string() == other.repr.token.to_string()
790
}
791
}
792
793
#[cfg(feature = "extra-traits")]
794
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
795
impl Hash for $ty {
796
fn hash<H>(&self, state: &mut H)
797
where
798
H: Hasher,
799
{
800
self.repr.token.to_string().hash(state);
801
}
802
}
803
804
#[cfg(feature = "parsing")]
805
pub_if_not_doc! {
806
#[doc(hidden)]
807
#[allow(non_snake_case)]
808
pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
809
match marker {}
810
}
811
}
812
};
813
}
814
815
lit_extra_traits!(LitStr);
816
lit_extra_traits!(LitByteStr);
817
lit_extra_traits!(LitCStr);
818
lit_extra_traits!(LitByte);
819
lit_extra_traits!(LitChar);
820
lit_extra_traits!(LitInt);
821
lit_extra_traits!(LitFloat);
822
823
#[cfg(feature = "parsing")]
824
pub_if_not_doc! {
825
#[doc(hidden)]
826
#[allow(non_snake_case)]
827
pub fn LitBool(marker: lookahead::TokenMarker) -> LitBool {
828
match marker {}
829
}
830
}
831
832
/// The style of a string literal, either plain quoted or a raw string like
833
/// `r##"data"##`.
834
#[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566
835
pub enum StrStyle {
836
/// An ordinary string like `"data"`.
837
Cooked,
838
/// A raw string like `r##"data"##`.
839
///
840
/// The unsigned integer is the number of `#` symbols used.
841
Raw(usize),
842
}
843
844
#[cfg(feature = "parsing")]
845
pub_if_not_doc! {
846
#[doc(hidden)]
847
#[allow(non_snake_case)]
848
pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
849
match marker {}
850
}
851
}
852
853
#[cfg(feature = "parsing")]
854
pub(crate) mod parsing {
855
use crate::buffer::Cursor;
856
use crate::error::Result;
857
use crate::lit::{
858
value, Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
859
LitIntRepr, LitStr,
860
};
861
use crate::parse::{Parse, ParseStream, Unexpected};
862
use crate::token::{self, Token};
863
use proc_macro2::{Literal, Punct, Span};
864
use std::cell::Cell;
865
use std::rc::Rc;
866
867
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
868
impl Parse for Lit {
869
fn parse(input: ParseStream) -> Result<Self> {
870
input.step(|cursor| {
871
if let Some((lit, rest)) = cursor.literal() {
872
return Ok((Lit::new(lit), rest));
873
}
874
875
if let Some((ident, rest)) = cursor.ident() {
876
let value = ident == "true";
877
if value || ident == "false" {
878
let lit_bool = LitBool {
879
value,
880
span: ident.span(),
881
};
882
return Ok((Lit::Bool(lit_bool), rest));
883
}
884
}
885
886
if let Some((punct, rest)) = cursor.punct() {
887
if punct.as_char() == '-' {
888
if let Some((lit, rest)) = parse_negative_lit(punct, rest) {
889
return Ok((lit, rest));
890
}
891
}
892
}
893
894
Err(cursor.error("expected literal"))
895
})
896
}
897
}
898
899
fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> {
900
let (lit, rest) = cursor.literal()?;
901
902
let mut span = neg.span();
903
span = span.join(lit.span()).unwrap_or(span);
904
905
let mut repr = lit.to_string();
906
repr.insert(0, '-');
907
908
if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
909
let mut token: Literal = repr.parse().unwrap();
910
token.set_span(span);
911
return Some((
912
Lit::Int(LitInt {
913
repr: Box::new(LitIntRepr {
914
token,
915
digits,
916
suffix,
917
}),
918
}),
919
rest,
920
));
921
}
922
923
let (digits, suffix) = value::parse_lit_float(&repr)?;
924
let mut token: Literal = repr.parse().unwrap();
925
token.set_span(span);
926
Some((
927
Lit::Float(LitFloat {
928
repr: Box::new(LitFloatRepr {
929
token,
930
digits,
931
suffix,
932
}),
933
}),
934
rest,
935
))
936
}
937
938
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
939
impl Parse for LitStr {
940
fn parse(input: ParseStream) -> Result<Self> {
941
let head = input.fork();
942
match input.parse() {
943
Ok(Lit::Str(lit)) => Ok(lit),
944
_ => Err(head.error("expected string literal")),
945
}
946
}
947
}
948
949
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
950
impl Parse for LitByteStr {
951
fn parse(input: ParseStream) -> Result<Self> {
952
let head = input.fork();
953
match input.parse() {
954
Ok(Lit::ByteStr(lit)) => Ok(lit),
955
_ => Err(head.error("expected byte string literal")),
956
}
957
}
958
}
959
960
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
961
impl Parse for LitCStr {
962
fn parse(input: ParseStream) -> Result<Self> {
963
let head = input.fork();
964
match input.parse() {
965
Ok(Lit::CStr(lit)) => Ok(lit),
966
_ => Err(head.error("expected C string literal")),
967
}
968
}
969
}
970
971
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
972
impl Parse for LitByte {
973
fn parse(input: ParseStream) -> Result<Self> {
974
let head = input.fork();
975
match input.parse() {
976
Ok(Lit::Byte(lit)) => Ok(lit),
977
_ => Err(head.error("expected byte literal")),
978
}
979
}
980
}
981
982
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
983
impl Parse for LitChar {
984
fn parse(input: ParseStream) -> Result<Self> {
985
let head = input.fork();
986
match input.parse() {
987
Ok(Lit::Char(lit)) => Ok(lit),
988
_ => Err(head.error("expected character literal")),
989
}
990
}
991
}
992
993
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
994
impl Parse for LitInt {
995
fn parse(input: ParseStream) -> Result<Self> {
996
let head = input.fork();
997
match input.parse() {
998
Ok(Lit::Int(lit)) => Ok(lit),
999
_ => Err(head.error("expected integer literal")),
1000
}
1001
}
1002
}
1003
1004
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1005
impl Parse for LitFloat {
1006
fn parse(input: ParseStream) -> Result<Self> {
1007
let head = input.fork();
1008
match input.parse() {
1009
Ok(Lit::Float(lit)) => Ok(lit),
1010
_ => Err(head.error("expected floating point literal")),
1011
}
1012
}
1013
}
1014
1015
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1016
impl Parse for LitBool {
1017
fn parse(input: ParseStream) -> Result<Self> {
1018
let head = input.fork();
1019
match input.parse() {
1020
Ok(Lit::Bool(lit)) => Ok(lit),
1021
_ => Err(head.error("expected boolean literal")),
1022
}
1023
}
1024
}
1025
1026
fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
1027
let scope = Span::call_site();
1028
let unexpected = Rc::new(Cell::new(Unexpected::None));
1029
let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected);
1030
peek(&buffer)
1031
}
1032
1033
macro_rules! impl_token {
1034
($display:literal $name:ty) => {
1035
impl Token for $name {
1036
fn peek(cursor: Cursor) -> bool {
1037
fn peek(input: ParseStream) -> bool {
1038
<$name as Parse>::parse(input).is_ok()
1039
}
1040
peek_impl(cursor, peek)
1041
}
1042
1043
fn display() -> &'static str {
1044
$display
1045
}
1046
}
1047
1048
impl token::private::Sealed for $name {}
1049
};
1050
}
1051
1052
impl_token!("literal" Lit);
1053
impl_token!("string literal" LitStr);
1054
impl_token!("byte string literal" LitByteStr);
1055
impl_token!("C-string literal" LitCStr);
1056
impl_token!("byte literal" LitByte);
1057
impl_token!("character literal" LitChar);
1058
impl_token!("integer literal" LitInt);
1059
impl_token!("floating point literal" LitFloat);
1060
impl_token!("boolean literal" LitBool);
1061
}
1062
1063
#[cfg(feature = "printing")]
1064
mod printing {
1065
use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
1066
use proc_macro2::TokenStream;
1067
use quote::{ToTokens, TokenStreamExt};
1068
1069
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1070
impl ToTokens for LitStr {
1071
fn to_tokens(&self, tokens: &mut TokenStream) {
1072
self.repr.token.to_tokens(tokens);
1073
}
1074
}
1075
1076
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1077
impl ToTokens for LitByteStr {
1078
fn to_tokens(&self, tokens: &mut TokenStream) {
1079
self.repr.token.to_tokens(tokens);
1080
}
1081
}
1082
1083
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1084
impl ToTokens for LitCStr {
1085
fn to_tokens(&self, tokens: &mut TokenStream) {
1086
self.repr.token.to_tokens(tokens);
1087
}
1088
}
1089
1090
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1091
impl ToTokens for LitByte {
1092
fn to_tokens(&self, tokens: &mut TokenStream) {
1093
self.repr.token.to_tokens(tokens);
1094
}
1095
}
1096
1097
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1098
impl ToTokens for LitChar {
1099
fn to_tokens(&self, tokens: &mut TokenStream) {
1100
self.repr.token.to_tokens(tokens);
1101
}
1102
}
1103
1104
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1105
impl ToTokens for LitInt {
1106
fn to_tokens(&self, tokens: &mut TokenStream) {
1107
self.repr.token.to_tokens(tokens);
1108
}
1109
}
1110
1111
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1112
impl ToTokens for LitFloat {
1113
fn to_tokens(&self, tokens: &mut TokenStream) {
1114
self.repr.token.to_tokens(tokens);
1115
}
1116
}
1117
1118
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1119
impl ToTokens for LitBool {
1120
fn to_tokens(&self, tokens: &mut TokenStream) {
1121
tokens.append(self.token());
1122
}
1123
}
1124
}
1125
1126
mod value {
1127
use crate::bigint::BigInt;
1128
use crate::lit::{
1129
Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
1130
LitIntRepr, LitRepr, LitStr,
1131
};
1132
use proc_macro2::{Literal, Span};
1133
use std::ascii;
1134
use std::char;
1135
use std::ffi::CString;
1136
use std::ops::{Index, RangeFrom};
1137
1138
impl Lit {
1139
/// Interpret a Syn literal from a proc-macro2 literal.
1140
pub fn new(token: Literal) -> Self {
1141
let repr = token.to_string();
1142
1143
match byte(&repr, 0) {
1144
// "...", r"...", r#"..."#
1145
b'"' | b'r' => {
1146
let (_, suffix) = parse_lit_str(&repr);
1147
return Lit::Str(LitStr {
1148
repr: Box::new(LitRepr { token, suffix }),
1149
});
1150
}
1151
b'b' => match byte(&repr, 1) {
1152
// b"...", br"...", br#"...#"
1153
b'"' | b'r' => {
1154
let (_, suffix) = parse_lit_byte_str(&repr);
1155
return Lit::ByteStr(LitByteStr {
1156
repr: Box::new(LitRepr { token, suffix }),
1157
});
1158
}
1159
// b'...'
1160
b'\'' => {
1161
let (_, suffix) = parse_lit_byte(&repr);
1162
return Lit::Byte(LitByte {
1163
repr: Box::new(LitRepr { token, suffix }),
1164
});
1165
}
1166
_ => {}
1167
},
1168
// c"...", cr"...", cr#"..."#
1169
b'c' => {
1170
let (_, suffix) = parse_lit_c_str(&repr);
1171
return Lit::CStr(LitCStr {
1172
repr: Box::new(LitRepr { token, suffix }),
1173
});
1174
}
1175
// '...'
1176
b'\'' => {
1177
let (_, suffix) = parse_lit_char(&repr);
1178
return Lit::Char(LitChar {
1179
repr: Box::new(LitRepr { token, suffix }),
1180
});
1181
}
1182
b'0'..=b'9' | b'-' => {
1183
// 0, 123, 0xFF, 0o77, 0b11
1184
if let Some((digits, suffix)) = parse_lit_int(&repr) {
1185
return Lit::Int(LitInt {
1186
repr: Box::new(LitIntRepr {
1187
token,
1188
digits,
1189
suffix,
1190
}),
1191
});
1192
}
1193
// 1.0, 1e-1, 1e+1
1194
if let Some((digits, suffix)) = parse_lit_float(&repr) {
1195
return Lit::Float(LitFloat {
1196
repr: Box::new(LitFloatRepr {
1197
token,
1198
digits,
1199
suffix,
1200
}),
1201
});
1202
}
1203
}
1204
// true, false
1205
b't' | b'f' => {
1206
if repr == "true" || repr == "false" {
1207
return Lit::Bool(LitBool {
1208
value: repr == "true",
1209
span: token.span(),
1210
});
1211
}
1212
}
1213
b'(' if repr == "(/*ERROR*/)" => return Lit::Verbatim(token),
1214
_ => {}
1215
}
1216
1217
panic!("unrecognized literal: `{}`", repr);
1218
}
1219
1220
pub fn suffix(&self) -> &str {
1221
match self {
1222
Lit::Str(lit) => lit.suffix(),
1223
Lit::ByteStr(lit) => lit.suffix(),
1224
Lit::CStr(lit) => lit.suffix(),
1225
Lit::Byte(lit) => lit.suffix(),
1226
Lit::Char(lit) => lit.suffix(),
1227
Lit::Int(lit) => lit.suffix(),
1228
Lit::Float(lit) => lit.suffix(),
1229
Lit::Bool(_) | Lit::Verbatim(_) => "",
1230
}
1231
}
1232
1233
pub fn span(&self) -> Span {
1234
match self {
1235
Lit::Str(lit) => lit.span(),
1236
Lit::ByteStr(lit) => lit.span(),
1237
Lit::CStr(lit) => lit.span(),
1238
Lit::Byte(lit) => lit.span(),
1239
Lit::Char(lit) => lit.span(),
1240
Lit::Int(lit) => lit.span(),
1241
Lit::Float(lit) => lit.span(),
1242
Lit::Bool(lit) => lit.span,
1243
Lit::Verbatim(lit) => lit.span(),
1244
}
1245
}
1246
1247
pub fn set_span(&mut self, span: Span) {
1248
match self {
1249
Lit::Str(lit) => lit.set_span(span),
1250
Lit::ByteStr(lit) => lit.set_span(span),
1251
Lit::CStr(lit) => lit.set_span(span),
1252
Lit::Byte(lit) => lit.set_span(span),
1253
Lit::Char(lit) => lit.set_span(span),
1254
Lit::Int(lit) => lit.set_span(span),
1255
Lit::Float(lit) => lit.set_span(span),
1256
Lit::Bool(lit) => lit.span = span,
1257
Lit::Verbatim(lit) => lit.set_span(span),
1258
}
1259
}
1260
}
1261
1262
/// Get the byte at offset idx, or a default of `b'\0'` if we're looking
1263
/// past the end of the input buffer.
1264
pub(crate) fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
1265
let s = s.as_ref();
1266
if idx < s.len() {
1267
s[idx]
1268
} else {
1269
0
1270
}
1271
}
1272
1273
fn next_chr(s: &str) -> char {
1274
s.chars().next().unwrap_or('\0')
1275
}
1276
1277
// Returns (content, suffix).
1278
pub(crate) fn parse_lit_str(s: &str) -> (Box<str>, Box<str>) {
1279
match byte(s, 0) {
1280
b'"' => parse_lit_str_cooked(s),
1281
b'r' => parse_lit_str_raw(s),
1282
_ => unreachable!(),
1283
}
1284
}
1285
1286
fn parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>) {
1287
assert_eq!(byte(s, 0), b'"');
1288
s = &s[1..];
1289
1290
let mut content = String::new();
1291
'outer: loop {
1292
let ch = match byte(s, 0) {
1293
b'"' => break,
1294
b'\\' => {
1295
let b = byte(s, 1);
1296
s = &s[2..];
1297
match b {
1298
b'x' => {
1299
let (byte, rest) = backslash_x(s);
1300
s = rest;
1301
assert!(byte <= 0x7F, "invalid \\x byte in string literal");
1302
char::from_u32(u32::from(byte)).unwrap()
1303
}
1304
b'u' => {
1305
let (ch, rest) = backslash_u(s);
1306
s = rest;
1307
ch
1308
}
1309
b'n' => '\n',
1310
b'r' => '\r',
1311
b't' => '\t',
1312
b'\\' => '\\',
1313
b'0' => '\0',
1314
b'\'' => '\'',
1315
b'"' => '"',
1316
b'\r' | b'\n' => loop {
1317
let b = byte(s, 0);
1318
match b {
1319
b' ' | b'\t' | b'\n' | b'\r' => s = &s[1..],
1320
_ => continue 'outer,
1321
}
1322
},
1323
b => panic!(
1324
"unexpected byte '{}' after \\ character in string literal",
1325
ascii::escape_default(b),
1326
),
1327
}
1328
}
1329
b'\r' => {
1330
assert_eq!(byte(s, 1), b'\n', "bare CR not allowed in string");
1331
s = &s[2..];
1332
'\n'
1333
}
1334
_ => {
1335
let ch = next_chr(s);
1336
s = &s[ch.len_utf8()..];
1337
ch
1338
}
1339
};
1340
content.push(ch);
1341
}
1342
1343
assert!(s.starts_with('"'));
1344
let content = content.into_boxed_str();
1345
let suffix = s[1..].to_owned().into_boxed_str();
1346
(content, suffix)
1347
}
1348
1349
fn parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>) {
1350
assert_eq!(byte(s, 0), b'r');
1351
s = &s[1..];
1352
1353
let mut pounds = 0;
1354
while byte(s, pounds) == b'#' {
1355
pounds += 1;
1356
}
1357
assert_eq!(byte(s, pounds), b'"');
1358
let close = s.rfind('"').unwrap();
1359
for end in s[close + 1..close + 1 + pounds].bytes() {
1360
assert_eq!(end, b'#');
1361
}
1362
1363
let content = s[pounds + 1..close].to_owned().into_boxed_str();
1364
let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str();
1365
(content, suffix)
1366
}
1367
1368
// Returns (content, suffix).
1369
pub(crate) fn parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>) {
1370
assert_eq!(byte(s, 0), b'b');
1371
match byte(s, 1) {
1372
b'"' => parse_lit_byte_str_cooked(s),
1373
b'r' => parse_lit_byte_str_raw(s),
1374
_ => unreachable!(),
1375
}
1376
}
1377
1378
fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>) {
1379
assert_eq!(byte(s, 0), b'b');
1380
assert_eq!(byte(s, 1), b'"');
1381
s = &s[2..];
1382
1383
// We're going to want to have slices which don't respect codepoint boundaries.
1384
let mut v = s.as_bytes();
1385
1386
let mut out = Vec::new();
1387
'outer: loop {
1388
let byte = match byte(v, 0) {
1389
b'"' => break,
1390
b'\\' => {
1391
let b = byte(v, 1);
1392
v = &v[2..];
1393
match b {
1394
b'x' => {
1395
let (b, rest) = backslash_x(v);
1396
v = rest;
1397
b
1398
}
1399
b'n' => b'\n',
1400
b'r' => b'\r',
1401
b't' => b'\t',
1402
b'\\' => b'\\',
1403
b'0' => b'\0',
1404
b'\'' => b'\'',
1405
b'"' => b'"',
1406
b'\r' | b'\n' => loop {
1407
let byte = byte(v, 0);
1408
if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
1409
v = &v[1..];
1410
} else {
1411
continue 'outer;
1412
}
1413
},
1414
b => panic!(
1415
"unexpected byte '{}' after \\ character in byte-string literal",
1416
ascii::escape_default(b),
1417
),
1418
}
1419
}
1420
b'\r' => {
1421
assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string");
1422
v = &v[2..];
1423
b'\n'
1424
}
1425
b => {
1426
v = &v[1..];
1427
b
1428
}
1429
};
1430
out.push(byte);
1431
}
1432
1433
assert_eq!(byte(v, 0), b'"');
1434
let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1435
(out, suffix)
1436
}
1437
1438
fn parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>) {
1439
assert_eq!(byte(s, 0), b'b');
1440
let (value, suffix) = parse_lit_str_raw(&s[1..]);
1441
(String::from(value).into_bytes(), suffix)
1442
}
1443
1444
// Returns (content, suffix).
1445
pub(crate) fn parse_lit_c_str(s: &str) -> (CString, Box<str>) {
1446
assert_eq!(byte(s, 0), b'c');
1447
match byte(s, 1) {
1448
b'"' => parse_lit_c_str_cooked(s),
1449
b'r' => parse_lit_c_str_raw(s),
1450
_ => unreachable!(),
1451
}
1452
}
1453
1454
fn parse_lit_c_str_cooked(mut s: &str) -> (CString, Box<str>) {
1455
assert_eq!(byte(s, 0), b'c');
1456
assert_eq!(byte(s, 1), b'"');
1457
s = &s[2..];
1458
1459
// We're going to want to have slices which don't respect codepoint boundaries.
1460
let mut v = s.as_bytes();
1461
1462
let mut out = Vec::new();
1463
'outer: loop {
1464
let byte = match byte(v, 0) {
1465
b'"' => break,
1466
b'\\' => {
1467
let b = byte(v, 1);
1468
v = &v[2..];
1469
match b {
1470
b'x' => {
1471
let (b, rest) = backslash_x(v);
1472
assert!(b != 0, "\\x00 is not allowed in C-string literal");
1473
v = rest;
1474
b
1475
}
1476
b'u' => {
1477
let (ch, rest) = backslash_u(v);
1478
assert!(ch != '\0', "\\u{{0}} is not allowed in C-string literal");
1479
v = rest;
1480
out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes());
1481
continue 'outer;
1482
}
1483
b'n' => b'\n',
1484
b'r' => b'\r',
1485
b't' => b'\t',
1486
b'\\' => b'\\',
1487
b'\'' => b'\'',
1488
b'"' => b'"',
1489
b'\r' | b'\n' => loop {
1490
let byte = byte(v, 0);
1491
if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
1492
v = &v[1..];
1493
} else {
1494
continue 'outer;
1495
}
1496
},
1497
b => panic!(
1498
"unexpected byte '{}' after \\ character in byte literal",
1499
ascii::escape_default(b),
1500
),
1501
}
1502
}
1503
b'\r' => {
1504
assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string");
1505
v = &v[2..];
1506
b'\n'
1507
}
1508
b => {
1509
v = &v[1..];
1510
b
1511
}
1512
};
1513
out.push(byte);
1514
}
1515
1516
assert_eq!(byte(v, 0), b'"');
1517
let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1518
(CString::new(out).unwrap(), suffix)
1519
}
1520
1521
fn parse_lit_c_str_raw(s: &str) -> (CString, Box<str>) {
1522
assert_eq!(byte(s, 0), b'c');
1523
let (value, suffix) = parse_lit_str_raw(&s[1..]);
1524
(CString::new(String::from(value)).unwrap(), suffix)
1525
}
1526
1527
// Returns (value, suffix).
1528
pub(crate) fn parse_lit_byte(s: &str) -> (u8, Box<str>) {
1529
assert_eq!(byte(s, 0), b'b');
1530
assert_eq!(byte(s, 1), b'\'');
1531
1532
// We're going to want to have slices which don't respect codepoint boundaries.
1533
let mut v = &s.as_bytes()[2..];
1534
1535
let b = match byte(v, 0) {
1536
b'\\' => {
1537
let b = byte(v, 1);
1538
v = &v[2..];
1539
match b {
1540
b'x' => {
1541
let (b, rest) = backslash_x(v);
1542
v = rest;
1543
b
1544
}
1545
b'n' => b'\n',
1546
b'r' => b'\r',
1547
b't' => b'\t',
1548
b'\\' => b'\\',
1549
b'0' => b'\0',
1550
b'\'' => b'\'',
1551
b'"' => b'"',
1552
b => panic!(
1553
"unexpected byte '{}' after \\ character in byte literal",
1554
ascii::escape_default(b),
1555
),
1556
}
1557
}
1558
b => {
1559
v = &v[1..];
1560
b
1561
}
1562
};
1563
1564
assert_eq!(byte(v, 0), b'\'');
1565
let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
1566
(b, suffix)
1567
}
1568
1569
// Returns (value, suffix).
1570
pub(crate) fn parse_lit_char(mut s: &str) -> (char, Box<str>) {
1571
assert_eq!(byte(s, 0), b'\'');
1572
s = &s[1..];
1573
1574
let ch = match byte(s, 0) {
1575
b'\\' => {
1576
let b = byte(s, 1);
1577
s = &s[2..];
1578
match b {
1579
b'x' => {
1580
let (byte, rest) = backslash_x(s);
1581
s = rest;
1582
assert!(byte <= 0x7F, "invalid \\x byte in character literal");
1583
char::from_u32(u32::from(byte)).unwrap()
1584
}
1585
b'u' => {
1586
let (ch, rest) = backslash_u(s);
1587
s = rest;
1588
ch
1589
}
1590
b'n' => '\n',
1591
b'r' => '\r',
1592
b't' => '\t',
1593
b'\\' => '\\',
1594
b'0' => '\0',
1595
b'\'' => '\'',
1596
b'"' => '"',
1597
b => panic!(
1598
"unexpected byte '{}' after \\ character in character literal",
1599
ascii::escape_default(b),
1600
),
1601
}
1602
}
1603
_ => {
1604
let ch = next_chr(s);
1605
s = &s[ch.len_utf8()..];
1606
ch
1607
}
1608
};
1609
assert_eq!(byte(s, 0), b'\'');
1610
let suffix = s[1..].to_owned().into_boxed_str();
1611
(ch, suffix)
1612
}
1613
1614
fn backslash_x<S>(s: &S) -> (u8, &S)
1615
where
1616
S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1617
{
1618
let mut ch = 0;
1619
let b0 = byte(s, 0);
1620
let b1 = byte(s, 1);
1621
ch += 0x10
1622
* match b0 {
1623
b'0'..=b'9' => b0 - b'0',
1624
b'a'..=b'f' => 10 + (b0 - b'a'),
1625
b'A'..=b'F' => 10 + (b0 - b'A'),
1626
_ => panic!("unexpected non-hex character after \\x"),
1627
};
1628
ch += match b1 {
1629
b'0'..=b'9' => b1 - b'0',
1630
b'a'..=b'f' => 10 + (b1 - b'a'),
1631
b'A'..=b'F' => 10 + (b1 - b'A'),
1632
_ => panic!("unexpected non-hex character after \\x"),
1633
};
1634
(ch, &s[2..])
1635
}
1636
1637
fn backslash_u<S>(mut s: &S) -> (char, &S)
1638
where
1639
S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
1640
{
1641
if byte(s, 0) != b'{' {
1642
panic!("{}", "expected { after \\u");
1643
}
1644
s = &s[1..];
1645
1646
let mut ch = 0;
1647
let mut digits = 0;
1648
loop {
1649
let b = byte(s, 0);
1650
let digit = match b {
1651
b'0'..=b'9' => b - b'0',
1652
b'a'..=b'f' => 10 + b - b'a',
1653
b'A'..=b'F' => 10 + b - b'A',
1654
b'_' if digits > 0 => {
1655
s = &s[1..];
1656
continue;
1657
}
1658
b'}' if digits == 0 => panic!("invalid empty unicode escape"),
1659
b'}' => break,
1660
_ => panic!("unexpected non-hex character after \\u"),
1661
};
1662
if digits == 6 {
1663
panic!("overlong unicode escape (must have at most 6 hex digits)");
1664
}
1665
ch *= 0x10;
1666
ch += u32::from(digit);
1667
digits += 1;
1668
s = &s[1..];
1669
}
1670
assert!(byte(s, 0) == b'}');
1671
s = &s[1..];
1672
1673
if let Some(ch) = char::from_u32(ch) {
1674
(ch, s)
1675
} else {
1676
panic!("character code {:x} is not a valid unicode character", ch);
1677
}
1678
}
1679
1680
// Returns base 10 digits and suffix.
1681
pub(crate) fn parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)> {
1682
let negative = byte(s, 0) == b'-';
1683
if negative {
1684
s = &s[1..];
1685
}
1686
1687
let base = match (byte(s, 0), byte(s, 1)) {
1688
(b'0', b'x') => {
1689
s = &s[2..];
1690
16
1691
}
1692
(b'0', b'o') => {
1693
s = &s[2..];
1694
8
1695
}
1696
(b'0', b'b') => {
1697
s = &s[2..];
1698
2
1699
}
1700
(b'0'..=b'9', _) => 10,
1701
_ => return None,
1702
};
1703
1704
let mut value = BigInt::new();
1705
let mut has_digit = false;
1706
'outer: loop {
1707
let b = byte(s, 0);
1708
let digit = match b {
1709
b'0'..=b'9' => b - b'0',
1710
b'a'..=b'f' if base > 10 => b - b'a' + 10,
1711
b'A'..=b'F' if base > 10 => b - b'A' + 10,
1712
b'_' => {
1713
s = &s[1..];
1714
continue;
1715
}
1716
// If looking at a floating point literal, we don't want to
1717
// consider it an integer.
1718
b'.' if base == 10 => return None,
1719
b'e' | b'E' if base == 10 => {
1720
let mut has_exp = false;
1721
for (i, b) in s[1..].bytes().enumerate() {
1722
match b {
1723
b'_' => {}
1724
b'-' | b'+' => return None,
1725
b'0'..=b'9' => has_exp = true,
1726
_ => {
1727
let suffix = &s[1 + i..];
1728
if has_exp && crate::ident::xid_ok(suffix) {
1729
return None;
1730
} else {
1731
break 'outer;
1732
}
1733
}
1734
}
1735
}
1736
if has_exp {
1737
return None;
1738
} else {
1739
break;
1740
}
1741
}
1742
_ => break,
1743
};
1744
1745
if digit >= base {
1746
return None;
1747
}
1748
1749
has_digit = true;
1750
value *= base;
1751
value += digit;
1752
s = &s[1..];
1753
}
1754
1755
if !has_digit {
1756
return None;
1757
}
1758
1759
let suffix = s;
1760
if suffix.is_empty() || crate::ident::xid_ok(suffix) {
1761
let mut repr = value.to_string();
1762
if negative {
1763
repr.insert(0, '-');
1764
}
1765
Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str()))
1766
} else {
1767
None
1768
}
1769
}
1770
1771
// Returns base 10 digits and suffix.
1772
pub(crate) fn parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)> {
1773
// Rust's floating point literals are very similar to the ones parsed by
1774
// the standard library, except that rust's literals can contain
1775
// ignorable underscores. Let's remove those underscores.
1776
1777
let mut bytes = input.to_owned().into_bytes();
1778
1779
let start = (*bytes.first()? == b'-') as usize;
1780
match bytes.get(start)? {
1781
b'0'..=b'9' => {}
1782
_ => return None,
1783
}
1784
1785
let mut read = start;
1786
let mut write = start;
1787
let mut has_dot = false;
1788
let mut has_e = false;
1789
let mut has_sign = false;
1790
let mut has_exponent = false;
1791
while read < bytes.len() {
1792
match bytes[read] {
1793
b'_' => {
1794
// Don't increase write
1795
read += 1;
1796
continue;
1797
}
1798
b'0'..=b'9' => {
1799
if has_e {
1800
has_exponent = true;
1801
}
1802
bytes[write] = bytes[read];
1803
}
1804
b'.' => {
1805
if has_e || has_dot {
1806
return None;
1807
}
1808
has_dot = true;
1809
bytes[write] = b'.';
1810
}
1811
b'e' | b'E' => {
1812
match bytes[read + 1..]
1813
.iter()
1814
.find(|b| **b != b'_')
1815
.unwrap_or(&b'\0')
1816
{
1817
b'-' | b'+' | b'0'..=b'9' => {}
1818
_ => break,
1819
}
1820
if has_e {
1821
if has_exponent {
1822
break;
1823
} else {
1824
return None;
1825
}
1826
}
1827
has_e = true;
1828
bytes[write] = b'e';
1829
}
1830
b'-' | b'+' => {
1831
if has_sign || has_exponent || !has_e {
1832
return None;
1833
}
1834
has_sign = true;
1835
if bytes[read] == b'-' {
1836
bytes[write] = bytes[read];
1837
} else {
1838
// Omit '+'
1839
read += 1;
1840
continue;
1841
}
1842
}
1843
_ => break,
1844
}
1845
read += 1;
1846
write += 1;
1847
}
1848
1849
if has_e && !has_exponent {
1850
return None;
1851
}
1852
1853
let mut digits = String::from_utf8(bytes).unwrap();
1854
let suffix = digits.split_off(read);
1855
digits.truncate(write);
1856
if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
1857
Some((digits.into_boxed_str(), suffix.into_boxed_str()))
1858
} else {
1859
None
1860
}
1861
}
1862
}
1863
1864