2 use std
::cell
::RefCell
;
3 #[cfg(procmacro2_semver_exempt)]
7 #[cfg(procmacro2_semver_exempt)]
9 use std
::path
::PathBuf
;
10 use std
::str::FromStr
;
13 use strnom
::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}
;
14 use unicode_xid
::UnicodeXID
;
16 use {Delimiter, Punct, Spacing, TokenTree}
;
19 pub struct TokenStream
{
20 inner
: Vec
<TokenTree
>,
27 pub fn new() -> TokenStream
{
28 TokenStream { inner: Vec::new() }
31 pub fn is_empty(&self) -> bool
{
36 #[cfg(span_locations)]
37 fn get_cursor(src
: &str) -> Cursor
{
38 // Create a dummy file & add it to the codemap
40 let mut cm
= cm
.borrow_mut();
41 let name
= format
!("<parsed string {}>", cm
.files
.len());
42 let span
= cm
.add_file(&name
, src
);
50 #[cfg(not(span_locations))]
51 fn get_cursor(src
: &str) -> Cursor
{
55 impl FromStr
for TokenStream
{
58 fn from_str(src
: &str) -> Result
<TokenStream
, LexError
> {
59 // Create a dummy file & add it to the codemap
60 let cursor
= get_cursor(src
);
62 match token_stream(cursor
) {
63 Ok((input
, output
)) => {
64 if skip_whitespace(input
).len() != 0 {
70 Err(LexError
) => Err(LexError
),
75 impl fmt
::Display
for TokenStream
{
76 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
77 let mut joint
= false;
78 for (i
, tt
) in self.inner
.iter().enumerate() {
84 TokenTree
::Group(ref tt
) => {
85 let (start
, end
) = match tt
.delimiter() {
86 Delimiter
::Parenthesis
=> ("(", ")"),
87 Delimiter
::Brace
=> ("{", "}"),
88 Delimiter
::Bracket
=> ("[", "]"),
89 Delimiter
::None
=> ("", ""),
91 if tt
.stream().into_iter().next().is_none() {
92 write
!(f
, "{} {}", start
, end
)?
94 write
!(f
, "{} {} {}", start
, tt
.stream(), end
)?
97 TokenTree
::Ident(ref tt
) => write
!(f
, "{}", tt
)?
,
98 TokenTree
::Punct(ref tt
) => {
99 write
!(f
, "{}", tt
.as_char())?
;
102 Spacing
::Joint
=> joint
= true,
105 TokenTree
::Literal(ref tt
) => write
!(f
, "{}", tt
)?
,
113 impl fmt
::Debug
for TokenStream
{
114 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
115 f
.write_str("TokenStream ")?
;
116 f
.debug_list().entries(self.clone()).finish()
120 #[cfg(use_proc_macro)]
121 impl From
<::proc_macro
::TokenStream
> for TokenStream
{
122 fn from(inner
: ::proc_macro
::TokenStream
) -> TokenStream
{
126 .expect("compiler token stream parse failed")
130 #[cfg(use_proc_macro)]
131 impl From
<TokenStream
> for ::proc_macro
::TokenStream
{
132 fn from(inner
: TokenStream
) -> ::proc_macro
::TokenStream
{
136 .expect("failed to parse to compiler tokens")
140 impl From
<TokenTree
> for TokenStream
{
141 fn from(tree
: TokenTree
) -> TokenStream
{
142 TokenStream { inner: vec![tree] }
146 impl iter
::FromIterator
<TokenTree
> for TokenStream
{
147 fn from_iter
<I
: IntoIterator
<Item
= TokenTree
>>(streams
: I
) -> Self {
148 let mut v
= Vec
::new();
150 for token
in streams
.into_iter() {
154 TokenStream { inner: v }
158 impl iter
::FromIterator
<TokenStream
> for TokenStream
{
159 fn from_iter
<I
: IntoIterator
<Item
= TokenStream
>>(streams
: I
) -> Self {
160 let mut v
= Vec
::new();
162 for stream
in streams
.into_iter() {
163 v
.extend(stream
.inner
);
166 TokenStream { inner: v }
170 impl Extend
<TokenTree
> for TokenStream
{
171 fn extend
<I
: IntoIterator
<Item
= TokenTree
>>(&mut self, streams
: I
) {
172 self.inner
.extend(streams
);
176 impl Extend
<TokenStream
> for TokenStream
{
177 fn extend
<I
: IntoIterator
<Item
= TokenStream
>>(&mut self, streams
: I
) {
179 .extend(streams
.into_iter().flat_map(|stream
| stream
));
183 pub type TokenTreeIter
= vec
::IntoIter
<TokenTree
>;
185 impl IntoIterator
for TokenStream
{
186 type Item
= TokenTree
;
187 type IntoIter
= TokenTreeIter
;
189 fn into_iter(self) -> TokenTreeIter
{
190 self.inner
.into_iter()
194 #[derive(Clone, PartialEq, Eq)]
195 pub struct SourceFile
{
200 /// Get the path to this source file as a string.
201 pub fn path(&self) -> PathBuf
{
205 pub fn is_real(&self) -> bool
{
206 // XXX(nika): Support real files in the future?
211 impl fmt
::Debug
for SourceFile
{
212 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
213 f
.debug_struct("SourceFile")
214 .field("path", &self.path())
215 .field("is_real", &self.is_real())
220 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
221 pub struct LineColumn
{
226 #[cfg(span_locations)]
228 static CODEMAP
: RefCell
<Codemap
> = RefCell
::new(Codemap
{
229 // NOTE: We start with a single dummy file which all call_site() and
230 // def_site() spans reference.
232 #[cfg(procmacro2_semver_exempt)]
235 name
: "<unspecified>".to_owned(),
236 span
: Span { lo: 0, hi: 0 }
,
241 #[cfg(not(procmacro2_semver_exempt))]
244 span
: Span { lo: 0, hi: 0 }
,
252 #[cfg(span_locations)]
254 #[cfg(procmacro2_semver_exempt)]
260 #[cfg(span_locations)]
262 fn offset_line_column(&self, offset
: usize) -> LineColumn
{
263 assert
!(self.span_within(Span
{
267 let offset
= offset
- self.span
.lo
as usize;
268 match self.lines
.binary_search(&offset
) {
269 Ok(found
) => LineColumn
{
273 Err(idx
) => LineColumn
{
275 column
: offset
- self.lines
[idx
- 1],
280 fn span_within(&self, span
: Span
) -> bool
{
281 span
.lo
>= self.span
.lo
&& span
.hi
<= self.span
.hi
285 /// Computesthe offsets of each line in the given source string.
286 #[cfg(span_locations)]
287 fn lines_offsets(s
: &str) -> Vec
<usize> {
288 let mut lines
= vec
![0];
290 while let Some(len
) = s
[prev
..].find('
\n'
) {
297 #[cfg(span_locations)]
299 files
: Vec
<FileInfo
>,
302 #[cfg(span_locations)]
304 fn next_start_pos(&self) -> u32 {
305 // Add 1 so there's always space between files.
307 // We'll always have at least 1 file, as we initialize our files list
308 // with a dummy file.
309 self.files
.last().unwrap().span
.hi
+ 1
312 fn add_file(&mut self, name
: &str, src
: &str) -> Span
{
313 let lines
= lines_offsets(src
);
314 let lo
= self.next_start_pos();
315 // XXX(nika): Shouild we bother doing a checked cast or checked add here?
318 hi
: lo
+ (src
.len() as u32),
321 #[cfg(procmacro2_semver_exempt)]
322 self.files
.push(FileInfo
{
323 name
: name
.to_owned(),
328 #[cfg(not(procmacro2_semver_exempt))]
329 self.files
.push(FileInfo
{
338 fn fileinfo(&self, span
: Span
) -> &FileInfo
{
339 for file
in &self.files
{
340 if file
.span_within(span
) {
344 panic
!("Invalid span with no related FileInfo!");
348 #[derive(Clone, Copy, PartialEq, Eq)]
350 #[cfg(span_locations)]
352 #[cfg(span_locations)]
357 #[cfg(not(span_locations))]
358 pub fn call_site() -> Span
{
362 #[cfg(span_locations)]
363 pub fn call_site() -> Span
{
364 Span { lo: 0, hi: 0 }
367 #[cfg(procmacro2_semver_exempt)]
368 pub fn def_site() -> Span
{
372 #[cfg(procmacro2_semver_exempt)]
373 pub fn resolved_at(&self, _other
: Span
) -> Span
{
374 // Stable spans consist only of line/column information, so
375 // `resolved_at` and `located_at` only select which span the
376 // caller wants line/column information from.
380 #[cfg(procmacro2_semver_exempt)]
381 pub fn located_at(&self, other
: Span
) -> Span
{
385 #[cfg(procmacro2_semver_exempt)]
386 pub fn source_file(&self) -> SourceFile
{
388 let cm
= cm
.borrow();
389 let fi
= cm
.fileinfo(*self);
391 path
: Path
::new(&fi
.name
).to_owned(),
396 #[cfg(span_locations)]
397 pub fn start(&self) -> LineColumn
{
399 let cm
= cm
.borrow();
400 let fi
= cm
.fileinfo(*self);
401 fi
.offset_line_column(self.lo
as usize)
405 #[cfg(span_locations)]
406 pub fn end(&self) -> LineColumn
{
408 let cm
= cm
.borrow();
409 let fi
= cm
.fileinfo(*self);
410 fi
.offset_line_column(self.hi
as usize)
414 #[cfg(procmacro2_semver_exempt)]
415 pub fn join(&self, other
: Span
) -> Option
<Span
> {
417 let cm
= cm
.borrow();
418 // If `other` is not within the same FileInfo as us, return None.
419 if !cm
.fileinfo(*self).span_within(other
) {
423 lo
: cmp
::min(self.lo
, other
.lo
),
424 hi
: cmp
::max(self.hi
, other
.hi
),
430 impl fmt
::Debug
for Span
{
431 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
432 #[cfg(procmacro2_semver_exempt)]
433 return write
!(f
, "bytes({}..{})", self.lo
, self.hi
);
435 #[cfg(not(procmacro2_semver_exempt))]
440 pub fn debug_span_field_if_nontrivial(debug
: &mut fmt
::DebugStruct
, span
: Span
) {
441 if cfg
!(procmacro2_semver_exempt
) {
442 debug
.field("span", &span
);
448 delimiter
: Delimiter
,
454 pub fn new(delimiter
: Delimiter
, stream
: TokenStream
) -> Group
{
456 delimiter
: delimiter
,
458 span
: Span
::call_site(),
462 pub fn delimiter(&self) -> Delimiter
{
466 pub fn stream(&self) -> TokenStream
{
470 pub fn span(&self) -> Span
{
474 #[cfg(procmacro2_semver_exempt)]
475 pub fn span_open(&self) -> Span
{
479 #[cfg(procmacro2_semver_exempt)]
480 pub fn span_close(&self) -> Span
{
484 pub fn set_span(&mut self, span
: Span
) {
489 impl fmt
::Display
for Group
{
490 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
491 let (left
, right
) = match self.delimiter
{
492 Delimiter
::Parenthesis
=> ("(", ")"),
493 Delimiter
::Brace
=> ("{", "}"),
494 Delimiter
::Bracket
=> ("[", "]"),
495 Delimiter
::None
=> ("", ""),
506 impl fmt
::Debug
for Group
{
507 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
508 let mut debug
= fmt
.debug_struct("Group");
509 debug
.field("delimiter", &self.delimiter
);
510 debug
.field("stream", &self.stream
);
511 #[cfg(procmacro2_semver_exempt)]
512 debug
.field("span", &self.span
);
525 fn _new(string
: &str, raw
: bool
, span
: Span
) -> Ident
{
526 validate_term(string
);
529 sym
: string
.to_owned(),
535 pub fn new(string
: &str, span
: Span
) -> Ident
{
536 Ident
::_new(string
, false, span
)
539 pub fn new_raw(string
: &str, span
: Span
) -> Ident
{
540 Ident
::_new(string
, true, span
)
543 pub fn span(&self) -> Span
{
547 pub fn set_span(&mut self, span
: Span
) {
553 fn is_ident_start(c
: char) -> bool
{
554 ('a'
<= c
&& c
<= 'z'
)
555 || ('A'
<= c
&& c
<= 'Z'
)
557 || (c
> '
\x7f'
&& UnicodeXID
::is_xid_start(c
))
561 fn is_ident_continue(c
: char) -> bool
{
562 ('a'
<= c
&& c
<= 'z'
)
563 || ('A'
<= c
&& c
<= 'Z'
)
565 || ('
0'
<= c
&& c
<= '
9'
)
566 || (c
> '
\x7f'
&& UnicodeXID
::is_xid_continue(c
))
569 fn validate_term(string
: &str) {
570 let validate
= string
;
571 if validate
.is_empty() {
572 panic
!("Ident is not allowed to be empty; use Option<Ident>");
575 if validate
.bytes().all(|digit
| digit
>= b'
0'
&& digit
<= b'
9'
) {
576 panic
!("Ident cannot be a number; use Literal instead");
579 fn ident_ok(string
: &str) -> bool
{
580 let mut chars
= string
.chars();
581 let first
= chars
.next().unwrap();
582 if !is_ident_start(first
) {
586 if !is_ident_continue(ch
) {
593 if !ident_ok(validate
) {
594 panic
!("{:?} is not a valid Ident", string
);
598 impl PartialEq
for Ident
{
599 fn eq(&self, other
: &Ident
) -> bool
{
600 self.sym
== other
.sym
&& self.raw
== other
.raw
604 impl<T
> PartialEq
<T
> for Ident
606 T
: ?Sized
+ AsRef
<str>,
608 fn eq(&self, other
: &T
) -> bool
{
609 let other
= other
.as_ref();
611 other
.starts_with("r#") && self.sym
== other
[2..]
618 impl fmt
::Display
for Ident
{
619 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
627 impl fmt
::Debug
for Ident
{
628 // Ident(proc_macro), Ident(r#union)
629 #[cfg(not(procmacro2_semver_exempt))]
630 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
631 let mut debug
= f
.debug_tuple("Ident");
632 debug
.field(&format_args
!("{}", self));
638 // span: bytes(128..138)
640 #[cfg(procmacro2_semver_exempt)]
641 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
642 let mut debug
= f
.debug_struct("Ident");
643 debug
.field("sym", &format_args
!("{}", self));
644 debug
.field("span", &self.span
);
655 macro_rules
! suffixed_numbers
{
656 ($
($name
:ident
=> $kind
:ident
,)*) => ($
(
657 pub fn $
name(n
: $kind
) -> Literal
{
658 Literal
::_new(format
!(concat
!("{}", stringify
!($kind
)), n
))
663 macro_rules
! unsuffixed_numbers
{
664 ($
($name
:ident
=> $kind
:ident
,)*) => ($
(
665 pub fn $
name(n
: $kind
) -> Literal
{
666 Literal
::_new(n
.to_string())
672 fn _new(text
: String
) -> Literal
{
675 span
: Span
::call_site(),
684 usize_suffixed
=> usize,
689 isize_suffixed
=> isize,
697 u128_suffixed
=> u128
,
698 i128_suffixed
=> i128
,
701 unsuffixed_numbers
! {
703 u16_unsuffixed
=> u16,
704 u32_unsuffixed
=> u32,
705 u64_unsuffixed
=> u64,
706 usize_unsuffixed
=> usize,
708 i16_unsuffixed
=> i16,
709 i32_unsuffixed
=> i32,
710 i64_unsuffixed
=> i64,
711 isize_unsuffixed
=> isize,
715 unsuffixed_numbers
! {
716 u128_unsuffixed
=> u128
,
717 i128_unsuffixed
=> i128
,
720 pub fn f32_unsuffixed(f
: f32) -> Literal
{
721 let mut s
= f
.to_string();
722 if !s
.contains(".") {
728 pub fn f64_unsuffixed(f
: f64) -> Literal
{
729 let mut s
= f
.to_string();
730 if !s
.contains(".") {
736 pub fn string(t
: &str) -> Literal
{
739 .flat_map(|c
| c
.escape_default())
740 .collect
::<String
>();
746 pub fn character(t
: char) -> Literal
{
747 Literal
::_new(format
!("'{}'", t
.escape_default().collect
::<String
>()))
750 pub fn byte_string(bytes
: &[u8]) -> Literal
{
751 let mut escaped
= "b\"".to_string();
754 b'
\0'
=> escaped
.push_str(r
"\0"),
755 b'
\t'
=> escaped
.push_str(r
"\t"),
756 b'
\n'
=> escaped
.push_str(r
"\n"),
757 b'
\r'
=> escaped
.push_str(r
"\r"),
758 b'
"' => escaped.push_str("\\\""),
759 b'\\' => escaped.push_str("\\\\"),
760 b'\x20'...b'\x7E' => escaped.push(*b as char),
761 _ => escaped.push_str(&format!("\\x{:02X}
", b)),
765 Literal
::_new(escaped
)
768 pub fn span(&self) -> Span
{
772 pub fn set_span(&mut self, span
: Span
) {
777 impl fmt
::Display
for Literal
{
778 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
783 impl fmt
::Debug
for Literal
{
784 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
785 let mut debug
= fmt
.debug_struct("Literal");
786 debug
.field("lit", &format_args
!("{}", self.text
));
787 #[cfg(procmacro2_semver_exempt)]
788 debug
.field("span", &self.span
);
793 fn token_stream(mut input
: Cursor
) -> PResult
<TokenStream
> {
794 let mut trees
= Vec
::new();
796 let input_no_ws
= skip_whitespace(input
);
797 if input_no_ws
.rest
.len() == 0 {
800 if let Ok((a
, tokens
)) = doc_comment(input_no_ws
) {
802 trees
.extend(tokens
);
806 let (a
, tt
) = match token_tree(input_no_ws
) {
813 Ok((input
, TokenStream { inner: trees }
))
816 #[cfg(not(span_locations))]
819 f
: fn(Cursor
<'a
>) -> PResult
<'a
, T
>,
820 ) -> PResult
<'a
, (T
, ::Span
)> {
821 let (a
, b
) = f(skip_whitespace(input
))?
;
822 Ok((a
, ((b
, ::Span
::_new_stable(Span
::call_site())))))
825 #[cfg(span_locations)]
828 f
: fn(Cursor
<'a
>) -> PResult
<'a
, T
>,
829 ) -> PResult
<'a
, (T
, ::Span
)> {
830 let input
= skip_whitespace(input
);
832 let (a
, b
) = f(input
)?
;
834 let span
= ::Span
::_new_stable(Span { lo: lo, hi: hi }
);
838 fn token_tree(input
: Cursor
) -> PResult
<TokenTree
> {
839 let (rest
, (mut tt
, span
)) = spanned(input
, token_kind
)?
;
844 named
!(token_kind
-> TokenTree
, alt
!(
845 map
!(group
, |g
| TokenTree
::Group(::Group
::_new_stable(g
)))
847 map
!(literal
, |l
| TokenTree
::Literal(::Literal
::_new_stable(l
))) // must be before symbol
849 map
!(op
, TokenTree
::Punct
)
854 named
!(group
-> Group
, alt
!(
859 ) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
865 ) => { |ts| Group::new(Delimiter::Bracket, ts) }
871 ) => { |ts| Group::new(Delimiter::Brace, ts) }
874 fn symbol_leading_ws(input
: Cursor
) -> PResult
<TokenTree
> {
875 symbol(skip_whitespace(input
))
878 fn symbol(input
: Cursor
) -> PResult
<TokenTree
> {
879 let mut chars
= input
.char_indices();
881 let raw
= input
.starts_with("r#");
888 Some((_
, ch
)) if is_ident_start(ch
) => {}
889 _
=> return Err(LexError
),
892 let mut end
= input
.len();
893 for (i
, ch
) in chars
{
894 if !is_ident_continue(ch
) {
900 let a
= &input
.rest
[..end
];
905 ::Ident
::_new_raw(&a
[2..], ::Span
::call_site())
907 ::Ident
::new(a
, ::Span
::call_site())
909 Ok((input
.advance(end
), ident
.into()))
913 fn literal(input
: Cursor
) -> PResult
<Literal
> {
914 let input_no_ws
= skip_whitespace(input
);
916 match literal_nocapture(input_no_ws
) {
918 let start
= input
.len() - input_no_ws
.len();
919 let len
= input_no_ws
.len() - a
.len();
920 let end
= start
+ len
;
921 Ok((a
, Literal
::_new(input
.rest
[start
..end
].to_string())))
923 Err(LexError
) => Err(LexError
),
927 named
!(literal_nocapture
-> (), alt
!(
941 named
!(string
-> (), alt
!(
950 named
!(quoted_string
-> (), delimited
!(
956 fn cooked_string(input
: Cursor
) -> PResult
<()> {
957 let mut chars
= input
.char_indices().peekable();
958 while let Some((byte_offset
, ch
)) = chars
.next() {
961 return Ok((input.advance(byte_offset), ()));
964 if let Some((_, '\n')) = chars.next() {
970 '\\' => match chars.next() {
972 if !backslash_x_char(&mut chars) {
976 Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
977 | Some((_, '\'')) | Some((_, '"'
)) | Some((_
, '
0'
)) => {}
979 if !backslash_u(&mut chars
) {
983 Some((_
, '
\n'
)) | Some((_
, '
\r'
)) => {
984 while let Some(&(_
, ch
)) = chars
.peek() {
985 if ch
.is_whitespace() {
1000 named
!(byte_string
-> (), alt
!(
1013 fn cooked_byte_string(mut input
: Cursor
) -> PResult
<()> {
1014 let mut bytes
= input
.bytes().enumerate();
1015 'outer
: while let Some((offset
, b
)) = bytes
.next() {
1018 return Ok((input.advance(offset), ()));
1021 if let Some((_, b'\n')) = bytes.next() {
1027 b'\\' => match bytes.next() {
1028 Some((_, b'x')) => {
1029 if !backslash_x_byte(&mut bytes) {
1033 Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
1034 | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"'
)) => {}
1035 Some((newline
, b'
\n'
)) | Some((newline
, b'
\r'
)) => {
1036 let rest
= input
.advance(newline
+ 1);
1037 for (offset
, ch
) in rest
.char_indices() {
1038 if !ch
.is_whitespace() {
1039 input
= rest
.advance(offset
);
1040 bytes
= input
.bytes().enumerate();
1055 fn raw_string(input
: Cursor
) -> PResult
<()> {
1056 let mut chars
= input
.char_indices();
1058 while let Some((byte_offset
, ch
)) = chars
.next() {
1065 _ => return Err(LexError),
1068 for (byte_offset, ch) in chars {
1070 '"'
if input
.advance(byte_offset
+ 1).starts_with(&input
.rest
[..n
]) => {
1071 let rest
= input
.advance(byte_offset
+ 1 + n
);
1072 return Ok((rest
, ()));
1081 named
!(byte
-> (), do_parse
!(
1089 fn cooked_byte(input
: Cursor
) -> PResult
<()> {
1090 let mut bytes
= input
.bytes().enumerate();
1091 let ok
= match bytes
.next().map(|(_
, b
)| b
) {
1092 Some(b'
\\'
) => match bytes
.next().map(|(_
, b
)| b
) {
1093 Some(b'x'
) => backslash_x_byte(&mut bytes
),
1094 Some(b'n'
) | Some(b'r'
) | Some(b't'
) | Some(b'
\\'
) | Some(b'
0'
) | Some(b'
\''
)
1095 | Some(b'
"') => true,
1101 match bytes.next() {
1102 Some((offset, _)) => {
1103 if input.chars().as_str().is_char_boundary(offset) {
1104 Ok((input.advance(offset), ()))
1109 None => Ok((input.advance(input.len()), ())),
1116 named!(character -> (), do_parse!(
1123 fn cooked_char(input: Cursor) -> PResult<()> {
1124 let mut chars = input.char_indices();
1125 let ok = match chars.next().map(|(_, ch)| ch) {
1126 Some('\\') => match chars.next().map(|(_, ch)| ch) {
1127 Some('x') => backslash_x_char(&mut chars),
1128 Some('u') => backslash_u(&mut chars),
1129 Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"'
) => {
1137 match chars
.next() {
1138 Some((idx
, _
)) => Ok((input
.advance(idx
), ())),
1139 None
=> Ok((input
.advance(input
.len()), ())),
1146 macro_rules
! next_ch
{
1147 ($chars
:ident @ $pat
:pat $
(| $rest
:pat
)*) => {
1148 match $chars
.next() {
1149 Some((_
, ch
)) => match ch
{
1150 $pat $
(| $rest
)* => ch
,
1153 None
=> return false
1158 fn backslash_x_char
<I
>(chars
: &mut I
) -> bool
1160 I
: Iterator
<Item
= (usize, char)>,
1162 next_ch
!(chars @ '
0'
...'
7'
);
1163 next_ch
!(chars @ '
0'
...'
9'
| 'a'
...'f'
| 'A'
...'F'
);
1167 fn backslash_x_byte
<I
>(chars
: &mut I
) -> bool
1169 I
: Iterator
<Item
= (usize, u8)>,
1171 next_ch
!(chars @ b'
0'
...b'
9'
| b'a'
...b'f'
| b'A'
...b'F'
);
1172 next_ch
!(chars @ b'
0'
...b'
9'
| b'a'
...b'f'
| b'A'
...b'F'
);
1176 fn backslash_u
<I
>(chars
: &mut I
) -> bool
1178 I
: Iterator
<Item
= (usize, char)>,
1180 next_ch
!(chars @ '
{'
);
1181 next_ch
!(chars @ '
0'
...'
9'
| 'a'
...'f'
| 'A'
...'F'
);
1183 let c
= next_ch
!(chars @ '
0'
...'
9'
| 'a'
...'f'
| 'A'
...'F'
| '_'
| '
}'
);
1190 fn float(input
: Cursor
) -> PResult
<()> {
1191 let (rest
, ()) = float_digits(input
)?
;
1192 for suffix
in &["f32", "f64"] {
1193 if rest
.starts_with(suffix
) {
1194 return word_break(rest
.advance(suffix
.len()));
1200 fn float_digits(input
: Cursor
) -> PResult
<()> {
1201 let mut chars
= input
.chars().peekable();
1202 match chars
.next() {
1203 Some(ch
) if ch
>= '
0'
&& ch
<= '
9'
=> {}
1204 _
=> return Err(LexError
),
1208 let mut has_dot
= false;
1209 let mut has_exp
= false;
1210 while let Some(&ch
) = chars
.peek() {
1212 '
0'
...'
9'
| '_'
=> {
1223 .map(|&ch
| ch
== '
.'
|| UnicodeXID
::is_xid_start(ch
))
1226 return Err(LexError
);
1241 let rest
= input
.advance(len
);
1242 if !(has_dot
|| has_exp
|| rest
.starts_with("f32") || rest
.starts_with("f64")) {
1243 return Err(LexError
);
1247 let mut has_exp_value
= false;
1248 while let Some(&ch
) = chars
.peek() {
1260 has_exp_value
= true;
1270 return Err(LexError
);
1274 Ok((input
.advance(len
), ()))
1277 fn int(input
: Cursor
) -> PResult
<()> {
1278 let (rest
, ()) = digits(input
)?
;
1280 "isize", "i8", "i16", "i32", "i64", "i128", "usize", "u8", "u16", "u32", "u64", "u128",
1282 if rest
.starts_with(suffix
) {
1283 return word_break(rest
.advance(suffix
.len()));
1289 fn digits(mut input
: Cursor
) -> PResult
<()> {
1290 let base
= if input
.starts_with("0x") {
1291 input
= input
.advance(2);
1293 } else if input
.starts_with("0o") {
1294 input
= input
.advance(2);
1296 } else if input
.starts_with("0b") {
1297 input
= input
.advance(2);
1304 let mut empty
= true;
1305 for b
in input
.bytes() {
1306 let digit
= match b
{
1307 b'
0'
...b'
9'
=> (b
- b'
0'
) as u64,
1308 b'a'
...b'f'
=> 10 + (b
- b'a'
) as u64,
1309 b'A'
...b'F'
=> 10 + (b
- b'A'
) as u64,
1311 if empty
&& base
== 10 {
1312 return Err(LexError
);
1320 return Err(LexError
);
1328 Ok((input
.advance(len
), ()))
1332 fn op(input
: Cursor
) -> PResult
<Punct
> {
1333 let input
= skip_whitespace(input
);
1334 match op_char(input
) {
1335 Ok((rest
, '
\''
)) => {
1337 Ok((rest
, Punct
::new('
\''
, Spacing
::Joint
)))
1340 let kind
= match op_char(rest
) {
1341 Ok(_
) => Spacing
::Joint
,
1342 Err(LexError
) => Spacing
::Alone
,
1344 Ok((rest
, Punct
::new(ch
, kind
)))
1346 Err(LexError
) => Err(LexError
),
1350 fn op_char(input
: Cursor
) -> PResult
<char> {
1351 if input
.starts_with("//") || input
.starts_with("/*") {
1352 // Do not accept `/` of a comment as an op.
1353 return Err(LexError
);
1356 let mut chars
= input
.chars();
1357 let first
= match chars
.next() {
1360 return Err(LexError
);
1363 let recognized
= "~!@#$%^&*-=+|;:,<.>/?'";
1364 if recognized
.contains(first
) {
1365 Ok((input
.advance(first
.len_utf8()), first
))
1371 fn doc_comment(input
: Cursor
) -> PResult
<Vec
<TokenTree
>> {
1372 let mut trees
= Vec
::new();
1373 let (rest
, ((comment
, inner
), span
)) = spanned(input
, doc_comment_contents
)?
;
1374 trees
.push(TokenTree
::Punct(Punct
::new('
#', Spacing::Alone)));
1376 trees
.push(Punct
::new('
!'
, Spacing
::Alone
).into());
1378 let mut stream
= vec
![
1379 TokenTree
::Ident(::Ident
::new("doc", span
)),
1380 TokenTree
::Punct(Punct
::new('
='
, Spacing
::Alone
)),
1381 TokenTree
::Literal(::Literal
::string(comment
)),
1383 for tt
in stream
.iter_mut() {
1386 let group
= Group
::new(Delimiter
::Bracket
, stream
.into_iter().collect());
1387 trees
.push(::Group
::_new_stable(group
).into());
1388 for tt
in trees
.iter_mut() {
1394 named
!(doc_comment_contents
-> (&str, bool
), alt
!(
1397 s
: take_until_newline_or_eof
!() >>
1402 option
!(whitespace
) >>
1403 peek
!(tag
!("/*!")) >>
1411 s
: take_until_newline_or_eof
!() >>
1416 option
!(whitespace
) >>
1417 peek
!(tuple
!(tag
!("/**"), not
!(tag
!("*")))) >>