1 use crate::fallback::{
2 is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream,
3 TokenStreamBuilder,
4 };
5 use crate::{Delimiter, Punct, Spacing, TokenTree};
6 use core::char;
7 use core::str::{Bytes, CharIndices, Chars};
8
9 #[derive(Copy, Clone, Eq, PartialEq)]
10 pub(crate) struct Cursor<'a> {
11 pub rest: &'a str,
12 #[cfg(span_locations)]
13 pub off: u32,
14 }
15
16 impl<'a> Cursor<'a> {
advance(&self, bytes: usize) -> Cursor<'a>17 pub fn advance(&self, bytes: usize) -> Cursor<'a> {
18 let (_front, rest) = self.rest.split_at(bytes);
19 Cursor {
20 rest,
21 #[cfg(span_locations)]
22 off: self.off + _front.chars().count() as u32,
23 }
24 }
25
starts_with(&self, s: &str) -> bool26 pub fn starts_with(&self, s: &str) -> bool {
27 self.rest.starts_with(s)
28 }
29
starts_with_char(&self, ch: char) -> bool30 pub fn starts_with_char(&self, ch: char) -> bool {
31 self.rest.starts_with(ch)
32 }
33
starts_with_fn<Pattern>(&self, f: Pattern) -> bool where Pattern: FnMut(char) -> bool,34 pub fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool
35 where
36 Pattern: FnMut(char) -> bool,
37 {
38 self.rest.starts_with(f)
39 }
40
is_empty(&self) -> bool41 pub fn is_empty(&self) -> bool {
42 self.rest.is_empty()
43 }
44
len(&self) -> usize45 fn len(&self) -> usize {
46 self.rest.len()
47 }
48
as_bytes(&self) -> &'a [u8]49 fn as_bytes(&self) -> &'a [u8] {
50 self.rest.as_bytes()
51 }
52
bytes(&self) -> Bytes<'a>53 fn bytes(&self) -> Bytes<'a> {
54 self.rest.bytes()
55 }
56
chars(&self) -> Chars<'a>57 fn chars(&self) -> Chars<'a> {
58 self.rest.chars()
59 }
60
char_indices(&self) -> CharIndices<'a>61 fn char_indices(&self) -> CharIndices<'a> {
62 self.rest.char_indices()
63 }
64
parse(&self, tag: &str) -> Result<Cursor<'a>, Reject>65 fn parse(&self, tag: &str) -> Result<Cursor<'a>, Reject> {
66 if self.starts_with(tag) {
67 Ok(self.advance(tag.len()))
68 } else {
69 Err(Reject)
70 }
71 }
72 }
73
74 pub(crate) struct Reject;
75 type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>;
76
skip_whitespace(input: Cursor) -> Cursor77 fn skip_whitespace(input: Cursor) -> Cursor {
78 let mut s = input;
79
80 while !s.is_empty() {
81 let byte = s.as_bytes()[0];
82 if byte == b'/' {
83 if s.starts_with("//")
84 && (!s.starts_with("///") || s.starts_with("////"))
85 && !s.starts_with("//!")
86 {
87 let (cursor, _) = take_until_newline_or_eof(s);
88 s = cursor;
89 continue;
90 } else if s.starts_with("/**/") {
91 s = s.advance(4);
92 continue;
93 } else if s.starts_with("/*")
94 && (!s.starts_with("/**") || s.starts_with("/***"))
95 && !s.starts_with("/*!")
96 {
97 match block_comment(s) {
98 Ok((rest, _)) => {
99 s = rest;
100 continue;
101 }
102 Err(Reject) => return s,
103 }
104 }
105 }
106 match byte {
107 b' ' | 0x09..=0x0d => {
108 s = s.advance(1);
109 continue;
110 }
111 b if b.is_ascii() => {}
112 _ => {
113 let ch = s.chars().next().unwrap();
114 if is_whitespace(ch) {
115 s = s.advance(ch.len_utf8());
116 continue;
117 }
118 }
119 }
120 return s;
121 }
122 s
123 }
124
block_comment(input: Cursor) -> PResult<&str>125 fn block_comment(input: Cursor) -> PResult<&str> {
126 if !input.starts_with("/*") {
127 return Err(Reject);
128 }
129
130 let mut depth = 0usize;
131 let bytes = input.as_bytes();
132 let mut i = 0usize;
133 let upper = bytes.len() - 1;
134
135 while i < upper {
136 if bytes[i] == b'/' && bytes[i + 1] == b'*' {
137 depth += 1;
138 i += 1; // eat '*'
139 } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
140 depth -= 1;
141 if depth == 0 {
142 return Ok((input.advance(i + 2), &input.rest[..i + 2]));
143 }
144 i += 1; // eat '/'
145 }
146 i += 1;
147 }
148
149 Err(Reject)
150 }
151
is_whitespace(ch: char) -> bool152 fn is_whitespace(ch: char) -> bool {
153 // Rust treats left-to-right mark and right-to-left mark as whitespace
154 ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
155 }
156
word_break(input: Cursor) -> Result<Cursor, Reject>157 fn word_break(input: Cursor) -> Result<Cursor, Reject> {
158 match input.chars().next() {
159 Some(ch) if is_ident_continue(ch) => Err(Reject),
160 Some(_) | None => Ok(input),
161 }
162 }
163
164 // Rustc's representation of a macro expansion error in expression position or
165 // type position.
166 const ERROR: &str = "(/*ERROR*/)";
167
token_stream(mut input: Cursor) -> Result<TokenStream, LexError>168 pub(crate) fn token_stream(mut input: Cursor) -> Result<TokenStream, LexError> {
169 let mut trees = TokenStreamBuilder::new();
170 let mut stack = Vec::new();
171
172 loop {
173 input = skip_whitespace(input);
174
175 if let Ok((rest, ())) = doc_comment(input, &mut trees) {
176 input = rest;
177 continue;
178 }
179
180 #[cfg(span_locations)]
181 let lo = input.off;
182
183 let first = match input.bytes().next() {
184 Some(first) => first,
185 None => match stack.last() {
186 None => return Ok(trees.build()),
187 #[cfg(span_locations)]
188 Some((lo, _frame)) => {
189 return Err(LexError {
190 span: Span { lo: *lo, hi: *lo },
191 })
192 }
193 #[cfg(not(span_locations))]
194 Some(_frame) => return Err(LexError { span: Span {} }),
195 },
196 };
197
198 if let Some(open_delimiter) = match first {
199 b'(' if !input.starts_with(ERROR) => Some(Delimiter::Parenthesis),
200 b'[' => Some(Delimiter::Bracket),
201 b'{' => Some(Delimiter::Brace),
202 _ => None,
203 } {
204 input = input.advance(1);
205 let frame = (open_delimiter, trees);
206 #[cfg(span_locations)]
207 let frame = (lo, frame);
208 stack.push(frame);
209 trees = TokenStreamBuilder::new();
210 } else if let Some(close_delimiter) = match first {
211 b')' => Some(Delimiter::Parenthesis),
212 b']' => Some(Delimiter::Bracket),
213 b'}' => Some(Delimiter::Brace),
214 _ => None,
215 } {
216 let frame = match stack.pop() {
217 Some(frame) => frame,
218 None => return Err(lex_error(input)),
219 };
220 #[cfg(span_locations)]
221 let (lo, frame) = frame;
222 let (open_delimiter, outer) = frame;
223 if open_delimiter != close_delimiter {
224 return Err(lex_error(input));
225 }
226 input = input.advance(1);
227 let mut g = Group::new(open_delimiter, trees.build());
228 g.set_span(Span {
229 #[cfg(span_locations)]
230 lo,
231 #[cfg(span_locations)]
232 hi: input.off,
233 });
234 trees = outer;
235 trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g)));
236 } else {
237 let (rest, mut tt) = match leaf_token(input) {
238 Ok((rest, tt)) => (rest, tt),
239 Err(Reject) => return Err(lex_error(input)),
240 };
241 tt.set_span(crate::Span::_new_fallback(Span {
242 #[cfg(span_locations)]
243 lo,
244 #[cfg(span_locations)]
245 hi: rest.off,
246 }));
247 trees.push_token_from_parser(tt);
248 input = rest;
249 }
250 }
251 }
252
lex_error(cursor: Cursor) -> LexError253 fn lex_error(cursor: Cursor) -> LexError {
254 #[cfg(not(span_locations))]
255 let _ = cursor;
256 LexError {
257 span: Span {
258 #[cfg(span_locations)]
259 lo: cursor.off,
260 #[cfg(span_locations)]
261 hi: cursor.off,
262 },
263 }
264 }
265
leaf_token(input: Cursor) -> PResult<TokenTree>266 fn leaf_token(input: Cursor) -> PResult<TokenTree> {
267 if let Ok((input, l)) = literal(input) {
268 // must be parsed before ident
269 Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l))))
270 } else if let Ok((input, p)) = punct(input) {
271 Ok((input, TokenTree::Punct(p)))
272 } else if let Ok((input, i)) = ident(input) {
273 Ok((input, TokenTree::Ident(i)))
274 } else if input.starts_with(ERROR) {
275 let rest = input.advance(ERROR.len());
276 let repr = crate::Literal::_new_fallback(Literal::_new(ERROR.to_owned()));
277 Ok((rest, TokenTree::Literal(repr)))
278 } else {
279 Err(Reject)
280 }
281 }
282
ident(input: Cursor) -> PResult<crate::Ident>283 fn ident(input: Cursor) -> PResult<crate::Ident> {
284 if [
285 "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#",
286 ]
287 .iter()
288 .any(|prefix| input.starts_with(prefix))
289 {
290 Err(Reject)
291 } else {
292 ident_any(input)
293 }
294 }
295
ident_any(input: Cursor) -> PResult<crate::Ident>296 fn ident_any(input: Cursor) -> PResult<crate::Ident> {
297 let raw = input.starts_with("r#");
298 let rest = input.advance((raw as usize) << 1);
299
300 let (rest, sym) = ident_not_raw(rest)?;
301
302 if !raw {
303 let ident = crate::Ident::new(sym, crate::Span::call_site());
304 return Ok((rest, ident));
305 }
306
307 match sym {
308 "_" | "super" | "self" | "Self" | "crate" => return Err(Reject),
309 _ => {}
310 }
311
312 let ident = crate::Ident::_new_raw(sym, crate::Span::call_site());
313 Ok((rest, ident))
314 }
315
ident_not_raw(input: Cursor) -> PResult<&str>316 fn ident_not_raw(input: Cursor) -> PResult<&str> {
317 let mut chars = input.char_indices();
318
319 match chars.next() {
320 Some((_, ch)) if is_ident_start(ch) => {}
321 _ => return Err(Reject),
322 }
323
324 let mut end = input.len();
325 for (i, ch) in chars {
326 if !is_ident_continue(ch) {
327 end = i;
328 break;
329 }
330 }
331
332 Ok((input.advance(end), &input.rest[..end]))
333 }
334
literal(input: Cursor) -> PResult<Literal>335 pub(crate) fn literal(input: Cursor) -> PResult<Literal> {
336 let rest = literal_nocapture(input)?;
337 let end = input.len() - rest.len();
338 Ok((rest, Literal::_new(input.rest[..end].to_string())))
339 }
340
literal_nocapture(input: Cursor) -> Result<Cursor, Reject>341 fn literal_nocapture(input: Cursor) -> Result<Cursor, Reject> {
342 if let Ok(ok) = string(input) {
343 Ok(ok)
344 } else if let Ok(ok) = byte_string(input) {
345 Ok(ok)
346 } else if let Ok(ok) = c_string(input) {
347 Ok(ok)
348 } else if let Ok(ok) = byte(input) {
349 Ok(ok)
350 } else if let Ok(ok) = character(input) {
351 Ok(ok)
352 } else if let Ok(ok) = float(input) {
353 Ok(ok)
354 } else if let Ok(ok) = int(input) {
355 Ok(ok)
356 } else {
357 Err(Reject)
358 }
359 }
360
literal_suffix(input: Cursor) -> Cursor361 fn literal_suffix(input: Cursor) -> Cursor {
362 match ident_not_raw(input) {
363 Ok((input, _)) => input,
364 Err(Reject) => input,
365 }
366 }
367
string(input: Cursor) -> Result<Cursor, Reject>368 fn string(input: Cursor) -> Result<Cursor, Reject> {
369 if let Ok(input) = input.parse("\"") {
370 cooked_string(input)
371 } else if let Ok(input) = input.parse("r") {
372 raw_string(input)
373 } else {
374 Err(Reject)
375 }
376 }
377
cooked_string(mut input: Cursor) -> Result<Cursor, Reject>378 fn cooked_string(mut input: Cursor) -> Result<Cursor, Reject> {
379 let mut chars = input.char_indices();
380
381 while let Some((i, ch)) = chars.next() {
382 match ch {
383 '"' => {
384 let input = input.advance(i + 1);
385 return Ok(literal_suffix(input));
386 }
387 '\r' => match chars.next() {
388 Some((_, '\n')) => {}
389 _ => break,
390 },
391 '\\' => match chars.next() {
392 Some((_, 'x')) => {
393 backslash_x_char(&mut chars)?;
394 }
395 Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0')) => {}
396 Some((_, 'u')) => {
397 backslash_u(&mut chars)?;
398 }
399 Some((newline, ch @ ('\n' | '\r'))) => {
400 input = input.advance(newline + 1);
401 trailing_backslash(&mut input, ch as u8)?;
402 chars = input.char_indices();
403 }
404 _ => break,
405 },
406 _ch => {}
407 }
408 }
409 Err(Reject)
410 }
411
raw_string(input: Cursor) -> Result<Cursor, Reject>412 fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
413 let (input, delimiter) = delimiter_of_raw_string(input)?;
414 let mut bytes = input.bytes().enumerate();
415 while let Some((i, byte)) = bytes.next() {
416 match byte {
417 b'"' if input.rest[i + 1..].starts_with(delimiter) => {
418 let rest = input.advance(i + 1 + delimiter.len());
419 return Ok(literal_suffix(rest));
420 }
421 b'\r' => match bytes.next() {
422 Some((_, b'\n')) => {}
423 _ => break,
424 },
425 _ => {}
426 }
427 }
428 Err(Reject)
429 }
430
byte_string(input: Cursor) -> Result<Cursor, Reject>431 fn byte_string(input: Cursor) -> Result<Cursor, Reject> {
432 if let Ok(input) = input.parse("b\"") {
433 cooked_byte_string(input)
434 } else if let Ok(input) = input.parse("br") {
435 raw_byte_string(input)
436 } else {
437 Err(Reject)
438 }
439 }
440
cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject>441 fn cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject> {
442 let mut bytes = input.bytes().enumerate();
443 while let Some((offset, b)) = bytes.next() {
444 match b {
445 b'"' => {
446 let input = input.advance(offset + 1);
447 return Ok(literal_suffix(input));
448 }
449 b'\r' => match bytes.next() {
450 Some((_, b'\n')) => {}
451 _ => break,
452 },
453 b'\\' => match bytes.next() {
454 Some((_, b'x')) => {
455 backslash_x_byte(&mut bytes)?;
456 }
457 Some((_, b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"')) => {}
458 Some((newline, b @ (b'\n' | b'\r'))) => {
459 input = input.advance(newline + 1);
460 trailing_backslash(&mut input, b)?;
461 bytes = input.bytes().enumerate();
462 }
463 _ => break,
464 },
465 b if b.is_ascii() => {}
466 _ => break,
467 }
468 }
469 Err(Reject)
470 }
471
delimiter_of_raw_string(input: Cursor) -> PResult<&str>472 fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> {
473 for (i, byte) in input.bytes().enumerate() {
474 match byte {
475 b'"' => {
476 if i > 255 {
477 // https://github.com/rust-lang/rust/pull/95251
478 return Err(Reject);
479 }
480 return Ok((input.advance(i + 1), &input.rest[..i]));
481 }
482 b'#' => {}
483 _ => break,
484 }
485 }
486 Err(Reject)
487 }
488
raw_byte_string(input: Cursor) -> Result<Cursor, Reject>489 fn raw_byte_string(input: Cursor) -> Result<Cursor, Reject> {
490 let (input, delimiter) = delimiter_of_raw_string(input)?;
491 let mut bytes = input.bytes().enumerate();
492 while let Some((i, byte)) = bytes.next() {
493 match byte {
494 b'"' if input.rest[i + 1..].starts_with(delimiter) => {
495 let rest = input.advance(i + 1 + delimiter.len());
496 return Ok(literal_suffix(rest));
497 }
498 b'\r' => match bytes.next() {
499 Some((_, b'\n')) => {}
500 _ => break,
501 },
502 other => {
503 if !other.is_ascii() {
504 break;
505 }
506 }
507 }
508 }
509 Err(Reject)
510 }
511
c_string(input: Cursor) -> Result<Cursor, Reject>512 fn c_string(input: Cursor) -> Result<Cursor, Reject> {
513 if let Ok(input) = input.parse("c\"") {
514 cooked_c_string(input)
515 } else if let Ok(input) = input.parse("cr") {
516 raw_c_string(input)
517 } else {
518 Err(Reject)
519 }
520 }
521
raw_c_string(input: Cursor) -> Result<Cursor, Reject>522 fn raw_c_string(input: Cursor) -> Result<Cursor, Reject> {
523 let (input, delimiter) = delimiter_of_raw_string(input)?;
524 let mut bytes = input.bytes().enumerate();
525 while let Some((i, byte)) = bytes.next() {
526 match byte {
527 b'"' if input.rest[i + 1..].starts_with(delimiter) => {
528 let rest = input.advance(i + 1 + delimiter.len());
529 return Ok(literal_suffix(rest));
530 }
531 b'\r' => match bytes.next() {
532 Some((_, b'\n')) => {}
533 _ => break,
534 },
535 b'\0' => break,
536 _ => {}
537 }
538 }
539 Err(Reject)
540 }
541
cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject>542 fn cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject> {
543 let mut chars = input.char_indices();
544
545 while let Some((i, ch)) = chars.next() {
546 match ch {
547 '"' => {
548 let input = input.advance(i + 1);
549 return Ok(literal_suffix(input));
550 }
551 '\r' => match chars.next() {
552 Some((_, '\n')) => {}
553 _ => break,
554 },
555 '\\' => match chars.next() {
556 Some((_, 'x')) => {
557 backslash_x_nonzero(&mut chars)?;
558 }
559 Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"')) => {}
560 Some((_, 'u')) => {
561 if backslash_u(&mut chars)? == '\0' {
562 break;
563 }
564 }
565 Some((newline, ch @ ('\n' | '\r'))) => {
566 input = input.advance(newline + 1);
567 trailing_backslash(&mut input, ch as u8)?;
568 chars = input.char_indices();
569 }
570 _ => break,
571 },
572 '\0' => break,
573 _ch => {}
574 }
575 }
576 Err(Reject)
577 }
578
byte(input: Cursor) -> Result<Cursor, Reject>579 fn byte(input: Cursor) -> Result<Cursor, Reject> {
580 let input = input.parse("b'")?;
581 let mut bytes = input.bytes().enumerate();
582 let ok = match bytes.next().map(|(_, b)| b) {
583 Some(b'\\') => match bytes.next().map(|(_, b)| b) {
584 Some(b'x') => backslash_x_byte(&mut bytes).is_ok(),
585 Some(b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"') => true,
586 _ => false,
587 },
588 b => b.is_some(),
589 };
590 if !ok {
591 return Err(Reject);
592 }
593 let (offset, _) = bytes.next().ok_or(Reject)?;
594 if !input.chars().as_str().is_char_boundary(offset) {
595 return Err(Reject);
596 }
597 let input = input.advance(offset).parse("'")?;
598 Ok(literal_suffix(input))
599 }
600
character(input: Cursor) -> Result<Cursor, Reject>601 fn character(input: Cursor) -> Result<Cursor, Reject> {
602 let input = input.parse("'")?;
603 let mut chars = input.char_indices();
604 let ok = match chars.next().map(|(_, ch)| ch) {
605 Some('\\') => match chars.next().map(|(_, ch)| ch) {
606 Some('x') => backslash_x_char(&mut chars).is_ok(),
607 Some('u') => backslash_u(&mut chars).is_ok(),
608 Some('n' | 'r' | 't' | '\\' | '0' | '\'' | '"') => true,
609 _ => false,
610 },
611 ch => ch.is_some(),
612 };
613 if !ok {
614 return Err(Reject);
615 }
616 let (idx, _) = chars.next().ok_or(Reject)?;
617 let input = input.advance(idx).parse("'")?;
618 Ok(literal_suffix(input))
619 }
620
621 macro_rules! next_ch {
622 ($chars:ident @ $pat:pat) => {
623 match $chars.next() {
624 Some((_, ch)) => match ch {
625 $pat => ch,
626 _ => return Err(Reject),
627 },
628 None => return Err(Reject),
629 }
630 };
631 }
632
backslash_x_char<I>(chars: &mut I) -> Result<(), Reject> where I: Iterator<Item = (usize, char)>,633 fn backslash_x_char<I>(chars: &mut I) -> Result<(), Reject>
634 where
635 I: Iterator<Item = (usize, char)>,
636 {
637 next_ch!(chars @ '0'..='7');
638 next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
639 Ok(())
640 }
641
backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject> where I: Iterator<Item = (usize, u8)>,642 fn backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject>
643 where
644 I: Iterator<Item = (usize, u8)>,
645 {
646 next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
647 next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
648 Ok(())
649 }
650
backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject> where I: Iterator<Item = (usize, char)>,651 fn backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject>
652 where
653 I: Iterator<Item = (usize, char)>,
654 {
655 let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
656 let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
657 if first == '0' && second == '0' {
658 Err(Reject)
659 } else {
660 Ok(())
661 }
662 }
663
backslash_u<I>(chars: &mut I) -> Result<char, Reject> where I: Iterator<Item = (usize, char)>,664 fn backslash_u<I>(chars: &mut I) -> Result<char, Reject>
665 where
666 I: Iterator<Item = (usize, char)>,
667 {
668 next_ch!(chars @ '{');
669 let mut value = 0;
670 let mut len = 0;
671 for (_, ch) in chars {
672 let digit = match ch {
673 '0'..='9' => ch as u8 - b'0',
674 'a'..='f' => 10 + ch as u8 - b'a',
675 'A'..='F' => 10 + ch as u8 - b'A',
676 '_' if len > 0 => continue,
677 '}' if len > 0 => return char::from_u32(value).ok_or(Reject),
678 _ => break,
679 };
680 if len == 6 {
681 break;
682 }
683 value *= 0x10;
684 value += u32::from(digit);
685 len += 1;
686 }
687 Err(Reject)
688 }
689
trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject>690 fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> {
691 let mut whitespace = input.bytes().enumerate();
692 loop {
693 if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') {
694 return Err(Reject);
695 }
696 match whitespace.next() {
697 Some((_, b @ (b' ' | b'\t' | b'\n' | b'\r'))) => {
698 last = b;
699 }
700 Some((offset, _)) => {
701 *input = input.advance(offset);
702 return Ok(());
703 }
704 None => return Err(Reject),
705 }
706 }
707 }
708
float(input: Cursor) -> Result<Cursor, Reject>709 fn float(input: Cursor) -> Result<Cursor, Reject> {
710 let mut rest = float_digits(input)?;
711 if let Some(ch) = rest.chars().next() {
712 if is_ident_start(ch) {
713 rest = ident_not_raw(rest)?.0;
714 }
715 }
716 word_break(rest)
717 }
718
float_digits(input: Cursor) -> Result<Cursor, Reject>719 fn float_digits(input: Cursor) -> Result<Cursor, Reject> {
720 let mut chars = input.chars().peekable();
721 match chars.next() {
722 Some(ch) if '0' <= ch && ch <= '9' => {}
723 _ => return Err(Reject),
724 }
725
726 let mut len = 1;
727 let mut has_dot = false;
728 let mut has_exp = false;
729 while let Some(&ch) = chars.peek() {
730 match ch {
731 '0'..='9' | '_' => {
732 chars.next();
733 len += 1;
734 }
735 '.' => {
736 if has_dot {
737 break;
738 }
739 chars.next();
740 if chars
741 .peek()
742 .map_or(false, |&ch| ch == '.' || is_ident_start(ch))
743 {
744 return Err(Reject);
745 }
746 len += 1;
747 has_dot = true;
748 }
749 'e' | 'E' => {
750 chars.next();
751 len += 1;
752 has_exp = true;
753 break;
754 }
755 _ => break,
756 }
757 }
758
759 if !(has_dot || has_exp) {
760 return Err(Reject);
761 }
762
763 if has_exp {
764 let token_before_exp = if has_dot {
765 Ok(input.advance(len - 1))
766 } else {
767 Err(Reject)
768 };
769 let mut has_sign = false;
770 let mut has_exp_value = false;
771 while let Some(&ch) = chars.peek() {
772 match ch {
773 '+' | '-' => {
774 if has_exp_value {
775 break;
776 }
777 if has_sign {
778 return token_before_exp;
779 }
780 chars.next();
781 len += 1;
782 has_sign = true;
783 }
784 '0'..='9' => {
785 chars.next();
786 len += 1;
787 has_exp_value = true;
788 }
789 '_' => {
790 chars.next();
791 len += 1;
792 }
793 _ => break,
794 }
795 }
796 if !has_exp_value {
797 return token_before_exp;
798 }
799 }
800
801 Ok(input.advance(len))
802 }
803
int(input: Cursor) -> Result<Cursor, Reject>804 fn int(input: Cursor) -> Result<Cursor, Reject> {
805 let mut rest = digits(input)?;
806 if let Some(ch) = rest.chars().next() {
807 if is_ident_start(ch) {
808 rest = ident_not_raw(rest)?.0;
809 }
810 }
811 word_break(rest)
812 }
813
digits(mut input: Cursor) -> Result<Cursor, Reject>814 fn digits(mut input: Cursor) -> Result<Cursor, Reject> {
815 let base = if input.starts_with("0x") {
816 input = input.advance(2);
817 16
818 } else if input.starts_with("0o") {
819 input = input.advance(2);
820 8
821 } else if input.starts_with("0b") {
822 input = input.advance(2);
823 2
824 } else {
825 10
826 };
827
828 let mut len = 0;
829 let mut empty = true;
830 for b in input.bytes() {
831 match b {
832 b'0'..=b'9' => {
833 let digit = (b - b'0') as u64;
834 if digit >= base {
835 return Err(Reject);
836 }
837 }
838 b'a'..=b'f' => {
839 let digit = 10 + (b - b'a') as u64;
840 if digit >= base {
841 break;
842 }
843 }
844 b'A'..=b'F' => {
845 let digit = 10 + (b - b'A') as u64;
846 if digit >= base {
847 break;
848 }
849 }
850 b'_' => {
851 if empty && base == 10 {
852 return Err(Reject);
853 }
854 len += 1;
855 continue;
856 }
857 _ => break,
858 };
859 len += 1;
860 empty = false;
861 }
862 if empty {
863 Err(Reject)
864 } else {
865 Ok(input.advance(len))
866 }
867 }
868
punct(input: Cursor) -> PResult<Punct>869 fn punct(input: Cursor) -> PResult<Punct> {
870 let (rest, ch) = punct_char(input)?;
871 if ch == '\'' {
872 if ident_any(rest)?.0.starts_with_char('\'') {
873 Err(Reject)
874 } else {
875 Ok((rest, Punct::new('\'', Spacing::Joint)))
876 }
877 } else {
878 let kind = match punct_char(rest) {
879 Ok(_) => Spacing::Joint,
880 Err(Reject) => Spacing::Alone,
881 };
882 Ok((rest, Punct::new(ch, kind)))
883 }
884 }
885
punct_char(input: Cursor) -> PResult<char>886 fn punct_char(input: Cursor) -> PResult<char> {
887 if input.starts_with("//") || input.starts_with("/*") {
888 // Do not accept `/` of a comment as a punct.
889 return Err(Reject);
890 }
891
892 let mut chars = input.chars();
893 let first = match chars.next() {
894 Some(ch) => ch,
895 None => {
896 return Err(Reject);
897 }
898 };
899 let recognized = "~!@#$%^&*-=+|;:,<.>/?'";
900 if recognized.contains(first) {
901 Ok((input.advance(first.len_utf8()), first))
902 } else {
903 Err(Reject)
904 }
905 }
906
doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()>907 fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> {
908 #[cfg(span_locations)]
909 let lo = input.off;
910 let (rest, (comment, inner)) = doc_comment_contents(input)?;
911 let span = crate::Span::_new_fallback(Span {
912 #[cfg(span_locations)]
913 lo,
914 #[cfg(span_locations)]
915 hi: rest.off,
916 });
917
918 let mut scan_for_bare_cr = comment;
919 while let Some(cr) = scan_for_bare_cr.find('\r') {
920 let rest = &scan_for_bare_cr[cr + 1..];
921 if !rest.starts_with('\n') {
922 return Err(Reject);
923 }
924 scan_for_bare_cr = rest;
925 }
926
927 let mut pound = Punct::new('#', Spacing::Alone);
928 pound.set_span(span);
929 trees.push_token_from_parser(TokenTree::Punct(pound));
930
931 if inner {
932 let mut bang = Punct::new('!', Spacing::Alone);
933 bang.set_span(span);
934 trees.push_token_from_parser(TokenTree::Punct(bang));
935 }
936
937 let doc_ident = crate::Ident::new("doc", span);
938 let mut equal = Punct::new('=', Spacing::Alone);
939 equal.set_span(span);
940 let mut literal = crate::Literal::string(comment);
941 literal.set_span(span);
942 let mut bracketed = TokenStreamBuilder::with_capacity(3);
943 bracketed.push_token_from_parser(TokenTree::Ident(doc_ident));
944 bracketed.push_token_from_parser(TokenTree::Punct(equal));
945 bracketed.push_token_from_parser(TokenTree::Literal(literal));
946 let group = Group::new(Delimiter::Bracket, bracketed.build());
947 let mut group = crate::Group::_new_fallback(group);
948 group.set_span(span);
949 trees.push_token_from_parser(TokenTree::Group(group));
950
951 Ok((rest, ()))
952 }
953
doc_comment_contents(input: Cursor) -> PResult<(&str, bool)>954 fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> {
955 if input.starts_with("//!") {
956 let input = input.advance(3);
957 let (input, s) = take_until_newline_or_eof(input);
958 Ok((input, (s, true)))
959 } else if input.starts_with("/*!") {
960 let (input, s) = block_comment(input)?;
961 Ok((input, (&s[3..s.len() - 2], true)))
962 } else if input.starts_with("///") {
963 let input = input.advance(3);
964 if input.starts_with_char('/') {
965 return Err(Reject);
966 }
967 let (input, s) = take_until_newline_or_eof(input);
968 Ok((input, (s, false)))
969 } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') {
970 let (input, s) = block_comment(input)?;
971 Ok((input, (&s[3..s.len() - 2], false)))
972 } else {
973 Err(Reject)
974 }
975 }
976
take_until_newline_or_eof(input: Cursor) -> (Cursor, &str)977 fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) {
978 let chars = input.char_indices();
979
980 for (i, ch) in chars {
981 if ch == '\n' {
982 return (input.advance(i), &input.rest[..i]);
983 } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') {
984 return (input.advance(i + 1), &input.rest[..i]);
985 }
986 }
987
988 (input.advance(input.len()), input.rest)
989 }
990