]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/mod.rs
Auto merge of #56863 - arielb1:supertrait-self-4, r=nikomatsakis
[rust.git] / src / libsyntax / parse / mod.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The main parser interface
12
13 use rustc_data_structures::sync::{Lrc, Lock};
14 use ast::{self, CrateConfig, NodeId};
15 use early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
16 use source_map::{SourceMap, FilePathMapping};
17 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
18 use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
19 use feature_gate::UnstableFeatures;
20 use parse::parser::Parser;
21 use ptr::P;
22 use symbol::Symbol;
23 use tokenstream::{TokenStream, TokenTree};
24 use diagnostics::plugin::ErrorMap;
25
26 use rustc_data_structures::fx::FxHashSet;
27 use std::borrow::Cow;
28 use std::iter;
29 use std::path::{Path, PathBuf};
30 use std::str;
31
32 pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
33
34 #[macro_use]
35 pub mod parser;
36
37 pub mod lexer;
38 pub mod token;
39 pub mod attr;
40
41 pub mod classify;
42
43 /// Info about a parsing session.
44 pub struct ParseSess {
45     pub span_diagnostic: Handler,
46     pub unstable_features: UnstableFeatures,
47     pub config: CrateConfig,
48     pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
49     /// Places where raw identifiers were used. This is used for feature gating
50     /// raw identifiers
51     pub raw_identifier_spans: Lock<Vec<Span>>,
52     /// The registered diagnostics codes
53     crate registered_diagnostics: Lock<ErrorMap>,
54     /// Used to determine and report recursive mod inclusions
55     included_mod_stack: Lock<Vec<PathBuf>>,
56     source_map: Lrc<SourceMap>,
57     pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
58 }
59
60 impl ParseSess {
61     pub fn new(file_path_mapping: FilePathMapping) -> Self {
62         let cm = Lrc::new(SourceMap::new(file_path_mapping));
63         let handler = Handler::with_tty_emitter(ColorConfig::Auto,
64                                                 true,
65                                                 false,
66                                                 Some(cm.clone()));
67         ParseSess::with_span_handler(handler, cm)
68     }
69
70     pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> ParseSess {
71         ParseSess {
72             span_diagnostic: handler,
73             unstable_features: UnstableFeatures::from_environment(),
74             config: FxHashSet::default(),
75             missing_fragment_specifiers: Lock::new(FxHashSet::default()),
76             raw_identifier_spans: Lock::new(Vec::new()),
77             registered_diagnostics: Lock::new(ErrorMap::new()),
78             included_mod_stack: Lock::new(vec![]),
79             source_map,
80             buffered_lints: Lock::new(vec![]),
81         }
82     }
83
84     pub fn source_map(&self) -> &SourceMap {
85         &self.source_map
86     }
87
88     pub fn buffer_lint<S: Into<MultiSpan>>(&self,
89         lint_id: BufferedEarlyLintId,
90         span: S,
91         id: NodeId,
92         msg: &str,
93     ) {
94         self.buffered_lints.with_lock(|buffered_lints| {
95             buffered_lints.push(BufferedEarlyLint{
96                 span: span.into(),
97                 id,
98                 msg: msg.into(),
99                 lint_id,
100             });
101         });
102     }
103 }
104
105 #[derive(Clone)]
106 pub struct Directory<'a> {
107     pub path: Cow<'a, Path>,
108     pub ownership: DirectoryOwnership,
109 }
110
111 #[derive(Copy, Clone)]
112 pub enum DirectoryOwnership {
113     Owned {
114         // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`
115         relative: Option<ast::Ident>,
116     },
117     UnownedViaBlock,
118     UnownedViaMod(bool /* legacy warnings? */),
119 }
120
121 // a bunch of utility functions of the form parse_<thing>_from_<source>
122 // where <thing> includes crate, expr, item, stmt, tts, and one that
123 // uses a HOF to parse anything, and <source> includes file and
124 // source_str.
125
126 pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
127     let mut parser = new_parser_from_file(sess, input);
128     parser.parse_crate_mod()
129 }
130
131 pub fn parse_crate_attrs_from_file<'a>(input: &Path, sess: &'a ParseSess)
132                                        -> PResult<'a, Vec<ast::Attribute>> {
133     let mut parser = new_parser_from_file(sess, input);
134     parser.parse_inner_attributes()
135 }
136
137 pub fn parse_crate_from_source_str(name: FileName, source: String, sess: &ParseSess)
138                                        -> PResult<ast::Crate> {
139     new_parser_from_source_str(sess, name, source).parse_crate_mod()
140 }
141
142 pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &ParseSess)
143                                              -> PResult<Vec<ast::Attribute>> {
144     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
145 }
146
147 crate fn parse_expr_from_source_str(name: FileName, source: String, sess: &ParseSess)
148                                       -> PResult<P<ast::Expr>> {
149     new_parser_from_source_str(sess, name, source).parse_expr()
150 }
151
152 /// Parses an item.
153 ///
154 /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
155 /// when a syntax error occurred.
156 crate fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess)
157                                       -> PResult<Option<P<ast::Item>>> {
158     new_parser_from_source_str(sess, name, source).parse_item()
159 }
160
161 crate fn parse_stmt_from_source_str(name: FileName, source: String, sess: &ParseSess)
162                                       -> PResult<Option<ast::Stmt>> {
163     new_parser_from_source_str(sess, name, source).parse_stmt()
164 }
165
166 pub fn parse_stream_from_source_str(name: FileName, source: String, sess: &ParseSess,
167                                     override_span: Option<Span>)
168                                     -> TokenStream {
169     source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span)
170 }
171
172 /// Create a new parser from a source string
173 pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String)
174                                       -> Parser {
175     panictry_buffer!(&sess.span_diagnostic, maybe_new_parser_from_source_str(sess, name, source))
176 }
177
178 /// Create a new parser from a source string. Returns any buffered errors from lexing the initial
179 /// token stream.
180 pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String)
181     -> Result<Parser, Vec<Diagnostic>>
182 {
183     let mut parser = maybe_source_file_to_parser(sess,
184                                                  sess.source_map().new_source_file(name, source))?;
185     parser.recurse_into_file_modules = false;
186     Ok(parser)
187 }
188
189 /// Create a new parser, handling errors as appropriate
190 /// if the file doesn't exist
191 pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> {
192     source_file_to_parser(sess, file_to_source_file(sess, path, None))
193 }
194
195 /// Create a new parser, returning buffered diagnostics if the file doesn't
196 /// exist or from lexing the initial token stream.
197 pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
198     -> Result<Parser<'a>, Vec<Diagnostic>> {
199     let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?;
200     maybe_source_file_to_parser(sess, file)
201 }
202
203 /// Given a session, a crate config, a path, and a span, add
204 /// the file at the given path to the source_map, and return a parser.
205 /// On an error, use the given span as the source of the problem.
206 crate fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
207                                     path: &Path,
208                                     directory_ownership: DirectoryOwnership,
209                                     module_name: Option<String>,
210                                     sp: Span) -> Parser<'a> {
211     let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp)));
212     p.directory.ownership = directory_ownership;
213     p.root_module_name = module_name;
214     p
215 }
216
217 /// Given a source_file and config, return a parser
218 fn source_file_to_parser(sess: & ParseSess, source_file: Lrc<SourceFile>) -> Parser {
219     panictry_buffer!(&sess.span_diagnostic,
220                      maybe_source_file_to_parser(sess, source_file))
221 }
222
223 /// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
224 /// initial token stream.
225 fn maybe_source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>)
226     -> Result<Parser, Vec<Diagnostic>>
227 {
228     let end_pos = source_file.end_pos;
229     let mut parser = stream_to_parser(sess, maybe_file_to_stream(sess, source_file, None)?);
230
231     if parser.token == token::Eof && parser.span.is_dummy() {
232         parser.span = Span::new(end_pos, end_pos, parser.span.ctxt());
233     }
234
235     Ok(parser)
236 }
237
238 // must preserve old name for now, because quote! from the *existing*
239 // compiler expands into it
240 pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser {
241     stream_to_parser(sess, tts.into_iter().collect())
242 }
243
244
245 // base abstractions
246
247 /// Given a session and a path and an optional span (for error reporting),
248 /// add the path to the session's source_map and return the new source_file or
249 /// error when a file can't be read.
250 fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
251                    -> Result<Lrc<SourceFile>, Diagnostic> {
252     sess.source_map().load_file(path)
253     .map_err(|e| {
254         let msg = format!("couldn't read {}: {}", path.display(), e);
255         let mut diag = Diagnostic::new(Level::Fatal, &msg);
256         if let Some(sp) = spanopt {
257             diag.set_span(sp);
258         }
259         diag
260     })
261 }
262
263 /// Given a session and a path and an optional span (for error reporting),
264 /// add the path to the session's source_map and return the new source_file.
265 fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
266                    -> Lrc<SourceFile> {
267     match try_file_to_source_file(sess, path, spanopt) {
268         Ok(source_file) => source_file,
269         Err(d) => {
270             DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit();
271             FatalError.raise();
272         }
273     }
274 }
275
276 /// Given a source_file, produce a sequence of token-trees
277 pub fn source_file_to_stream(sess: &ParseSess,
278                              source_file: Lrc<SourceFile>,
279                              override_span: Option<Span>) -> TokenStream {
280     panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span))
281 }
282
283 /// Given a source file, produce a sequence of token-trees. Returns any buffered errors from
284 /// parsing the token tream.
285 pub fn maybe_file_to_stream(sess: &ParseSess,
286                             source_file: Lrc<SourceFile>,
287                             override_span: Option<Span>) -> Result<TokenStream, Vec<Diagnostic>> {
288     let mut srdr = lexer::StringReader::new_or_buffered_errs(sess, source_file, override_span)?;
289     srdr.real_token();
290
291     match srdr.parse_all_token_trees() {
292         Ok(stream) => Ok(stream),
293         Err(err) => {
294             let mut buffer = Vec::with_capacity(1);
295             err.buffer(&mut buffer);
296             Err(buffer)
297         }
298     }
299 }
300
301 /// Given stream and the `ParseSess`, produce a parser
302 pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
303     Parser::new(sess, stream, None, true, false)
304 }
305
306 /// Parse a string representing a character literal into its final form.
307 /// Rather than just accepting/rejecting a given literal, unescapes it as
308 /// well. Can take any slice prefixed by a character escape. Returns the
309 /// character and the number of characters consumed.
310 fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) {
311     use std::char;
312
313     // Handle non-escaped chars first.
314     if lit.as_bytes()[0] != b'\\' {
315         // If the first byte isn't '\\' it might part of a multi-byte char, so
316         // get the char with chars().
317         let c = lit.chars().next().unwrap();
318         return (c, 1);
319     }
320
321     // Handle escaped chars.
322     match lit.as_bytes()[1] as char {
323         '"' => ('"', 2),
324         'n' => ('\n', 2),
325         'r' => ('\r', 2),
326         't' => ('\t', 2),
327         '\\' => ('\\', 2),
328         '\'' => ('\'', 2),
329         '0' => ('\0', 2),
330         'x' => {
331             let v = u32::from_str_radix(&lit[2..4], 16).unwrap();
332             let c = char::from_u32(v).unwrap();
333             (c, 4)
334         }
335         'u' => {
336             assert_eq!(lit.as_bytes()[2], b'{');
337             let idx = lit.find('}').unwrap();
338
339             // All digits and '_' are ascii, so treat each byte as a char.
340             let mut v: u32 = 0;
341             for c in lit[3..idx].bytes() {
342                 let c = char::from(c);
343                 if c != '_' {
344                     let x = c.to_digit(16).unwrap();
345                     v = v.checked_mul(16).unwrap().checked_add(x).unwrap();
346                 }
347             }
348             let c = char::from_u32(v).unwrap_or_else(|| {
349                 if let Some((span, diag)) = diag {
350                     let mut diag = diag.struct_span_err(span, "invalid unicode character escape");
351                     if v > 0x10FFFF {
352                         diag.help("unicode escape must be at most 10FFFF").emit();
353                     } else {
354                         diag.help("unicode escape must not be a surrogate").emit();
355                     }
356                 }
357                 '\u{FFFD}'
358             });
359             (c, (idx + 1) as isize)
360         }
361         _ => panic!("lexer should have rejected a bad character escape {}", lit)
362     }
363 }
364
365 /// Parse a string representing a string literal into its final form. Does
366 /// unescaping.
367 pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
368     debug!("str_lit: given {}", lit.escape_default());
369     let mut res = String::with_capacity(lit.len());
370
371     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
372
373     /// Eat everything up to a non-whitespace
374     fn eat<'a>(it: &mut iter::Peekable<str::CharIndices<'a>>) {
375         loop {
376             match it.peek().map(|x| x.1) {
377                 Some(' ') | Some('\n') | Some('\r') | Some('\t') => {
378                     it.next();
379                 },
380                 _ => { break; }
381             }
382         }
383     }
384
385     let mut chars = lit.char_indices().peekable();
386     while let Some((i, c)) = chars.next() {
387         match c {
388             '\\' => {
389                 let ch = chars.peek().unwrap_or_else(|| {
390                     panic!("{}", error(i))
391                 }).1;
392
393                 if ch == '\n' {
394                     eat(&mut chars);
395                 } else if ch == '\r' {
396                     chars.next();
397                     let ch = chars.peek().unwrap_or_else(|| {
398                         panic!("{}", error(i))
399                     }).1;
400
401                     if ch != '\n' {
402                         panic!("lexer accepted bare CR");
403                     }
404                     eat(&mut chars);
405                 } else {
406                     // otherwise, a normal escape
407                     let (c, n) = char_lit(&lit[i..], diag);
408                     for _ in 0..n - 1 { // we don't need to move past the first \
409                         chars.next();
410                     }
411                     res.push(c);
412                 }
413             },
414             '\r' => {
415                 let ch = chars.peek().unwrap_or_else(|| {
416                     panic!("{}", error(i))
417                 }).1;
418
419                 if ch != '\n' {
420                     panic!("lexer accepted bare CR");
421                 }
422                 chars.next();
423                 res.push('\n');
424             }
425             c => res.push(c),
426         }
427     }
428
429     res.shrink_to_fit(); // probably not going to do anything, unless there was an escape.
430     debug!("parse_str_lit: returning {}", res);
431     res
432 }
433
434 /// Parse a string representing a raw string literal into its final form. The
435 /// only operation this does is convert embedded CRLF into a single LF.
436 fn raw_str_lit(lit: &str) -> String {
437     debug!("raw_str_lit: given {}", lit.escape_default());
438     let mut res = String::with_capacity(lit.len());
439
440     let mut chars = lit.chars().peekable();
441     while let Some(c) = chars.next() {
442         if c == '\r' {
443             if *chars.peek().unwrap() != '\n' {
444                 panic!("lexer accepted bare CR");
445             }
446             chars.next();
447             res.push('\n');
448         } else {
449             res.push(c);
450         }
451     }
452
453     res.shrink_to_fit();
454     res
455 }
456
457 // check if `s` looks like i32 or u1234 etc.
458 fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
459     s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
460 }
461
462 macro_rules! err {
463     ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => {
464         match $opt_diag {
465             Some(($span, $diag)) => { $($body)* }
466             None => return None,
467         }
468     }
469 }
470
471 crate fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Handler)>)
472                  -> (bool /* suffix illegal? */, Option<ast::LitKind>) {
473     use ast::LitKind;
474
475     match lit {
476        token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))),
477        token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
478
479         // There are some valid suffixes for integer and float literals,
480         // so all the handling is done internally.
481         token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)),
482         token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)),
483
484         token::Str_(mut sym) => {
485             // If there are no characters requiring special treatment we can
486             // reuse the symbol from the Token. Otherwise, we must generate a
487             // new symbol because the string in the LitKind is different to the
488             // string in the Token.
489             let s = &sym.as_str();
490             if s.as_bytes().iter().any(|&c| c == b'\\' || c == b'\r') {
491                 sym = Symbol::intern(&str_lit(s, diag));
492             }
493             (true, Some(LitKind::Str(sym, ast::StrStyle::Cooked)))
494         }
495         token::StrRaw(mut sym, n) => {
496             // Ditto.
497             let s = &sym.as_str();
498             if s.contains('\r') {
499                 sym = Symbol::intern(&raw_str_lit(s));
500             }
501             (true, Some(LitKind::Str(sym, ast::StrStyle::Raw(n))))
502         }
503         token::ByteStr(i) => {
504             (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str()))))
505         }
506         token::ByteStrRaw(i, _) => {
507             (true, Some(LitKind::ByteStr(Lrc::new(i.to_string().into_bytes()))))
508         }
509     }
510 }
511
512 fn filtered_float_lit(data: Symbol, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
513                       -> Option<ast::LitKind> {
514     debug!("filtered_float_lit: {}, {:?}", data, suffix);
515     let suffix = match suffix {
516         Some(suffix) => suffix,
517         None => return Some(ast::LitKind::FloatUnsuffixed(data)),
518     };
519
520     Some(match &*suffix.as_str() {
521         "f32" => ast::LitKind::Float(data, ast::FloatTy::F32),
522         "f64" => ast::LitKind::Float(data, ast::FloatTy::F64),
523         suf => {
524             err!(diag, |span, diag| {
525                 if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) {
526                     // if it looks like a width, lets try to be helpful.
527                     let msg = format!("invalid width `{}` for float literal", &suf[1..]);
528                     diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit()
529                 } else {
530                     let msg = format!("invalid suffix `{}` for float literal", suf);
531                     diag.struct_span_err(span, &msg)
532                         .help("valid suffixes are `f32` and `f64`")
533                         .emit();
534                 }
535             });
536
537             ast::LitKind::FloatUnsuffixed(data)
538         }
539     })
540 }
541 fn float_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
542                  -> Option<ast::LitKind> {
543     debug!("float_lit: {:?}, {:?}", s, suffix);
544     // FIXME #2252: bounds checking float literals is deferred until trans
545
546     // Strip underscores without allocating a new String unless necessary.
547     let s2;
548     let s = if s.chars().any(|c| c == '_') {
549         s2 = s.chars().filter(|&c| c != '_').collect::<String>();
550         &s2
551     } else {
552         s
553     };
554
555     filtered_float_lit(Symbol::intern(s), suffix, diag)
556 }
557
558 /// Parse a string representing a byte literal into its final form. Similar to `char_lit`
559 fn byte_lit(lit: &str) -> (u8, usize) {
560     let err = |i| format!("lexer accepted invalid byte literal {} step {}", lit, i);
561
562     if lit.len() == 1 {
563         (lit.as_bytes()[0], 1)
564     } else {
565         assert_eq!(lit.as_bytes()[0], b'\\', "{}", err(0));
566         let b = match lit.as_bytes()[1] {
567             b'"' => b'"',
568             b'n' => b'\n',
569             b'r' => b'\r',
570             b't' => b'\t',
571             b'\\' => b'\\',
572             b'\'' => b'\'',
573             b'0' => b'\0',
574             _ => {
575                 match u64::from_str_radix(&lit[2..4], 16).ok() {
576                     Some(c) =>
577                         if c > 0xFF {
578                             panic!(err(2))
579                         } else {
580                             return (c as u8, 4)
581                         },
582                     None => panic!(err(3))
583                 }
584             }
585         };
586         (b, 2)
587     }
588 }
589
590 fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
591     let mut res = Vec::with_capacity(lit.len());
592
593     let error = |i| panic!("lexer should have rejected {} at {}", lit, i);
594
595     /// Eat everything up to a non-whitespace
596     fn eat<I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
597         loop {
598             match it.peek().map(|x| x.1) {
599                 Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => {
600                     it.next();
601                 },
602                 _ => { break; }
603             }
604         }
605     }
606
607     // byte string literals *must* be ASCII, but the escapes don't have to be
608     let mut chars = lit.bytes().enumerate().peekable();
609     loop {
610         match chars.next() {
611             Some((i, b'\\')) => {
612                 match chars.peek().unwrap_or_else(|| error(i)).1 {
613                     b'\n' => eat(&mut chars),
614                     b'\r' => {
615                         chars.next();
616                         if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
617                             panic!("lexer accepted bare CR");
618                         }
619                         eat(&mut chars);
620                     }
621                     _ => {
622                         // otherwise, a normal escape
623                         let (c, n) = byte_lit(&lit[i..]);
624                         // we don't need to move past the first \
625                         for _ in 0..n - 1 {
626                             chars.next();
627                         }
628                         res.push(c);
629                     }
630                 }
631             },
632             Some((i, b'\r')) => {
633                 if chars.peek().unwrap_or_else(|| error(i)).1 != b'\n' {
634                     panic!("lexer accepted bare CR");
635                 }
636                 chars.next();
637                 res.push(b'\n');
638             }
639             Some((_, c)) => res.push(c),
640             None => break,
641         }
642     }
643
644     Lrc::new(res)
645 }
646
647 fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
648                    -> Option<ast::LitKind> {
649     // s can only be ascii, byte indexing is fine
650
651     // Strip underscores without allocating a new String unless necessary.
652     let s2;
653     let mut s = if s.chars().any(|c| c == '_') {
654         s2 = s.chars().filter(|&c| c != '_').collect::<String>();
655         &s2
656     } else {
657         s
658     };
659
660     debug!("integer_lit: {}, {:?}", s, suffix);
661
662     let mut base = 10;
663     let orig = s;
664     let mut ty = ast::LitIntType::Unsuffixed;
665
666     if s.starts_with('0') && s.len() > 1 {
667         match s.as_bytes()[1] {
668             b'x' => base = 16,
669             b'o' => base = 8,
670             b'b' => base = 2,
671             _ => { }
672         }
673     }
674
675     // 1f64 and 2f32 etc. are valid float literals.
676     if let Some(suf) = suffix {
677         if looks_like_width_suffix(&['f'], &suf.as_str()) {
678             let err = match base {
679                 16 => Some("hexadecimal float literal is not supported"),
680                 8 => Some("octal float literal is not supported"),
681                 2 => Some("binary float literal is not supported"),
682                 _ => None,
683             };
684             if let Some(err) = err {
685                 err!(diag, |span, diag| diag.span_err(span, err));
686             }
687             return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
688         }
689     }
690
691     if base != 10 {
692         s = &s[2..];
693     }
694
695     if let Some(suf) = suffix {
696         if suf.as_str().is_empty() {
697             err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some"));
698         }
699         ty = match &*suf.as_str() {
700             "isize" => ast::LitIntType::Signed(ast::IntTy::Isize),
701             "i8"  => ast::LitIntType::Signed(ast::IntTy::I8),
702             "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
703             "i32" => ast::LitIntType::Signed(ast::IntTy::I32),
704             "i64" => ast::LitIntType::Signed(ast::IntTy::I64),
705             "i128" => ast::LitIntType::Signed(ast::IntTy::I128),
706             "usize" => ast::LitIntType::Unsigned(ast::UintTy::Usize),
707             "u8"  => ast::LitIntType::Unsigned(ast::UintTy::U8),
708             "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
709             "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
710             "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
711             "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128),
712             suf => {
713                 // i<digits> and u<digits> look like widths, so lets
714                 // give an error message along those lines
715                 err!(diag, |span, diag| {
716                     if looks_like_width_suffix(&['i', 'u'], suf) {
717                         let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
718                         diag.struct_span_err(span, &msg)
719                             .help("valid widths are 8, 16, 32, 64 and 128")
720                             .emit();
721                     } else {
722                         let msg = format!("invalid suffix `{}` for numeric literal", suf);
723                         diag.struct_span_err(span, &msg)
724                             .help("the suffix must be one of the integral types \
725                                    (`u32`, `isize`, etc)")
726                             .emit();
727                     }
728                 });
729
730                 ty
731             }
732         }
733     }
734
735     debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
736            string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
737
738     Some(match u128::from_str_radix(s, base) {
739         Ok(r) => ast::LitKind::Int(r, ty),
740         Err(_) => {
741             // small bases are lexed as if they were base 10, e.g, the string
742             // might be `0b10201`. This will cause the conversion above to fail,
743             // but these cases have errors in the lexer: we don't want to emit
744             // two errors, and we especially don't want to emit this error since
745             // it isn't necessarily true.
746             let already_errored = base < 10 &&
747                 s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
748
749             if !already_errored {
750                 err!(diag, |span, diag| diag.span_err(span, "int literal is too large"));
751             }
752             ast::LitKind::Int(0, ty)
753         }
754     })
755 }
756
757 /// `SeqSep` : a sequence separator (token)
758 /// and whether a trailing separator is allowed.
759 pub struct SeqSep {
760     pub sep: Option<token::Token>,
761     pub trailing_sep_allowed: bool,
762 }
763
764 impl SeqSep {
765     pub fn trailing_allowed(t: token::Token) -> SeqSep {
766         SeqSep {
767             sep: Some(t),
768             trailing_sep_allowed: true,
769         }
770     }
771
772     pub fn none() -> SeqSep {
773         SeqSep {
774             sep: None,
775             trailing_sep_allowed: false,
776         }
777     }
778 }
779
780 #[cfg(test)]
781 mod tests {
782     use super::*;
783     use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION};
784     use ast::{self, Ident, PatKind};
785     use attr::first_attr_value_str_by_name;
786     use parse;
787     use print::pprust::item_to_string;
788     use tokenstream::{DelimSpan, TokenTree};
789     use util::parser_testing::string_to_stream;
790     use util::parser_testing::{string_to_expr, string_to_item};
791     use with_globals;
792
793     // produce a syntax_pos::span
794     fn sp(a: u32, b: u32) -> Span {
795         Span::new(BytePos(a), BytePos(b), NO_EXPANSION)
796     }
797
798     #[should_panic]
799     #[test] fn bad_path_expr_1() {
800         with_globals(|| {
801             string_to_expr("::abc::def::return".to_string());
802         })
803     }
804
805     // check the token-tree-ization of macros
806     #[test]
807     fn string_to_tts_macro () {
808         with_globals(|| {
809             let tts: Vec<_> =
810                 string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect();
811             let tts: &[TokenTree] = &tts[..];
812
813             match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) {
814                 (
815                     4,
816                     Some(&TokenTree::Token(_, token::Ident(name_macro_rules, false))),
817                     Some(&TokenTree::Token(_, token::Not)),
818                     Some(&TokenTree::Token(_, token::Ident(name_zip, false))),
819                     Some(&TokenTree::Delimited(_, macro_delim, ref macro_tts)),
820                 )
821                 if name_macro_rules.name == "macro_rules"
822                 && name_zip.name == "zip" => {
823                     let tts = &macro_tts.stream().trees().collect::<Vec<_>>();
824                     match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
825                         (
826                             3,
827                             Some(&TokenTree::Delimited(_, first_delim, ref first_tts)),
828                             Some(&TokenTree::Token(_, token::FatArrow)),
829                             Some(&TokenTree::Delimited(_, second_delim, ref second_tts)),
830                         )
831                         if macro_delim == token::Paren => {
832                             let tts = &first_tts.stream().trees().collect::<Vec<_>>();
833                             match (tts.len(), tts.get(0), tts.get(1)) {
834                                 (
835                                     2,
836                                     Some(&TokenTree::Token(_, token::Dollar)),
837                                     Some(&TokenTree::Token(_, token::Ident(ident, false))),
838                                 )
839                                 if first_delim == token::Paren && ident.name == "a" => {},
840                                 _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
841                             }
842                             let tts = &second_tts.stream().trees().collect::<Vec<_>>();
843                             match (tts.len(), tts.get(0), tts.get(1)) {
844                                 (
845                                     2,
846                                     Some(&TokenTree::Token(_, token::Dollar)),
847                                     Some(&TokenTree::Token(_, token::Ident(ident, false))),
848                                 )
849                                 if second_delim == token::Paren && ident.name == "a" => {},
850                                 _ => panic!("value 4: {:?} {:?}", second_delim, second_tts),
851                             }
852                         },
853                         _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts),
854                     }
855                 },
856                 _ => panic!("value: {:?}",tts),
857             }
858         })
859     }
860
861     #[test]
862     fn string_to_tts_1() {
863         with_globals(|| {
864             let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
865
866             let expected = TokenStream::new(vec![
867                 TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(),
868                 TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(),
869                 TokenTree::Delimited(
870                     DelimSpan::from_pair(sp(5, 6), sp(13, 14)),
871                     token::DelimToken::Paren,
872                     TokenStream::new(vec![
873                         TokenTree::Token(sp(6, 7),
874                                          token::Ident(Ident::from_str("b"), false)).into(),
875                         TokenTree::Token(sp(8, 9), token::Colon).into(),
876                         TokenTree::Token(sp(10, 13),
877                                          token::Ident(Ident::from_str("i32"), false)).into(),
878                     ]).into(),
879                 ).into(),
880                 TokenTree::Delimited(
881                     DelimSpan::from_pair(sp(15, 16), sp(20, 21)),
882                     token::DelimToken::Brace,
883                     TokenStream::new(vec![
884                         TokenTree::Token(sp(17, 18),
885                                          token::Ident(Ident::from_str("b"), false)).into(),
886                         TokenTree::Token(sp(18, 19), token::Semi).into(),
887                     ]).into(),
888                 ).into()
889             ]);
890
891             assert_eq!(tts, expected);
892         })
893     }
894
895     #[test] fn parse_use() {
896         with_globals(|| {
897             let use_s = "use foo::bar::baz;";
898             let vitem = string_to_item(use_s.to_string()).unwrap();
899             let vitem_s = item_to_string(&vitem);
900             assert_eq!(&vitem_s[..], use_s);
901
902             let use_s = "use foo::bar as baz;";
903             let vitem = string_to_item(use_s.to_string()).unwrap();
904             let vitem_s = item_to_string(&vitem);
905             assert_eq!(&vitem_s[..], use_s);
906         })
907     }
908
909     #[test] fn parse_extern_crate() {
910         with_globals(|| {
911             let ex_s = "extern crate foo;";
912             let vitem = string_to_item(ex_s.to_string()).unwrap();
913             let vitem_s = item_to_string(&vitem);
914             assert_eq!(&vitem_s[..], ex_s);
915
916             let ex_s = "extern crate foo as bar;";
917             let vitem = string_to_item(ex_s.to_string()).unwrap();
918             let vitem_s = item_to_string(&vitem);
919             assert_eq!(&vitem_s[..], ex_s);
920         })
921     }
922
923     fn get_spans_of_pat_idents(src: &str) -> Vec<Span> {
924         let item = string_to_item(src.to_string()).unwrap();
925
926         struct PatIdentVisitor {
927             spans: Vec<Span>
928         }
929         impl<'a> ::visit::Visitor<'a> for PatIdentVisitor {
930             fn visit_pat(&mut self, p: &'a ast::Pat) {
931                 match p.node {
932                     PatKind::Ident(_ , ref spannedident, _) => {
933                         self.spans.push(spannedident.span.clone());
934                     }
935                     _ => {
936                         ::visit::walk_pat(self, p);
937                     }
938                 }
939             }
940         }
941         let mut v = PatIdentVisitor { spans: Vec::new() };
942         ::visit::walk_item(&mut v, &item);
943         return v.spans;
944     }
945
946     #[test] fn span_of_self_arg_pat_idents_are_correct() {
947         with_globals(|| {
948
949             let srcs = ["impl z { fn a (&self, &myarg: i32) {} }",
950                         "impl z { fn a (&mut self, &myarg: i32) {} }",
951                         "impl z { fn a (&'a self, &myarg: i32) {} }",
952                         "impl z { fn a (self, &myarg: i32) {} }",
953                         "impl z { fn a (self: Foo, &myarg: i32) {} }",
954                         ];
955
956             for &src in &srcs {
957                 let spans = get_spans_of_pat_idents(src);
958                 let (lo, hi) = (spans[0].lo(), spans[0].hi());
959                 assert!("self" == &src[lo.to_usize()..hi.to_usize()],
960                         "\"{}\" != \"self\". src=\"{}\"",
961                         &src[lo.to_usize()..hi.to_usize()], src)
962             }
963         })
964     }
965
966     #[test] fn parse_exprs () {
967         with_globals(|| {
968             // just make sure that they parse....
969             string_to_expr("3 + 4".to_string());
970             string_to_expr("a::z.froob(b,&(987+3))".to_string());
971         })
972     }
973
974     #[test] fn attrs_fix_bug () {
975         with_globals(|| {
976             string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
977                    -> Result<Box<Writer>, String> {
978     #[cfg(windows)]
979     fn wb() -> c_int {
980       (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
981     }
982
983     #[cfg(unix)]
984     fn wb() -> c_int { O_WRONLY as c_int }
985
986     let mut fflags: c_int = wb();
987 }".to_string());
988         })
989     }
990
991     #[test] fn crlf_doc_comments() {
992         with_globals(|| {
993             let sess = ParseSess::new(FilePathMapping::empty());
994
995             let name_1 = FileName::Custom("crlf_source_1".to_string());
996             let source = "/// doc comment\r\nfn foo() {}".to_string();
997             let item = parse_item_from_source_str(name_1, source, &sess)
998                 .unwrap().unwrap();
999             let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap();
1000             assert_eq!(doc, "/// doc comment");
1001
1002             let name_2 = FileName::Custom("crlf_source_2".to_string());
1003             let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
1004             let item = parse_item_from_source_str(name_2, source, &sess)
1005                 .unwrap().unwrap();
1006             let docs = item.attrs.iter().filter(|a| a.path == "doc")
1007                         .map(|a| a.value_str().unwrap().to_string()).collect::<Vec<_>>();
1008             let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
1009             assert_eq!(&docs[..], b);
1010
1011             let name_3 = FileName::Custom("clrf_source_3".to_string());
1012             let source = "/** doc comment\r\n *  with CRLF */\r\nfn foo() {}".to_string();
1013             let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap();
1014             let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap();
1015             assert_eq!(doc, "/** doc comment\n *  with CRLF */");
1016         });
1017     }
1018
1019     #[test]
1020     fn ttdelim_span() {
1021         with_globals(|| {
1022             let sess = ParseSess::new(FilePathMapping::empty());
1023             let expr = parse::parse_expr_from_source_str(PathBuf::from("foo").into(),
1024                 "foo!( fn main() { body } )".to_string(), &sess).unwrap();
1025
1026             let tts: Vec<_> = match expr.node {
1027                 ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(),
1028                 _ => panic!("not a macro"),
1029             };
1030
1031             let span = tts.iter().rev().next().unwrap().span();
1032
1033             match sess.source_map().span_to_snippet(span) {
1034                 Ok(s) => assert_eq!(&s[..], "{ body }"),
1035                 Err(_) => panic!("could not get snippet"),
1036             }
1037         });
1038     }
1039
1040     // This tests that when parsing a string (rather than a file) we don't try
1041     // and read in a file for a module declaration and just parse a stub.
1042     // See `recurse_into_file_modules` in the parser.
1043     #[test]
1044     fn out_of_line_mod() {
1045         with_globals(|| {
1046             let sess = ParseSess::new(FilePathMapping::empty());
1047             let item = parse_item_from_source_str(
1048                 PathBuf::from("foo").into(),
1049                 "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
1050                 &sess,
1051             ).unwrap().unwrap();
1052
1053             if let ast::ItemKind::Mod(ref m) = item.node {
1054                 assert!(m.items.len() == 2);
1055             } else {
1056                 panic!();
1057             }
1058         });
1059     }
1060 }