]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/lexer/mod.rs
Rollup merge of #60356 - JohnTitor:stabilize-as-mut-ptr, r=Centril
[rust.git] / src / libsyntax / parse / lexer / mod.rs
1 use crate::ast::{self, Ident};
2 use crate::parse::{token, ParseSess};
3 use crate::symbol::Symbol;
4
5 use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder};
6 use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION};
7 use core::unicode::property::Pattern_White_Space;
8
9 use std::borrow::Cow;
10 use std::char;
11 use std::iter;
12 use std::mem::replace;
13 use rustc_data_structures::sync::Lrc;
14 use log::debug;
15
16 pub mod comments;
17 mod tokentrees;
18 mod unicode_chars;
19
20 #[derive(Clone, Debug)]
21 pub struct TokenAndSpan {
22     pub tok: token::Token,
23     pub sp: Span,
24 }
25
26 impl Default for TokenAndSpan {
27     fn default() -> Self {
28         TokenAndSpan {
29             tok: token::Whitespace,
30             sp: syntax_pos::DUMMY_SP,
31         }
32     }
33 }
34
35 #[derive(Clone, Debug)]
36 pub struct UnmatchedBrace {
37     pub expected_delim: token::DelimToken,
38     pub found_delim: token::DelimToken,
39     pub found_span: Span,
40     pub unclosed_span: Option<Span>,
41     pub candidate_span: Option<Span>,
42 }
43
44 pub struct StringReader<'a> {
45     crate sess: &'a ParseSess,
46     /// The absolute offset within the source_map of the next character to read
47     crate next_pos: BytePos,
48     /// The absolute offset within the source_map of the current character
49     crate pos: BytePos,
50     /// The current character (which has been read from self.pos)
51     crate ch: Option<char>,
52     crate source_file: Lrc<syntax_pos::SourceFile>,
53     /// Stop reading src at this index.
54     crate end_src_index: usize,
55     // cached:
56     peek_tok: token::Token,
57     peek_span: Span,
58     peek_span_src_raw: Span,
59     fatal_errs: Vec<DiagnosticBuilder<'a>>,
60     // cache a direct reference to the source text, so that we don't have to
61     // retrieve it via `self.source_file.src.as_ref().unwrap()` all the time.
62     src: Lrc<String>,
63     token: token::Token,
64     span: Span,
65     /// The raw source span which *does not* take `override_span` into account
66     span_src_raw: Span,
67     /// Stack of open delimiters and their spans. Used for error message.
68     open_braces: Vec<(token::DelimToken, Span)>,
69     crate unmatched_braces: Vec<UnmatchedBrace>,
70     /// The type and spans for all braces
71     ///
72     /// Used only for error recovery when arriving to EOF with mismatched braces.
73     matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
74     crate override_span: Option<Span>,
75     last_unclosed_found_span: Option<Span>,
76 }
77
78 impl<'a> StringReader<'a> {
79     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
80         self.mk_sp_and_raw(lo, hi).0
81     }
82
83     fn mk_sp_and_raw(&self, lo: BytePos, hi: BytePos) -> (Span, Span) {
84         let raw = Span::new(lo, hi, NO_EXPANSION);
85         let real = self.override_span.unwrap_or(raw);
86
87         (real, raw)
88     }
89
90     fn mk_ident(&self, string: &str) -> Ident {
91         let mut ident = Ident::from_str(string);
92         if let Some(span) = self.override_span {
93             ident.span = span;
94         }
95
96         ident
97     }
98
99     fn unwrap_or_abort(&mut self, res: Result<TokenAndSpan, ()>) -> TokenAndSpan {
100         match res {
101             Ok(tok) => tok,
102             Err(_) => {
103                 self.emit_fatal_errors();
104                 FatalError.raise();
105             }
106         }
107     }
108
109     fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
110         let res = self.try_next_token();
111         self.unwrap_or_abort(res)
112     }
113
114     /// Returns the next token. EFFECT: advances the string_reader.
115     pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
116         assert!(self.fatal_errs.is_empty());
117         let ret_val = TokenAndSpan {
118             tok: replace(&mut self.peek_tok, token::Whitespace),
119             sp: self.peek_span,
120         };
121         self.advance_token()?;
122         self.span_src_raw = self.peek_span_src_raw;
123
124         Ok(ret_val)
125     }
126
127     /// Immutably extract string if found at current position with given delimiters
128     fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<String> {
129         let mut pos = self.pos;
130         let mut idx = self.src_index(pos);
131         let mut ch = char_at(&self.src, idx);
132         if ch != from_ch {
133             return None;
134         }
135         pos = pos + Pos::from_usize(ch.len_utf8());
136         let start_pos = pos;
137         idx = self.src_index(pos);
138         while idx < self.end_src_index {
139             ch = char_at(&self.src, idx);
140             if ch == to_ch {
141                 return Some(self.src[self.src_index(start_pos)..self.src_index(pos)].to_string());
142             }
143             pos = pos + Pos::from_usize(ch.len_utf8());
144             idx = self.src_index(pos);
145         }
146         return None;
147     }
148
149     fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
150         let mut t = self.try_next_token()?;
151         loop {
152             match t.tok {
153                 token::Whitespace | token::Comment | token::Shebang(_) => {
154                     t = self.try_next_token()?;
155                 }
156                 _ => break,
157             }
158         }
159
160         self.token = t.tok.clone();
161         self.span = t.sp;
162
163         Ok(t)
164     }
165
166     pub fn real_token(&mut self) -> TokenAndSpan {
167         let res = self.try_real_token();
168         self.unwrap_or_abort(res)
169     }
170
171     #[inline]
172     fn is_eof(&self) -> bool {
173         self.ch.is_none()
174     }
175
176     fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) {
177         let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string");
178         err.span_label(self.mk_sp(pos, pos), "unterminated raw string");
179
180         if hash_count > 0 {
181             err.note(&format!("this raw string should be terminated with `\"{}`",
182                               "#".repeat(hash_count as usize)));
183         }
184
185         err.emit();
186         FatalError.raise();
187     }
188
189     fn fatal(&self, m: &str) -> FatalError {
190         self.fatal_span(self.peek_span, m)
191     }
192
193     crate fn emit_fatal_errors(&mut self) {
194         for err in &mut self.fatal_errs {
195             err.emit();
196         }
197
198         self.fatal_errs.clear();
199     }
200
201     pub fn buffer_fatal_errors(&mut self) -> Vec<Diagnostic> {
202         let mut buffer = Vec::new();
203
204         for err in self.fatal_errs.drain(..) {
205             err.buffer(&mut buffer);
206         }
207
208         buffer
209     }
210
211     pub fn peek(&self) -> TokenAndSpan {
212         // FIXME(pcwalton): Bad copy!
213         TokenAndSpan {
214             tok: self.peek_tok.clone(),
215             sp: self.peek_span,
216         }
217     }
218
219     /// For comments.rs, which hackily pokes into next_pos and ch
220     fn new_raw(sess: &'a ParseSess,
221                source_file: Lrc<syntax_pos::SourceFile>,
222                override_span: Option<Span>) -> Self {
223         let mut sr = StringReader::new_raw_internal(sess, source_file, override_span);
224         sr.bump();
225
226         sr
227     }
228
229     fn new_raw_internal(sess: &'a ParseSess, source_file: Lrc<syntax_pos::SourceFile>,
230         override_span: Option<Span>) -> Self
231     {
232         if source_file.src.is_none() {
233             sess.span_diagnostic.bug(&format!("Cannot lex source_file without source: {}",
234                                               source_file.name));
235         }
236
237         let src = (*source_file.src.as_ref().unwrap()).clone();
238
239         StringReader {
240             sess,
241             next_pos: source_file.start_pos,
242             pos: source_file.start_pos,
243             ch: Some('\n'),
244             source_file,
245             end_src_index: src.len(),
246             // dummy values; not read
247             peek_tok: token::Eof,
248             peek_span: syntax_pos::DUMMY_SP,
249             peek_span_src_raw: syntax_pos::DUMMY_SP,
250             src,
251             fatal_errs: Vec::new(),
252             token: token::Eof,
253             span: syntax_pos::DUMMY_SP,
254             span_src_raw: syntax_pos::DUMMY_SP,
255             open_braces: Vec::new(),
256             unmatched_braces: Vec::new(),
257             matching_delim_spans: Vec::new(),
258             override_span,
259             last_unclosed_found_span: None,
260         }
261     }
262
263     pub fn new(sess: &'a ParseSess,
264                source_file: Lrc<syntax_pos::SourceFile>,
265                override_span: Option<Span>) -> Self {
266         let mut sr = StringReader::new_raw(sess, source_file, override_span);
267         if sr.advance_token().is_err() {
268             sr.emit_fatal_errors();
269             FatalError.raise();
270         }
271
272         sr
273     }
274
275     pub fn new_or_buffered_errs(sess: &'a ParseSess,
276                                 source_file: Lrc<syntax_pos::SourceFile>,
277                                 override_span: Option<Span>) -> Result<Self, Vec<Diagnostic>> {
278         let mut sr = StringReader::new_raw(sess, source_file, override_span);
279         if sr.advance_token().is_err() {
280             Err(sr.buffer_fatal_errors())
281         } else {
282             Ok(sr)
283         }
284     }
285
286     pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
287         let begin = sess.source_map().lookup_byte_offset(span.lo());
288         let end = sess.source_map().lookup_byte_offset(span.hi());
289
290         // Make the range zero-length if the span is invalid.
291         if span.lo() > span.hi() || begin.sf.start_pos != end.sf.start_pos {
292             span = span.shrink_to_lo();
293         }
294
295         let mut sr = StringReader::new_raw_internal(sess, begin.sf, None);
296
297         // Seek the lexer to the right byte range.
298         sr.next_pos = span.lo();
299         sr.end_src_index = sr.src_index(span.hi());
300
301         sr.bump();
302
303         if sr.advance_token().is_err() {
304             sr.emit_fatal_errors();
305             FatalError.raise();
306         }
307
308         sr
309     }
310
311     #[inline]
312     fn ch_is(&self, c: char) -> bool {
313         self.ch == Some(c)
314     }
315
316     /// Report a fatal lexical error with a given span.
317     fn fatal_span(&self, sp: Span, m: &str) -> FatalError {
318         self.sess.span_diagnostic.span_fatal(sp, m)
319     }
320
321     /// Report a lexical error with a given span.
322     fn err_span(&self, sp: Span, m: &str) {
323         self.sess.span_diagnostic.struct_span_err(sp, m).emit();
324     }
325
326
327     /// Report a fatal error spanning [`from_pos`, `to_pos`).
328     fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
329         self.fatal_span(self.mk_sp(from_pos, to_pos), m)
330     }
331
332     /// Report a lexical error spanning [`from_pos`, `to_pos`).
333     fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) {
334         self.err_span(self.mk_sp(from_pos, to_pos), m)
335     }
336
337     /// Pushes a character to a message string for error reporting
338     fn push_escaped_char_for_msg(m: &mut String, c: char) {
339         match c {
340             '\u{20}'..='\u{7e}' => {
341                 // Don't escape \, ' or " for user-facing messages
342                 m.push(c);
343             }
344             _ => {
345                 m.extend(c.escape_default());
346             }
347         }
348     }
349
350     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
351     /// escaped character to the error message
352     fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
353         let mut m = m.to_string();
354         m.push_str(": ");
355         Self::push_escaped_char_for_msg(&mut m, c);
356
357         self.fatal_span_(from_pos, to_pos, &m[..])
358     }
359
360     fn struct_span_fatal(&self, from_pos: BytePos, to_pos: BytePos, m: &str)
361         -> DiagnosticBuilder<'a>
362     {
363         self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), m)
364     }
365
366     fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
367         -> DiagnosticBuilder<'a>
368     {
369         let mut m = m.to_string();
370         m.push_str(": ");
371         Self::push_escaped_char_for_msg(&mut m, c);
372
373         self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
374     }
375
376     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
377     /// escaped character to the error message
378     fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
379         let mut m = m.to_string();
380         m.push_str(": ");
381         Self::push_escaped_char_for_msg(&mut m, c);
382         self.err_span_(from_pos, to_pos, &m[..]);
383     }
384
385     fn struct_err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
386         -> DiagnosticBuilder<'a>
387     {
388         let mut m = m.to_string();
389         m.push_str(": ");
390         Self::push_escaped_char_for_msg(&mut m, c);
391
392         self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
393     }
394
395     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the
396     /// offending string to the error message
397     fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> FatalError {
398         m.push_str(": ");
399         m.push_str(&self.src[self.src_index(from_pos)..self.src_index(to_pos)]);
400
401         self.fatal_span_(from_pos, to_pos, &m[..])
402     }
403
404     /// Advance peek_tok and peek_span to refer to the next token, and
405     /// possibly update the interner.
406     fn advance_token(&mut self) -> Result<(), ()> {
407         match self.scan_whitespace_or_comment() {
408             Some(comment) => {
409                 self.peek_span_src_raw = comment.sp;
410                 self.peek_span = comment.sp;
411                 self.peek_tok = comment.tok;
412             }
413             None => {
414                 if self.is_eof() {
415                     self.peek_tok = token::Eof;
416                     let (real, raw) = self.mk_sp_and_raw(
417                         self.source_file.end_pos,
418                         self.source_file.end_pos,
419                     );
420                     self.peek_span = real;
421                     self.peek_span_src_raw = raw;
422                 } else {
423                     let start_bytepos = self.pos;
424                     self.peek_tok = self.next_token_inner()?;
425                     let (real, raw) = self.mk_sp_and_raw(start_bytepos, self.pos);
426                     self.peek_span = real;
427                     self.peek_span_src_raw = raw;
428                 };
429             }
430         }
431
432         Ok(())
433     }
434
435     #[inline]
436     fn src_index(&self, pos: BytePos) -> usize {
437         (pos - self.source_file.start_pos).to_usize()
438     }
439
440     /// Calls `f` with a string slice of the source text spanning from `start`
441     /// up to but excluding `self.pos`, meaning the slice does not include
442     /// the character `self.ch`.
443     fn with_str_from<T, F>(&self, start: BytePos, f: F) -> T
444         where F: FnOnce(&str) -> T
445     {
446         self.with_str_from_to(start, self.pos, f)
447     }
448
449     /// Creates a Name from a given offset to the current offset.
450     fn name_from(&self, start: BytePos) -> ast::Name {
451         debug!("taking an ident from {:?} to {:?}", start, self.pos);
452         self.with_str_from(start, Symbol::intern)
453     }
454
455     /// As name_from, with an explicit endpoint.
456     fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name {
457         debug!("taking an ident from {:?} to {:?}", start, end);
458         self.with_str_from_to(start, end, Symbol::intern)
459     }
460
461     /// Calls `f` with a string slice of the source text spanning from `start`
462     /// up to but excluding `end`.
463     fn with_str_from_to<T, F>(&self, start: BytePos, end: BytePos, f: F) -> T
464         where F: FnOnce(&str) -> T
465     {
466         f(&self.src[self.src_index(start)..self.src_index(end)])
467     }
468
469     /// Converts CRLF to LF in the given string, raising an error on bare CR.
470     fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> {
471         let mut chars = s.char_indices().peekable();
472         while let Some((i, ch)) = chars.next() {
473             if ch == '\r' {
474                 if let Some((lf_idx, '\n')) = chars.peek() {
475                     return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into();
476                 }
477                 let pos = start + BytePos(i as u32);
478                 let end_pos = start + BytePos((i + ch.len_utf8()) as u32);
479                 self.err_span_(pos, end_pos, errmsg);
480             }
481         }
482         return s.into();
483
484         fn translate_crlf_(rdr: &StringReader<'_>,
485                            start: BytePos,
486                            s: &str,
487                            mut j: usize,
488                            mut chars: iter::Peekable<impl Iterator<Item = (usize, char)>>,
489                            errmsg: &str)
490                            -> String {
491             let mut buf = String::with_capacity(s.len());
492             // Skip first CR
493             buf.push_str(&s[.. j - 1]);
494             while let Some((i, ch)) = chars.next() {
495                 if ch == '\r' {
496                     if j < i {
497                         buf.push_str(&s[j..i]);
498                     }
499                     let next = i + ch.len_utf8();
500                     j = next;
501                     if chars.peek().map(|(_, ch)| *ch) != Some('\n') {
502                         let pos = start + BytePos(i as u32);
503                         let end_pos = start + BytePos(next as u32);
504                         rdr.err_span_(pos, end_pos, errmsg);
505                     }
506                 }
507             }
508             if j < s.len() {
509                 buf.push_str(&s[j..]);
510             }
511             buf
512         }
513     }
514
515     /// Advance the StringReader by one character.
516     crate fn bump(&mut self) {
517         let next_src_index = self.src_index(self.next_pos);
518         if next_src_index < self.end_src_index {
519             let next_ch = char_at(&self.src, next_src_index);
520             let next_ch_len = next_ch.len_utf8();
521
522             self.ch = Some(next_ch);
523             self.pos = self.next_pos;
524             self.next_pos = self.next_pos + Pos::from_usize(next_ch_len);
525         } else {
526             self.ch = None;
527             self.pos = self.next_pos;
528         }
529     }
530
531     fn nextch(&self) -> Option<char> {
532         let next_src_index = self.src_index(self.next_pos);
533         if next_src_index < self.end_src_index {
534             Some(char_at(&self.src, next_src_index))
535         } else {
536             None
537         }
538     }
539
540     #[inline]
541     fn nextch_is(&self, c: char) -> bool {
542         self.nextch() == Some(c)
543     }
544
545     fn nextnextch(&self) -> Option<char> {
546         let next_src_index = self.src_index(self.next_pos);
547         if next_src_index < self.end_src_index {
548             let next_next_src_index =
549                 next_src_index + char_at(&self.src, next_src_index).len_utf8();
550             if next_next_src_index < self.end_src_index {
551                 return Some(char_at(&self.src, next_next_src_index));
552             }
553         }
554         None
555     }
556
557     #[inline]
558     fn nextnextch_is(&self, c: char) -> bool {
559         self.nextnextch() == Some(c)
560     }
561
562     /// Eats <XID_start><XID_continue>*, if possible.
563     fn scan_optional_raw_name(&mut self) -> Option<ast::Name> {
564         if !ident_start(self.ch) {
565             return None;
566         }
567
568         let start = self.pos;
569         self.bump();
570
571         while ident_continue(self.ch) {
572             self.bump();
573         }
574
575         self.with_str_from(start, |string| {
576             if string == "_" {
577                 self.sess.span_diagnostic
578                     .struct_span_warn(self.mk_sp(start, self.pos),
579                                       "underscore literal suffix is not allowed")
580                     .warn("this was previously accepted by the compiler but is \
581                           being phased out; it will become a hard error in \
582                           a future release!")
583                     .note("for more information, see issue #42326 \
584                           <https://github.com/rust-lang/rust/issues/42326>")
585                     .emit();
586                 None
587             } else {
588                 Some(Symbol::intern(string))
589             }
590         })
591     }
592
593     /// PRECONDITION: self.ch is not whitespace
594     /// Eats any kind of comment.
595     fn scan_comment(&mut self) -> Option<TokenAndSpan> {
596         if let Some(c) = self.ch {
597             if c.is_whitespace() {
598                 let msg = "called consume_any_line_comment, but there was whitespace";
599                 self.sess.span_diagnostic.span_err(self.mk_sp(self.pos, self.pos), msg);
600             }
601         }
602
603         if self.ch_is('/') {
604             match self.nextch() {
605                 Some('/') => {
606                     self.bump();
607                     self.bump();
608
609                     // line comments starting with "///" or "//!" are doc-comments
610                     let doc_comment = (self.ch_is('/') && !self.nextch_is('/')) || self.ch_is('!');
611                     let start_bpos = self.pos - BytePos(2);
612
613                     while !self.is_eof() {
614                         match self.ch.unwrap() {
615                             '\n' => break,
616                             '\r' => {
617                                 if self.nextch_is('\n') {
618                                     // CRLF
619                                     break;
620                                 } else if doc_comment {
621                                     self.err_span_(self.pos,
622                                                    self.next_pos,
623                                                    "bare CR not allowed in doc-comment");
624                                 }
625                             }
626                             _ => (),
627                         }
628                         self.bump();
629                     }
630
631                     let tok = if doc_comment {
632                         self.with_str_from(start_bpos, |string| {
633                             token::DocComment(Symbol::intern(string))
634                         })
635                     } else {
636                         token::Comment
637                     };
638                     Some(TokenAndSpan { tok, sp: self.mk_sp(start_bpos, self.pos) })
639                 }
640                 Some('*') => {
641                     self.bump();
642                     self.bump();
643                     self.scan_block_comment()
644                 }
645                 _ => None,
646             }
647         } else if self.ch_is('#') {
648             if self.nextch_is('!') {
649
650                 // Parse an inner attribute.
651                 if self.nextnextch_is('[') {
652                     return None;
653                 }
654
655                 let is_beginning_of_file = self.pos == self.source_file.start_pos;
656                 if is_beginning_of_file {
657                     debug!("Skipping a shebang");
658                     let start = self.pos;
659                     while !self.ch_is('\n') && !self.is_eof() {
660                         self.bump();
661                     }
662                     return Some(TokenAndSpan {
663                         tok: token::Shebang(self.name_from(start)),
664                         sp: self.mk_sp(start, self.pos),
665                     });
666                 }
667             }
668             None
669         } else {
670             None
671         }
672     }
673
674     /// If there is whitespace, shebang, or a comment, scan it. Otherwise,
675     /// return `None`.
676     fn scan_whitespace_or_comment(&mut self) -> Option<TokenAndSpan> {
677         match self.ch.unwrap_or('\0') {
678             // # to handle shebang at start of file -- this is the entry point
679             // for skipping over all "junk"
680             '/' | '#' => {
681                 let c = self.scan_comment();
682                 debug!("scanning a comment {:?}", c);
683                 c
684             },
685             c if is_pattern_whitespace(Some(c)) => {
686                 let start_bpos = self.pos;
687                 while is_pattern_whitespace(self.ch) {
688                     self.bump();
689                 }
690                 let c = Some(TokenAndSpan {
691                     tok: token::Whitespace,
692                     sp: self.mk_sp(start_bpos, self.pos),
693                 });
694                 debug!("scanning whitespace: {:?}", c);
695                 c
696             }
697             _ => None,
698         }
699     }
700
701     /// Might return a sugared-doc-attr
702     fn scan_block_comment(&mut self) -> Option<TokenAndSpan> {
703         // block comments starting with "/**" or "/*!" are doc-comments
704         let is_doc_comment = self.ch_is('*') || self.ch_is('!');
705         let start_bpos = self.pos - BytePos(2);
706
707         let mut level: isize = 1;
708         let mut has_cr = false;
709         while level > 0 {
710             if self.is_eof() {
711                 let msg = if is_doc_comment {
712                     "unterminated block doc-comment"
713                 } else {
714                     "unterminated block comment"
715                 };
716                 let last_bpos = self.pos;
717                 self.fatal_span_(start_bpos, last_bpos, msg).raise();
718             }
719             let n = self.ch.unwrap();
720             match n {
721                 '/' if self.nextch_is('*') => {
722                     level += 1;
723                     self.bump();
724                 }
725                 '*' if self.nextch_is('/') => {
726                     level -= 1;
727                     self.bump();
728                 }
729                 '\r' => {
730                     has_cr = true;
731                 }
732                 _ => (),
733             }
734             self.bump();
735         }
736
737         self.with_str_from(start_bpos, |string| {
738             // but comments with only "*"s between two "/"s are not
739             let tok = if is_block_doc_comment(string) {
740                 let string = if has_cr {
741                     self.translate_crlf(start_bpos,
742                                         string,
743                                         "bare CR not allowed in block doc-comment")
744                 } else {
745                     string.into()
746                 };
747                 token::DocComment(Symbol::intern(&string[..]))
748             } else {
749                 token::Comment
750             };
751
752             Some(TokenAndSpan {
753                 tok,
754                 sp: self.mk_sp(start_bpos, self.pos),
755             })
756         })
757     }
758
759     /// Scan through any digits (base `scan_radix`) or underscores,
760     /// and return how many digits there were.
761     ///
762     /// `real_radix` represents the true radix of the number we're
763     /// interested in, and errors will be emitted for any digits
764     /// between `real_radix` and `scan_radix`.
765     fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
766         assert!(real_radix <= scan_radix);
767         let mut len = 0;
768
769         loop {
770             let c = self.ch;
771             if c == Some('_') {
772                 debug!("skipping a _");
773                 self.bump();
774                 continue;
775             }
776             match c.and_then(|cc| cc.to_digit(scan_radix)) {
777                 Some(_) => {
778                     debug!("{:?} in scan_digits", c);
779                     // check that the hypothetical digit is actually
780                     // in range for the true radix
781                     if c.unwrap().to_digit(real_radix).is_none() {
782                         self.err_span_(self.pos,
783                                        self.next_pos,
784                                        &format!("invalid digit for a base {} literal", real_radix));
785                     }
786                     len += 1;
787                     self.bump();
788                 }
789                 _ => return len,
790             }
791         }
792     }
793
794     /// Lex a LIT_INTEGER or a LIT_FLOAT
795     fn scan_number(&mut self, c: char) -> token::Lit {
796         let mut base = 10;
797         let start_bpos = self.pos;
798         self.bump();
799
800         let num_digits = if c == '0' {
801             match self.ch.unwrap_or('\0') {
802                 'b' => {
803                     self.bump();
804                     base = 2;
805                     self.scan_digits(2, 10)
806                 }
807                 'o' => {
808                     self.bump();
809                     base = 8;
810                     self.scan_digits(8, 10)
811                 }
812                 'x' => {
813                     self.bump();
814                     base = 16;
815                     self.scan_digits(16, 16)
816                 }
817                 '0'..='9' | '_' | '.' | 'e' | 'E' => {
818                     self.scan_digits(10, 10) + 1
819                 }
820                 _ => {
821                     // just a 0
822                     return token::Integer(self.name_from(start_bpos));
823                 }
824             }
825         } else if c.is_digit(10) {
826             self.scan_digits(10, 10) + 1
827         } else {
828             0
829         };
830
831         if num_digits == 0 {
832             self.err_span_(start_bpos, self.pos, "no valid digits found for number");
833
834             return token::Integer(Symbol::intern("0"));
835         }
836
837         // might be a float, but don't be greedy if this is actually an
838         // integer literal followed by field/method access or a range pattern
839         // (`0..2` and `12.foo()`)
840         if self.ch_is('.') && !self.nextch_is('.') &&
841            !ident_start(self.nextch()) {
842             // might have stuff after the ., and if it does, it needs to start
843             // with a number
844             self.bump();
845             if self.ch.unwrap_or('\0').is_digit(10) {
846                 self.scan_digits(10, 10);
847                 self.scan_float_exponent();
848             }
849             let pos = self.pos;
850             self.check_float_base(start_bpos, pos, base);
851
852             token::Float(self.name_from(start_bpos))
853         } else {
854             // it might be a float if it has an exponent
855             if self.ch_is('e') || self.ch_is('E') {
856                 self.scan_float_exponent();
857                 let pos = self.pos;
858                 self.check_float_base(start_bpos, pos, base);
859                 return token::Float(self.name_from(start_bpos));
860             }
861             // but we certainly have an integer!
862             token::Integer(self.name_from(start_bpos))
863         }
864     }
865
866     /// Scan over `n_digits` hex digits, stopping at `delim`, reporting an
867     /// error if too many or too few digits are encountered.
868     fn scan_hex_digits(&mut self, n_digits: usize, delim: char, below_0x7f_only: bool) -> bool {
869         debug!("scanning {} digits until {:?}", n_digits, delim);
870         let start_bpos = self.pos;
871         let mut accum_int = 0;
872
873         let mut valid = true;
874         for _ in 0..n_digits {
875             if self.is_eof() {
876                 let last_bpos = self.pos;
877                 self.fatal_span_(start_bpos,
878                                  last_bpos,
879                                  "unterminated numeric character escape").raise();
880             }
881             if self.ch_is(delim) {
882                 let last_bpos = self.pos;
883                 self.err_span_(start_bpos,
884                                last_bpos,
885                                "numeric character escape is too short");
886                 valid = false;
887                 break;
888             }
889             let c = self.ch.unwrap_or('\x00');
890             accum_int *= 16;
891             accum_int += c.to_digit(16).unwrap_or_else(|| {
892                 self.err_span_char(self.pos,
893                                    self.next_pos,
894                                    "invalid character in numeric character escape",
895                                    c);
896
897                 valid = false;
898                 0
899             });
900             self.bump();
901         }
902
903         if below_0x7f_only && accum_int >= 0x80 {
904             self.err_span_(start_bpos,
905                            self.pos,
906                            "this form of character escape may only be used with characters in \
907                             the range [\\x00-\\x7f]");
908             valid = false;
909         }
910
911         match char::from_u32(accum_int) {
912             Some(_) => valid,
913             None => {
914                 let last_bpos = self.pos;
915                 self.err_span_(start_bpos, last_bpos, "invalid numeric character escape");
916                 false
917             }
918         }
919     }
920
921     /// Scan for a single (possibly escaped) byte or char
922     /// in a byte, (non-raw) byte string, char, or (non-raw) string literal.
923     /// `start` is the position of `first_source_char`, which is already consumed.
924     ///
925     /// Returns `true` if there was a valid char/byte.
926     fn scan_char_or_byte(&mut self,
927                          start: BytePos,
928                          first_source_char: char,
929                          ascii_only: bool,
930                          delim: char)
931                          -> bool
932     {
933         match first_source_char {
934             '\\' => {
935                 // '\X' for some X must be a character constant:
936                 let escaped = self.ch;
937                 let escaped_pos = self.pos;
938                 self.bump();
939                 match escaped {
940                     None => {}  // EOF here is an error that will be checked later.
941                     Some(e) => {
942                         return match e {
943                             'n' | 'r' | 't' | '\\' | '\'' | '"' | '0' => true,
944                             'x' => self.scan_byte_escape(delim, !ascii_only),
945                             'u' => {
946                                 let valid = if self.ch_is('{') {
947                                     self.scan_unicode_escape(delim) && !ascii_only
948                                 } else {
949                                     let span = self.mk_sp(start, self.pos);
950                                     let mut suggestion = "\\u{".to_owned();
951                                     let msg = "incorrect unicode escape sequence";
952                                     let mut err = self.sess.span_diagnostic.struct_span_err(
953                                         span,
954                                         msg,
955                                     );
956                                     let mut i = 0;
957                                     while let (Some(ch), true) = (self.ch, i < 6) {
958                                         if ch.is_digit(16) {
959                                             suggestion.push(ch);
960                                             self.bump();
961                                             i += 1;
962                                         } else {
963                                             break;
964                                         }
965                                     }
966                                     if i != 0 {
967                                         suggestion.push('}');
968                                         err.span_suggestion(
969                                             self.mk_sp(start, self.pos),
970                                             "format of unicode escape sequences uses braces",
971                                             suggestion,
972                                             Applicability::MaybeIncorrect,
973                                         );
974                                     } else {
975                                         err.span_label(span, msg);
976                                         err.help(
977                                             "format of unicode escape sequences is `\\u{...}`",
978                                         );
979                                     }
980                                     err.emit();
981                                     false
982                                 };
983                                 if ascii_only {
984                                     self.err_span_(start,
985                                                    self.pos,
986                                                    "unicode escape sequences cannot be used as a \
987                                                     byte or in a byte string");
988                                 }
989                                 valid
990
991                             }
992                             '\n' if delim == '"' => {
993                                 self.consume_whitespace();
994                                 true
995                             }
996                             '\r' if delim == '"' && self.ch_is('\n') => {
997                                 self.consume_whitespace();
998                                 true
999                             }
1000                             c => {
1001                                 let pos = self.pos;
1002                                 let msg = if ascii_only {
1003                                     "unknown byte escape"
1004                                 } else {
1005                                     "unknown character escape"
1006                                 };
1007                                 let mut err = self.struct_err_span_char(escaped_pos, pos, msg, c);
1008                                 err.span_label(self.mk_sp(escaped_pos, pos), msg);
1009                                 if e == '\r' {
1010                                     err.help(
1011                                         "this is an isolated carriage return; consider checking \
1012                                          your editor and version control settings",
1013                                     );
1014                                 }
1015                                 if (e == '{' || e == '}') && !ascii_only {
1016                                     err.help(
1017                                         "if used in a formatting string, curly braces are escaped \
1018                                          with `{{` and `}}`",
1019                                     );
1020                                 }
1021                                 err.emit();
1022                                 false
1023                             }
1024                         }
1025                     }
1026                 }
1027             }
1028             '\t' | '\n' | '\r' | '\'' if delim == '\'' => {
1029                 let pos = self.pos;
1030                 self.err_span_char(start,
1031                                    pos,
1032                                    if ascii_only {
1033                                        "byte constant must be escaped"
1034                                    } else {
1035                                        "character constant must be escaped"
1036                                    },
1037                                    first_source_char);
1038                 return false;
1039             }
1040             '\r' => {
1041                 if self.ch_is('\n') {
1042                     self.bump();
1043                     return true;
1044                 } else {
1045                     self.err_span_(start,
1046                                    self.pos,
1047                                    "bare CR not allowed in string, use \\r instead");
1048                     return false;
1049                 }
1050             }
1051             _ => {
1052                 if ascii_only && first_source_char > '\x7F' {
1053                     let pos = self.pos;
1054                     self.err_span_(start,
1055                                    pos,
1056                                    "byte constant must be ASCII. Use a \\xHH escape for a \
1057                                     non-ASCII byte");
1058                     return false;
1059                 }
1060             }
1061         }
1062         true
1063     }
1064
1065     /// Scan over a `\u{...}` escape
1066     ///
1067     /// At this point, we have already seen the `\` and the `u`, the `{` is the current character.
1068     /// We will read a hex number (with `_` separators), with 1 to 6 actual digits,
1069     /// and pass over the `}`.
1070     fn scan_unicode_escape(&mut self, delim: char) -> bool {
1071         self.bump(); // past the {
1072         let start_bpos = self.pos;
1073         let mut valid = true;
1074
1075         if let Some('_') = self.ch {
1076             // disallow leading `_`
1077             self.err_span_(self.pos,
1078                            self.next_pos,
1079                            "invalid start of unicode escape");
1080             valid = false;
1081         }
1082
1083         let count = self.scan_digits(16, 16);
1084
1085         if count > 6 {
1086             self.err_span_(start_bpos,
1087                            self.pos,
1088                            "overlong unicode escape (must have at most 6 hex digits)");
1089             valid = false;
1090         }
1091
1092         loop {
1093             match self.ch {
1094                 Some('}') => {
1095                     if valid && count == 0 {
1096                         self.err_span_(start_bpos,
1097                                        self.pos,
1098                                        "empty unicode escape (must have at least 1 hex digit)");
1099                         valid = false;
1100                     }
1101                     self.bump(); // past the ending `}`
1102                     break;
1103                 },
1104                 Some(c) => {
1105                     if c == delim {
1106                         self.err_span_(self.pos,
1107                                        self.pos,
1108                                        "unterminated unicode escape (needed a `}`)");
1109                         valid = false;
1110                         break;
1111                     } else if valid {
1112                         self.err_span_char(start_bpos,
1113                                            self.pos,
1114                                            "invalid character in unicode escape",
1115                                            c);
1116                         valid = false;
1117                     }
1118                 },
1119                 None => {
1120                     self.fatal_span_(start_bpos,
1121                                      self.pos,
1122                                      "unterminated unicode escape (found EOF)").raise();
1123                 }
1124             }
1125             self.bump();
1126         }
1127
1128         valid
1129     }
1130
1131     /// Scan over a float exponent.
1132     fn scan_float_exponent(&mut self) {
1133         if self.ch_is('e') || self.ch_is('E') {
1134             self.bump();
1135
1136             if self.ch_is('-') || self.ch_is('+') {
1137                 self.bump();
1138             }
1139
1140             if self.scan_digits(10, 10) == 0 {
1141                 let mut err = self.struct_span_fatal(
1142                     self.pos, self.next_pos,
1143                     "expected at least one digit in exponent"
1144                 );
1145                 if let Some(ch) = self.ch {
1146                     // check for e.g., Unicode minus '−' (Issue #49746)
1147                     if unicode_chars::check_for_substitution(self, ch, &mut err) {
1148                         self.bump();
1149                         self.scan_digits(10, 10);
1150                     }
1151                 }
1152                 err.emit();
1153             }
1154         }
1155     }
1156
1157     /// Checks that a base is valid for a floating literal, emitting a nice
1158     /// error if it isn't.
1159     fn check_float_base(&mut self, start_bpos: BytePos, last_bpos: BytePos, base: usize) {
1160         match base {
1161             16 => {
1162                 self.err_span_(start_bpos,
1163                                last_bpos,
1164                                "hexadecimal float literal is not supported")
1165             }
1166             8 => {
1167                 self.err_span_(start_bpos,
1168                                last_bpos,
1169                                "octal float literal is not supported")
1170             }
1171             2 => {
1172                 self.err_span_(start_bpos,
1173                                last_bpos,
1174                                "binary float literal is not supported")
1175             }
1176             _ => (),
1177         }
1178     }
1179
1180     fn binop(&mut self, op: token::BinOpToken) -> token::Token {
1181         self.bump();
1182         if self.ch_is('=') {
1183             self.bump();
1184             token::BinOpEq(op)
1185         } else {
1186             token::BinOp(op)
1187         }
1188     }
1189
1190     /// Returns the next token from the string, advances the input past that
1191     /// token, and updates the interner
1192     fn next_token_inner(&mut self) -> Result<token::Token, ()> {
1193         let c = self.ch;
1194
1195         if ident_start(c) {
1196             let (is_ident_start, is_raw_ident) =
1197                 match (c.unwrap(), self.nextch(), self.nextnextch()) {
1198                     // r# followed by an identifier starter is a raw identifier.
1199                     // This is an exception to the r# case below.
1200                     ('r', Some('#'), x) if ident_start(x) => (true, true),
1201                     // r as in r" or r#" is part of a raw string literal.
1202                     // b as in b' is part of a byte literal.
1203                     // They are not identifiers, and are handled further down.
1204                     ('r', Some('"'), _) |
1205                     ('r', Some('#'), _) |
1206                     ('b', Some('"'), _) |
1207                     ('b', Some('\''), _) |
1208                     ('b', Some('r'), Some('"')) |
1209                     ('b', Some('r'), Some('#')) => (false, false),
1210                     _ => (true, false),
1211                 };
1212
1213             if is_ident_start {
1214                 let raw_start = self.pos;
1215                 if is_raw_ident {
1216                     // Consume the 'r#' characters.
1217                     self.bump();
1218                     self.bump();
1219                 }
1220
1221                 let start = self.pos;
1222                 self.bump();
1223
1224                 while ident_continue(self.ch) {
1225                     self.bump();
1226                 }
1227
1228                 return Ok(self.with_str_from(start, |string| {
1229                     // FIXME: perform NFKC normalization here. (Issue #2253)
1230                     let ident = self.mk_ident(string);
1231
1232                     if is_raw_ident {
1233                         let span = self.mk_sp(raw_start, self.pos);
1234                         if !ident.can_be_raw() {
1235                             self.err_span(span, &format!("`{}` cannot be a raw identifier", ident));
1236                         }
1237                         self.sess.raw_identifier_spans.borrow_mut().push(span);
1238                     }
1239
1240                     token::Ident(ident, is_raw_ident)
1241                 }));
1242             }
1243         }
1244
1245         if is_dec_digit(c) {
1246             let num = self.scan_number(c.unwrap());
1247             let suffix = self.scan_optional_raw_name();
1248             debug!("next_token_inner: scanned number {:?}, {:?}", num, suffix);
1249             return Ok(token::Literal(num, suffix));
1250         }
1251
1252         match c.expect("next_token_inner called at EOF") {
1253             // One-byte tokens.
1254             ';' => {
1255                 self.bump();
1256                 Ok(token::Semi)
1257             }
1258             ',' => {
1259                 self.bump();
1260                 Ok(token::Comma)
1261             }
1262             '.' => {
1263                 self.bump();
1264                 if self.ch_is('.') {
1265                     self.bump();
1266                     if self.ch_is('.') {
1267                         self.bump();
1268                         Ok(token::DotDotDot)
1269                     } else if self.ch_is('=') {
1270                         self.bump();
1271                         Ok(token::DotDotEq)
1272                     } else {
1273                         Ok(token::DotDot)
1274                     }
1275                 } else {
1276                     Ok(token::Dot)
1277                 }
1278             }
1279             '(' => {
1280                 self.bump();
1281                 Ok(token::OpenDelim(token::Paren))
1282             }
1283             ')' => {
1284                 self.bump();
1285                 Ok(token::CloseDelim(token::Paren))
1286             }
1287             '{' => {
1288                 self.bump();
1289                 Ok(token::OpenDelim(token::Brace))
1290             }
1291             '}' => {
1292                 self.bump();
1293                 Ok(token::CloseDelim(token::Brace))
1294             }
1295             '[' => {
1296                 self.bump();
1297                 Ok(token::OpenDelim(token::Bracket))
1298             }
1299             ']' => {
1300                 self.bump();
1301                 Ok(token::CloseDelim(token::Bracket))
1302             }
1303             '@' => {
1304                 self.bump();
1305                 Ok(token::At)
1306             }
1307             '#' => {
1308                 self.bump();
1309                 Ok(token::Pound)
1310             }
1311             '~' => {
1312                 self.bump();
1313                 Ok(token::Tilde)
1314             }
1315             '?' => {
1316                 self.bump();
1317                 Ok(token::Question)
1318             }
1319             ':' => {
1320                 self.bump();
1321                 if self.ch_is(':') {
1322                     self.bump();
1323                     Ok(token::ModSep)
1324                 } else {
1325                     Ok(token::Colon)
1326                 }
1327             }
1328
1329             '$' => {
1330                 self.bump();
1331                 Ok(token::Dollar)
1332             }
1333
1334             // Multi-byte tokens.
1335             '=' => {
1336                 self.bump();
1337                 if self.ch_is('=') {
1338                     self.bump();
1339                     Ok(token::EqEq)
1340                 } else if self.ch_is('>') {
1341                     self.bump();
1342                     Ok(token::FatArrow)
1343                 } else {
1344                     Ok(token::Eq)
1345                 }
1346             }
1347             '!' => {
1348                 self.bump();
1349                 if self.ch_is('=') {
1350                     self.bump();
1351                     Ok(token::Ne)
1352                 } else {
1353                     Ok(token::Not)
1354                 }
1355             }
1356             '<' => {
1357                 self.bump();
1358                 match self.ch.unwrap_or('\x00') {
1359                     '=' => {
1360                         self.bump();
1361                         Ok(token::Le)
1362                     }
1363                     '<' => {
1364                         Ok(self.binop(token::Shl))
1365                     }
1366                     '-' => {
1367                         self.bump();
1368                         Ok(token::LArrow)
1369                     }
1370                     _ => {
1371                         Ok(token::Lt)
1372                     }
1373                 }
1374             }
1375             '>' => {
1376                 self.bump();
1377                 match self.ch.unwrap_or('\x00') {
1378                     '=' => {
1379                         self.bump();
1380                         Ok(token::Ge)
1381                     }
1382                     '>' => {
1383                         Ok(self.binop(token::Shr))
1384                     }
1385                     _ => {
1386                         Ok(token::Gt)
1387                     }
1388                 }
1389             }
1390             '\'' => {
1391                 // Either a character constant 'a' OR a lifetime name 'abc
1392                 let start_with_quote = self.pos;
1393                 self.bump();
1394                 let start = self.pos;
1395
1396                 // the eof will be picked up by the final `'` check below
1397                 let c2 = self.ch.unwrap_or('\x00');
1398                 self.bump();
1399
1400                 // If the character is an ident start not followed by another single
1401                 // quote, then this is a lifetime name:
1402                 if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') {
1403                     while ident_continue(self.ch) {
1404                         self.bump();
1405                     }
1406                     // lifetimes shouldn't end with a single quote
1407                     // if we find one, then this is an invalid character literal
1408                     if self.ch_is('\'') {
1409                         self.err_span_(
1410                             start_with_quote,
1411                             self.next_pos,
1412                             "character literal may only contain one codepoint");
1413                         self.bump();
1414                         return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
1415
1416                     }
1417
1418                     // Include the leading `'` in the real identifier, for macro
1419                     // expansion purposes. See #12512 for the gory details of why
1420                     // this is necessary.
1421                     let ident = self.with_str_from(start_with_quote, |lifetime_name| {
1422                         self.mk_ident(lifetime_name)
1423                     });
1424
1425                     if c2.is_numeric() {
1426                         // this is a recovered lifetime written `'1`, error but accept it
1427                         self.err_span_(
1428                             start_with_quote,
1429                             self.pos,
1430                             "lifetimes cannot start with a number",
1431                         );
1432                     }
1433
1434                     return Ok(token::Lifetime(ident));
1435                 }
1436
1437                 let valid = self.scan_char_or_byte(start, c2, /* ascii_only */ false, '\'');
1438
1439                 if !self.ch_is('\'') {
1440                     let pos = self.pos;
1441
1442                     loop {
1443                         self.bump();
1444                         if self.ch_is('\'') {
1445                             let start = self.src_index(start);
1446                             let end = self.src_index(self.pos);
1447                             self.bump();
1448                             let span = self.mk_sp(start_with_quote, self.pos);
1449                             self.sess.span_diagnostic
1450                                 .struct_span_err(span,
1451                                                  "character literal may only contain one codepoint")
1452                                 .span_suggestion(
1453                                     span,
1454                                     "if you meant to write a `str` literal, use double quotes",
1455                                     format!("\"{}\"", &self.src[start..end]),
1456                                     Applicability::MachineApplicable
1457                                 ).emit();
1458                             return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
1459                         }
1460                         if self.ch_is('\n') || self.is_eof() || self.ch_is('/') {
1461                             // Only attempt to infer single line string literals. If we encounter
1462                             // a slash, bail out in order to avoid nonsensical suggestion when
1463                             // involving comments.
1464                             break;
1465                         }
1466                     }
1467
1468                     self.fatal_span_verbose(start_with_quote, pos,
1469                         String::from("character literal may only contain one codepoint")).raise();
1470                 }
1471
1472                 let id = if valid {
1473                     self.name_from(start)
1474                 } else {
1475                     Symbol::intern("0")
1476                 };
1477
1478                 self.bump(); // advance ch past token
1479                 let suffix = self.scan_optional_raw_name();
1480
1481                 Ok(token::Literal(token::Char(id), suffix))
1482             }
1483             'b' => {
1484                 self.bump();
1485                 let lit = match self.ch {
1486                     Some('\'') => self.scan_byte(),
1487                     Some('"') => self.scan_byte_string(),
1488                     Some('r') => self.scan_raw_byte_string(),
1489                     _ => unreachable!(),  // Should have been a token::Ident above.
1490                 };
1491                 let suffix = self.scan_optional_raw_name();
1492
1493                 Ok(token::Literal(lit, suffix))
1494             }
1495             '"' => {
1496                 let start_bpos = self.pos;
1497                 let mut valid = true;
1498                 self.bump();
1499
1500                 while !self.ch_is('"') {
1501                     if self.is_eof() {
1502                         let last_bpos = self.pos;
1503                         self.fatal_span_(start_bpos,
1504                                          last_bpos,
1505                                          "unterminated double quote string").raise();
1506                     }
1507
1508                     let ch_start = self.pos;
1509                     let ch = self.ch.unwrap();
1510                     self.bump();
1511                     valid &= self.scan_char_or_byte(ch_start, ch, /* ascii_only */ false, '"');
1512                 }
1513                 // adjust for the ASCII " at the start of the literal
1514                 let id = if valid {
1515                     self.name_from(start_bpos + BytePos(1))
1516                 } else {
1517                     Symbol::intern("??")
1518                 };
1519                 self.bump();
1520                 let suffix = self.scan_optional_raw_name();
1521
1522                 Ok(token::Literal(token::Str_(id), suffix))
1523             }
1524             'r' => {
1525                 let start_bpos = self.pos;
1526                 self.bump();
1527                 let mut hash_count: u16 = 0;
1528                 while self.ch_is('#') {
1529                     if hash_count == 65535 {
1530                         let bpos = self.next_pos;
1531                         self.fatal_span_(start_bpos,
1532                                          bpos,
1533                                          "too many `#` symbols: raw strings may be \
1534                                          delimited by up to 65535 `#` symbols").raise();
1535                     }
1536                     self.bump();
1537                     hash_count += 1;
1538                 }
1539
1540                 if self.is_eof() {
1541                     self.fail_unterminated_raw_string(start_bpos, hash_count);
1542                 } else if !self.ch_is('"') {
1543                     let last_bpos = self.pos;
1544                     let curr_char = self.ch.unwrap();
1545                     self.fatal_span_char(start_bpos,
1546                                          last_bpos,
1547                                          "found invalid character; only `#` is allowed \
1548                                          in raw string delimitation",
1549                                          curr_char).raise();
1550                 }
1551                 self.bump();
1552                 let content_start_bpos = self.pos;
1553                 let mut content_end_bpos;
1554                 let mut valid = true;
1555                 'outer: loop {
1556                     if self.is_eof() {
1557                         self.fail_unterminated_raw_string(start_bpos, hash_count);
1558                     }
1559                     // if self.ch_is('"') {
1560                     // content_end_bpos = self.pos;
1561                     // for _ in 0..hash_count {
1562                     // self.bump();
1563                     // if !self.ch_is('#') {
1564                     // continue 'outer;
1565                     let c = self.ch.unwrap();
1566                     match c {
1567                         '"' => {
1568                             content_end_bpos = self.pos;
1569                             for _ in 0..hash_count {
1570                                 self.bump();
1571                                 if !self.ch_is('#') {
1572                                     continue 'outer;
1573                                 }
1574                             }
1575                             break;
1576                         }
1577                         '\r' => {
1578                             if !self.nextch_is('\n') {
1579                                 let last_bpos = self.pos;
1580                                 self.err_span_(start_bpos,
1581                                                last_bpos,
1582                                                "bare CR not allowed in raw string, use \\r \
1583                                                 instead");
1584                                 valid = false;
1585                             }
1586                         }
1587                         _ => (),
1588                     }
1589                     self.bump();
1590                 }
1591
1592                 self.bump();
1593                 let id = if valid {
1594                     self.name_from_to(content_start_bpos, content_end_bpos)
1595                 } else {
1596                     Symbol::intern("??")
1597                 };
1598                 let suffix = self.scan_optional_raw_name();
1599
1600                 Ok(token::Literal(token::StrRaw(id, hash_count), suffix))
1601             }
1602             '-' => {
1603                 if self.nextch_is('>') {
1604                     self.bump();
1605                     self.bump();
1606                     Ok(token::RArrow)
1607                 } else {
1608                     Ok(self.binop(token::Minus))
1609                 }
1610             }
1611             '&' => {
1612                 if self.nextch_is('&') {
1613                     self.bump();
1614                     self.bump();
1615                     Ok(token::AndAnd)
1616                 } else {
1617                     Ok(self.binop(token::And))
1618                 }
1619             }
1620             '|' => {
1621                 match self.nextch() {
1622                     Some('|') => {
1623                         self.bump();
1624                         self.bump();
1625                         Ok(token::OrOr)
1626                     }
1627                     _ => {
1628                         Ok(self.binop(token::Or))
1629                     }
1630                 }
1631             }
1632             '+' => {
1633                 Ok(self.binop(token::Plus))
1634             }
1635             '*' => {
1636                 Ok(self.binop(token::Star))
1637             }
1638             '/' => {
1639                 Ok(self.binop(token::Slash))
1640             }
1641             '^' => {
1642                 Ok(self.binop(token::Caret))
1643             }
1644             '%' => {
1645                 Ok(self.binop(token::Percent))
1646             }
1647             c => {
1648                 let last_bpos = self.pos;
1649                 let bpos = self.next_pos;
1650                 let mut err = self.struct_fatal_span_char(last_bpos,
1651                                                           bpos,
1652                                                           "unknown start of token",
1653                                                           c);
1654                 unicode_chars::check_for_substitution(self, c, &mut err);
1655                 self.fatal_errs.push(err);
1656
1657                 Err(())
1658             }
1659         }
1660     }
1661
1662     fn consume_whitespace(&mut self) {
1663         while is_pattern_whitespace(self.ch) && !self.is_eof() {
1664             self.bump();
1665         }
1666     }
1667
1668     fn read_to_eol(&mut self) -> String {
1669         let mut val = String::new();
1670         while !self.ch_is('\n') && !self.is_eof() {
1671             val.push(self.ch.unwrap());
1672             self.bump();
1673         }
1674
1675         if self.ch_is('\n') {
1676             self.bump();
1677         }
1678
1679         val
1680     }
1681
1682     fn read_one_line_comment(&mut self) -> String {
1683         let val = self.read_to_eol();
1684         assert!((val.as_bytes()[0] == b'/' && val.as_bytes()[1] == b'/') ||
1685                 (val.as_bytes()[0] == b'#' && val.as_bytes()[1] == b'!'));
1686         val
1687     }
1688
1689     fn consume_non_eol_whitespace(&mut self) {
1690         while is_pattern_whitespace(self.ch) && !self.ch_is('\n') && !self.is_eof() {
1691             self.bump();
1692         }
1693     }
1694
1695     fn peeking_at_comment(&self) -> bool {
1696         (self.ch_is('/') && self.nextch_is('/')) || (self.ch_is('/') && self.nextch_is('*')) ||
1697         // consider shebangs comments, but not inner attributes
1698         (self.ch_is('#') && self.nextch_is('!') && !self.nextnextch_is('['))
1699     }
1700
1701     fn scan_byte(&mut self) -> token::Lit {
1702         self.bump();
1703         let start = self.pos;
1704
1705         // the eof will be picked up by the final `'` check below
1706         let c2 = self.ch.unwrap_or('\x00');
1707         self.bump();
1708
1709         let valid = self.scan_char_or_byte(start,
1710                                            c2,
1711                                            // ascii_only =
1712                                            true,
1713                                            '\'');
1714         if !self.ch_is('\'') {
1715             // Byte offsetting here is okay because the
1716             // character before position `start` are an
1717             // ascii single quote and ascii 'b'.
1718             let pos = self.pos;
1719             self.fatal_span_verbose(start - BytePos(2),
1720                                     pos,
1721                                     "unterminated byte constant".to_string()).raise();
1722         }
1723
1724         let id = if valid {
1725             self.name_from(start)
1726         } else {
1727             Symbol::intern("?")
1728         };
1729         self.bump(); // advance ch past token
1730
1731         token::Byte(id)
1732     }
1733
1734     #[inline]
1735     fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool {
1736         self.scan_hex_digits(2, delim, below_0x7f_only)
1737     }
1738
1739     fn scan_byte_string(&mut self) -> token::Lit {
1740         self.bump();
1741         let start = self.pos;
1742         let mut valid = true;
1743
1744         while !self.ch_is('"') {
1745             if self.is_eof() {
1746                 let pos = self.pos;
1747                 self.fatal_span_(start, pos, "unterminated double quote byte string").raise();
1748             }
1749
1750             let ch_start = self.pos;
1751             let ch = self.ch.unwrap();
1752             self.bump();
1753             valid &= self.scan_char_or_byte(ch_start,
1754                                             ch,
1755                                             // ascii_only =
1756                                             true,
1757                                             '"');
1758         }
1759
1760         let id = if valid {
1761             self.name_from(start)
1762         } else {
1763             Symbol::intern("??")
1764         };
1765         self.bump();
1766
1767         token::ByteStr(id)
1768     }
1769
1770     fn scan_raw_byte_string(&mut self) -> token::Lit {
1771         let start_bpos = self.pos;
1772         self.bump();
1773         let mut hash_count = 0;
1774         while self.ch_is('#') {
1775             if hash_count == 65535 {
1776                 let bpos = self.next_pos;
1777                 self.fatal_span_(start_bpos,
1778                                  bpos,
1779                                  "too many `#` symbols: raw byte strings may be \
1780                                  delimited by up to 65535 `#` symbols").raise();
1781             }
1782             self.bump();
1783             hash_count += 1;
1784         }
1785
1786         if self.is_eof() {
1787             self.fail_unterminated_raw_string(start_bpos, hash_count);
1788         } else if !self.ch_is('"') {
1789             let pos = self.pos;
1790             let ch = self.ch.unwrap();
1791             self.fatal_span_char(start_bpos,
1792                                         pos,
1793                                         "found invalid character; only `#` is allowed in raw \
1794                                          string delimitation",
1795                                         ch).raise();
1796         }
1797         self.bump();
1798         let content_start_bpos = self.pos;
1799         let mut content_end_bpos;
1800         'outer: loop {
1801             match self.ch {
1802                 None => {
1803                     self.fail_unterminated_raw_string(start_bpos, hash_count);
1804                 }
1805                 Some('"') => {
1806                     content_end_bpos = self.pos;
1807                     for _ in 0..hash_count {
1808                         self.bump();
1809                         if !self.ch_is('#') {
1810                             continue 'outer;
1811                         }
1812                     }
1813                     break;
1814                 }
1815                 Some(c) => {
1816                     if c > '\x7F' {
1817                         let pos = self.pos;
1818                         self.err_span_char(pos, pos, "raw byte string must be ASCII", c);
1819                     }
1820                 }
1821             }
1822             self.bump();
1823         }
1824
1825         self.bump();
1826
1827         token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), hash_count)
1828     }
1829 }
1830
1831 // This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which
1832 // is guaranteed to be forward compatible. http://unicode.org/reports/tr31/#R3
1833 #[inline]
1834 crate fn is_pattern_whitespace(c: Option<char>) -> bool {
1835     c.map_or(false, Pattern_White_Space)
1836 }
1837
1838 #[inline]
1839 fn in_range(c: Option<char>, lo: char, hi: char) -> bool {
1840     c.map_or(false, |c| lo <= c && c <= hi)
1841 }
1842
1843 #[inline]
1844 fn is_dec_digit(c: Option<char>) -> bool {
1845     in_range(c, '0', '9')
1846 }
1847
1848 fn is_doc_comment(s: &str) -> bool {
1849     let res = (s.starts_with("///") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'/') ||
1850               s.starts_with("//!");
1851     debug!("is {:?} a doc comment? {}", s, res);
1852     res
1853 }
1854
1855 fn is_block_doc_comment(s: &str) -> bool {
1856     // Prevent `/**/` from being parsed as a doc comment
1857     let res = ((s.starts_with("/**") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'*') ||
1858                s.starts_with("/*!")) && s.len() >= 5;
1859     debug!("is {:?} a doc comment? {}", s, res);
1860     res
1861 }
1862
1863 /// Determine whether `c` is a valid start for an ident.
1864 fn ident_start(c: Option<char>) -> bool {
1865     let c = match c {
1866         Some(c) => c,
1867         None => return false,
1868     };
1869
1870     (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c > '\x7f' && c.is_xid_start())
1871 }
1872
1873 fn ident_continue(c: Option<char>) -> bool {
1874     let c = match c {
1875         Some(c) => c,
1876         None => return false,
1877     };
1878
1879     (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' ||
1880     (c > '\x7f' && c.is_xid_continue())
1881 }
1882
1883 #[inline]
1884 fn char_at(s: &str, byte: usize) -> char {
1885     s[byte..].chars().next().unwrap()
1886 }
1887
1888 #[cfg(test)]
1889 mod tests {
1890     use super::*;
1891
1892     use crate::ast::{Ident, CrateConfig};
1893     use crate::symbol::Symbol;
1894     use crate::source_map::{SourceMap, FilePathMapping};
1895     use crate::feature_gate::UnstableFeatures;
1896     use crate::parse::token;
1897     use crate::diagnostics::plugin::ErrorMap;
1898     use crate::with_globals;
1899     use std::io;
1900     use std::path::PathBuf;
1901     use syntax_pos::{BytePos, Span, NO_EXPANSION};
1902     use rustc_data_structures::fx::FxHashSet;
1903     use rustc_data_structures::sync::Lock;
1904
1905     fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
1906         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
1907                                                           Some(sm.clone()),
1908                                                           false,
1909                                                           false,
1910                                                           false);
1911         ParseSess {
1912             span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)),
1913             unstable_features: UnstableFeatures::from_environment(),
1914             config: CrateConfig::default(),
1915             included_mod_stack: Lock::new(Vec::new()),
1916             source_map: sm,
1917             missing_fragment_specifiers: Lock::new(FxHashSet::default()),
1918             raw_identifier_spans: Lock::new(Vec::new()),
1919             registered_diagnostics: Lock::new(ErrorMap::new()),
1920             buffered_lints: Lock::new(vec![]),
1921         }
1922     }
1923
1924     // open a string reader for the given string
1925     fn setup<'a>(sm: &SourceMap,
1926                  sess: &'a ParseSess,
1927                  teststr: String)
1928                  -> StringReader<'a> {
1929         let sf = sm.new_source_file(PathBuf::from(teststr.clone()).into(), teststr);
1930         StringReader::new(sess, sf, None)
1931     }
1932
1933     #[test]
1934     fn t1() {
1935         with_globals(|| {
1936             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
1937             let sh = mk_sess(sm.clone());
1938             let mut string_reader = setup(&sm,
1939                                         &sh,
1940                                         "/* my source file */ fn main() { println!(\"zebra\"); }\n"
1941                                             .to_string());
1942             let id = Ident::from_str("fn");
1943             assert_eq!(string_reader.next_token().tok, token::Comment);
1944             assert_eq!(string_reader.next_token().tok, token::Whitespace);
1945             let tok1 = string_reader.next_token();
1946             let tok2 = TokenAndSpan {
1947                 tok: token::Ident(id, false),
1948                 sp: Span::new(BytePos(21), BytePos(23), NO_EXPANSION),
1949             };
1950             assert_eq!(tok1.tok, tok2.tok);
1951             assert_eq!(tok1.sp, tok2.sp);
1952             assert_eq!(string_reader.next_token().tok, token::Whitespace);
1953             // the 'main' id is already read:
1954             assert_eq!(string_reader.pos.clone(), BytePos(28));
1955             // read another token:
1956             let tok3 = string_reader.next_token();
1957             let tok4 = TokenAndSpan {
1958                 tok: mk_ident("main"),
1959                 sp: Span::new(BytePos(24), BytePos(28), NO_EXPANSION),
1960             };
1961             assert_eq!(tok3.tok, tok4.tok);
1962             assert_eq!(tok3.sp, tok4.sp);
1963             // the lparen is already read:
1964             assert_eq!(string_reader.pos.clone(), BytePos(29))
1965         })
1966     }
1967
1968     // check that the given reader produces the desired stream
1969     // of tokens (stop checking after exhausting the expected vec)
1970     fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<token::Token>) {
1971         for expected_tok in &expected {
1972             assert_eq!(&string_reader.next_token().tok, expected_tok);
1973         }
1974     }
1975
1976     // make the identifier by looking up the string in the interner
1977     fn mk_ident(id: &str) -> token::Token {
1978         token::Token::from_ast_ident(Ident::from_str(id))
1979     }
1980
1981     #[test]
1982     fn doublecolonparsing() {
1983         with_globals(|| {
1984             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
1985             let sh = mk_sess(sm.clone());
1986             check_tokenization(setup(&sm, &sh, "a b".to_string()),
1987                             vec![mk_ident("a"), token::Whitespace, mk_ident("b")]);
1988         })
1989     }
1990
1991     #[test]
1992     fn dcparsing_2() {
1993         with_globals(|| {
1994             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
1995             let sh = mk_sess(sm.clone());
1996             check_tokenization(setup(&sm, &sh, "a::b".to_string()),
1997                             vec![mk_ident("a"), token::ModSep, mk_ident("b")]);
1998         })
1999     }
2000
2001     #[test]
2002     fn dcparsing_3() {
2003         with_globals(|| {
2004             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2005             let sh = mk_sess(sm.clone());
2006             check_tokenization(setup(&sm, &sh, "a ::b".to_string()),
2007                             vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]);
2008         })
2009     }
2010
2011     #[test]
2012     fn dcparsing_4() {
2013         with_globals(|| {
2014             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2015             let sh = mk_sess(sm.clone());
2016             check_tokenization(setup(&sm, &sh, "a:: b".to_string()),
2017                             vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]);
2018         })
2019     }
2020
2021     #[test]
2022     fn character_a() {
2023         with_globals(|| {
2024             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2025             let sh = mk_sess(sm.clone());
2026             assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token().tok,
2027                     token::Literal(token::Char(Symbol::intern("a")), None));
2028         })
2029     }
2030
2031     #[test]
2032     fn character_space() {
2033         with_globals(|| {
2034             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2035             let sh = mk_sess(sm.clone());
2036             assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token().tok,
2037                     token::Literal(token::Char(Symbol::intern(" ")), None));
2038         })
2039     }
2040
2041     #[test]
2042     fn character_escaped() {
2043         with_globals(|| {
2044             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2045             let sh = mk_sess(sm.clone());
2046             assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token().tok,
2047                     token::Literal(token::Char(Symbol::intern("\\n")), None));
2048         })
2049     }
2050
2051     #[test]
2052     fn lifetime_name() {
2053         with_globals(|| {
2054             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2055             let sh = mk_sess(sm.clone());
2056             assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token().tok,
2057                     token::Lifetime(Ident::from_str("'abc")));
2058         })
2059     }
2060
2061     #[test]
2062     fn raw_string() {
2063         with_globals(|| {
2064             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2065             let sh = mk_sess(sm.clone());
2066             assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string())
2067                         .next_token()
2068                         .tok,
2069                     token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None));
2070         })
2071     }
2072
2073     #[test]
2074     fn literal_suffixes() {
2075         with_globals(|| {
2076             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2077             let sh = mk_sess(sm.clone());
2078             macro_rules! test {
2079                 ($input: expr, $tok_type: ident, $tok_contents: expr) => {{
2080                     assert_eq!(setup(&sm, &sh, format!("{}suffix", $input)).next_token().tok,
2081                             token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
2082                                             Some(Symbol::intern("suffix"))));
2083                     // with a whitespace separator:
2084                     assert_eq!(setup(&sm, &sh, format!("{} suffix", $input)).next_token().tok,
2085                             token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
2086                                             None));
2087                 }}
2088             }
2089
2090             test!("'a'", Char, "a");
2091             test!("b'a'", Byte, "a");
2092             test!("\"a\"", Str_, "a");
2093             test!("b\"a\"", ByteStr, "a");
2094             test!("1234", Integer, "1234");
2095             test!("0b101", Integer, "0b101");
2096             test!("0xABC", Integer, "0xABC");
2097             test!("1.0", Float, "1.0");
2098             test!("1.0e10", Float, "1.0e10");
2099
2100             assert_eq!(setup(&sm, &sh, "2us".to_string()).next_token().tok,
2101                     token::Literal(token::Integer(Symbol::intern("2")),
2102                                     Some(Symbol::intern("us"))));
2103             assert_eq!(setup(&sm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok,
2104                     token::Literal(token::StrRaw(Symbol::intern("raw"), 3),
2105                                     Some(Symbol::intern("suffix"))));
2106             assert_eq!(setup(&sm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok,
2107                     token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3),
2108                                     Some(Symbol::intern("suffix"))));
2109         })
2110     }
2111
2112     #[test]
2113     fn line_doc_comments() {
2114         assert!(is_doc_comment("///"));
2115         assert!(is_doc_comment("/// blah"));
2116         assert!(!is_doc_comment("////"));
2117     }
2118
2119     #[test]
2120     fn nested_block_comments() {
2121         with_globals(|| {
2122             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2123             let sh = mk_sess(sm.clone());
2124             let mut lexer = setup(&sm, &sh, "/* /* */ */'a'".to_string());
2125             match lexer.next_token().tok {
2126                 token::Comment => {}
2127                 _ => panic!("expected a comment!"),
2128             }
2129             assert_eq!(lexer.next_token().tok,
2130                     token::Literal(token::Char(Symbol::intern("a")), None));
2131         })
2132     }
2133
2134     #[test]
2135     fn crlf_comments() {
2136         with_globals(|| {
2137             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
2138             let sh = mk_sess(sm.clone());
2139             let mut lexer = setup(&sm, &sh, "// test\r\n/// test\r\n".to_string());
2140             let comment = lexer.next_token();
2141             assert_eq!(comment.tok, token::Comment);
2142             assert_eq!((comment.sp.lo(), comment.sp.hi()), (BytePos(0), BytePos(7)));
2143             assert_eq!(lexer.next_token().tok, token::Whitespace);
2144             assert_eq!(lexer.next_token().tok,
2145                     token::DocComment(Symbol::intern("/// test")));
2146         })
2147     }
2148 }