]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
7453a54e | 11 | use abi::{self, Abi}; |
c34b1796 | 12 | use ast::BareFnTy; |
1a4d82fc | 13 | use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; |
7453a54e SL |
14 | use ast::Unsafety; |
15 | use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; | |
16 | use ast::Block; | |
17 | use ast::{BlockCheckMode, CaptureBy}; | |
18 | use ast::{Constness, Crate, CrateConfig}; | |
3157f602 XL |
19 | use ast::Defaultness; |
20 | use ast::EnumDef; | |
54a0048b | 21 | use ast::{Expr, ExprKind, RangeLimits}; |
7453a54e SL |
22 | use ast::{Field, FnDecl}; |
23 | use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; | |
24 | use ast::{Ident, ImplItem, Item, ItemKind}; | |
25 | use ast::{Lit, LitKind, UintTy}; | |
26 | use ast::Local; | |
27 | use ast::MacStmtStyle; | |
28 | use ast::Mac_; | |
29 | use ast::{MutTy, Mutability}; | |
7453a54e | 30 | use ast::{Pat, PatKind}; |
c34b1796 | 31 | use ast::{PolyTraitRef, QSelf}; |
7453a54e SL |
32 | use ast::{Stmt, StmtKind}; |
33 | use ast::{VariantData, StructField}; | |
34 | use ast::StrStyle; | |
35 | use ast::SelfKind; | |
3157f602 | 36 | use ast::{TraitItem, TraitRef}; |
7453a54e | 37 | use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; |
1a4d82fc JJ |
38 | use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; |
39 | use ast::{Visibility, WhereClause}; | |
7453a54e | 40 | use ast::{BinOpKind, UnOp}; |
223e47cc | 41 | use ast; |
3157f602 XL |
42 | use codemap::{self, CodeMap, Spanned, spanned}; |
43 | use syntax_pos::{self, Span, BytePos, mk_sp}; | |
9cc50fc6 | 44 | use errors::{self, DiagnosticBuilder}; |
1a4d82fc JJ |
45 | use ext::tt::macro_parser; |
46 | use parse; | |
223e47cc | 47 | use parse::classify; |
7453a54e | 48 | use parse::common::SeqSep; |
1a4d82fc | 49 | use parse::lexer::{Reader, TokenAndSpan}; |
85aaf69f | 50 | use parse::obsolete::{ParserObsoleteMethods, ObsoleteSyntax}; |
9cc50fc6 | 51 | use parse::token::{self, intern, MatchNt, SubstNt, SpecialVarNt, InternedString}; |
a7813a04 | 52 | use parse::token::{keywords, SpecialMacroVar}; |
1a4d82fc | 53 | use parse::{new_sub_parser_from_file, ParseSess}; |
92a42be0 | 54 | use util::parser::{AssocOp, Fixity}; |
1a4d82fc JJ |
55 | use print::pprust; |
56 | use ptr::P; | |
9346a6ac | 57 | use parse::PResult; |
3157f602 XL |
58 | use tokenstream::{self, Delimited, SequenceRepetition, TokenTree}; |
59 | use util::ThinVec; | |
1a4d82fc JJ |
60 | |
61 | use std::collections::HashSet; | |
1a4d82fc | 62 | use std::mem; |
c34b1796 | 63 | use std::path::{Path, PathBuf}; |
1a4d82fc JJ |
64 | use std::rc::Rc; |
65 | use std::slice; | |
66 | ||
67 | bitflags! { | |
68 | flags Restrictions: u8 { | |
d9579d0f AL |
69 | const RESTRICTION_STMT_EXPR = 1 << 0, |
70 | const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, | |
7453a54e | 71 | const NO_NONINLINE_MOD = 1 << 2, |
1a4d82fc | 72 | } |
223e47cc LB |
73 | } |
74 | ||
7453a54e | 75 | type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >); |
1a4d82fc | 76 | |
a7813a04 | 77 | /// How to parse a path. There are three different kinds of paths, all of which |
1a4d82fc | 78 | /// are parsed somewhat differently. |
c34b1796 | 79 | #[derive(Copy, Clone, PartialEq)] |
a7813a04 XL |
80 | pub enum PathStyle { |
81 | /// A path with no type parameters, e.g. `foo::bar::Baz`, used in imports or visibilities. | |
82 | Mod, | |
1a4d82fc | 83 | /// A path with a lifetime and type parameters, with no double colons |
a7813a04 XL |
84 | /// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`, used in types. |
85 | /// Paths using this style can be passed into macros expecting `path` nonterminals. | |
86 | Type, | |
1a4d82fc | 87 | /// A path with a lifetime and type parameters with double colons before |
a7813a04 XL |
88 | /// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`, used in expressions or patterns. |
89 | Expr, | |
1a4d82fc JJ |
90 | } |
91 | ||
92 | /// How to parse a bound, whether to allow bound modifiers such as `?`. | |
c34b1796 | 93 | #[derive(Copy, Clone, PartialEq)] |
1a4d82fc JJ |
94 | pub enum BoundParsingMode { |
95 | Bare, | |
96 | Modified, | |
223e47cc LB |
97 | } |
98 | ||
7453a54e SL |
99 | #[derive(Clone, Copy, PartialEq)] |
100 | pub enum SemiColonMode { | |
101 | Break, | |
102 | Ignore, | |
103 | } | |
104 | ||
1a4d82fc JJ |
105 | /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression |
106 | /// dropped into the token stream, which happens while parsing the result of | |
107 | /// macro expansion). Placement of these is not as complex as I feared it would | |
108 | /// be. The important thing is to make sure that lookahead doesn't balk at | |
109 | /// `token::Interpolated` tokens. | |
110 | macro_rules! maybe_whole_expr { | |
223e47cc | 111 | ($p:expr) => ( |
1a4d82fc JJ |
112 | { |
113 | let found = match $p.token { | |
114 | token::Interpolated(token::NtExpr(ref e)) => { | |
115 | Some((*e).clone()) | |
116 | } | |
117 | token::Interpolated(token::NtPath(_)) => { | |
118 | // FIXME: The following avoids an issue with lexical borrowck scopes, | |
119 | // but the clone is unfortunate. | |
120 | let pt = match $p.token { | |
121 | token::Interpolated(token::NtPath(ref pt)) => (**pt).clone(), | |
122 | _ => unreachable!() | |
123 | }; | |
124 | let span = $p.span; | |
3157f602 | 125 | Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new())) |
1a4d82fc JJ |
126 | } |
127 | token::Interpolated(token::NtBlock(_)) => { | |
128 | // FIXME: The following avoids an issue with lexical borrowck scopes, | |
129 | // but the clone is unfortunate. | |
130 | let b = match $p.token { | |
131 | token::Interpolated(token::NtBlock(ref b)) => (*b).clone(), | |
132 | _ => unreachable!() | |
133 | }; | |
134 | let span = $p.span; | |
3157f602 | 135 | Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new())) |
1a4d82fc JJ |
136 | } |
137 | _ => None | |
138 | }; | |
139 | match found { | |
140 | Some(e) => { | |
9cc50fc6 | 141 | $p.bump(); |
9346a6ac | 142 | return Ok(e); |
1a4d82fc JJ |
143 | } |
144 | None => () | |
223e47cc | 145 | } |
223e47cc LB |
146 | } |
147 | ) | |
1a4d82fc | 148 | } |
223e47cc | 149 | |
1a4d82fc JJ |
150 | /// As maybe_whole_expr, but for things other than expressions |
151 | macro_rules! maybe_whole { | |
223e47cc | 152 | ($p:expr, $constructor:ident) => ( |
1a4d82fc JJ |
153 | { |
154 | let found = match ($p).token { | |
155 | token::Interpolated(token::$constructor(_)) => { | |
9cc50fc6 | 156 | Some(($p).bump_and_get()) |
1a4d82fc JJ |
157 | } |
158 | _ => None | |
159 | }; | |
160 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
9346a6ac | 161 | return Ok(x.clone()); |
1a4d82fc JJ |
162 | } |
163 | } | |
164 | ); | |
165 | (no_clone $p:expr, $constructor:ident) => ( | |
166 | { | |
167 | let found = match ($p).token { | |
168 | token::Interpolated(token::$constructor(_)) => { | |
9cc50fc6 | 169 | Some(($p).bump_and_get()) |
1a4d82fc JJ |
170 | } |
171 | _ => None | |
172 | }; | |
173 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
9346a6ac | 174 | return Ok(x); |
223e47cc | 175 | } |
1a4d82fc | 176 | } |
223e47cc | 177 | ); |
7453a54e SL |
178 | (no_clone_from_p $p:expr, $constructor:ident) => ( |
179 | { | |
180 | let found = match ($p).token { | |
181 | token::Interpolated(token::$constructor(_)) => { | |
182 | Some(($p).bump_and_get()) | |
183 | } | |
184 | _ => None | |
185 | }; | |
186 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
187 | return Ok(x.unwrap()); | |
188 | } | |
189 | } | |
190 | ); | |
223e47cc | 191 | (deref $p:expr, $constructor:ident) => ( |
1a4d82fc JJ |
192 | { |
193 | let found = match ($p).token { | |
194 | token::Interpolated(token::$constructor(_)) => { | |
9cc50fc6 | 195 | Some(($p).bump_and_get()) |
1a4d82fc JJ |
196 | } |
197 | _ => None | |
198 | }; | |
199 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
9346a6ac | 200 | return Ok((*x).clone()); |
223e47cc | 201 | } |
223e47cc LB |
202 | } |
203 | ); | |
c34b1796 | 204 | (Some deref $p:expr, $constructor:ident) => ( |
1a4d82fc JJ |
205 | { |
206 | let found = match ($p).token { | |
207 | token::Interpolated(token::$constructor(_)) => { | |
9cc50fc6 | 208 | Some(($p).bump_and_get()) |
1a4d82fc JJ |
209 | } |
210 | _ => None | |
211 | }; | |
212 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
9346a6ac | 213 | return Ok(Some((*x).clone())); |
223e47cc | 214 | } |
223e47cc LB |
215 | } |
216 | ); | |
223e47cc | 217 | (pair_empty $p:expr, $constructor:ident) => ( |
1a4d82fc JJ |
218 | { |
219 | let found = match ($p).token { | |
220 | token::Interpolated(token::$constructor(_)) => { | |
9cc50fc6 | 221 | Some(($p).bump_and_get()) |
1a4d82fc JJ |
222 | } |
223 | _ => None | |
224 | }; | |
225 | if let Some(token::Interpolated(token::$constructor(x))) = found { | |
9346a6ac | 226 | return Ok((Vec::new(), x)); |
223e47cc | 227 | } |
223e47cc LB |
228 | } |
229 | ) | |
1a4d82fc | 230 | } |
223e47cc | 231 | |
1a4d82fc JJ |
232 | fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>) |
233 | -> Vec<Attribute> { | |
85aaf69f SL |
234 | if let Some(ref attrs) = rhs { |
235 | lhs.extend(attrs.iter().cloned()) | |
223e47cc | 236 | } |
1a4d82fc | 237 | lhs |
223e47cc LB |
238 | } |
239 | ||
223e47cc LB |
240 | /* ident is handled by common.rs */ |
241 | ||
1a4d82fc JJ |
242 | pub struct Parser<'a> { |
243 | pub sess: &'a ParseSess, | |
244 | /// the current token: | |
245 | pub token: token::Token, | |
246 | /// the span of the current token: | |
247 | pub span: Span, | |
248 | /// the span of the prior token: | |
249 | pub last_span: Span, | |
250 | pub cfg: CrateConfig, | |
251 | /// the previous token or None (only stashed sometimes). | |
252 | pub last_token: Option<Box<token::Token>>, | |
7453a54e SL |
253 | last_token_interpolated: bool, |
254 | last_token_eof: bool, | |
1a4d82fc | 255 | pub buffer: [TokenAndSpan; 4], |
85aaf69f SL |
256 | pub buffer_start: isize, |
257 | pub buffer_end: isize, | |
258 | pub tokens_consumed: usize, | |
1a4d82fc | 259 | pub restrictions: Restrictions, |
85aaf69f | 260 | pub quote_depth: usize, // not (yet) related to the quasiquoter |
5bcae85e | 261 | parsing_token_tree: bool, |
1a4d82fc | 262 | pub reader: Box<Reader+'a>, |
223e47cc LB |
263 | /// The set of seen errors about obsolete syntax. Used to suppress |
264 | /// extra detail when the same error is seen twice | |
1a4d82fc | 265 | pub obsolete_set: HashSet<ObsoleteSyntax>, |
223e47cc | 266 | /// Used to determine the path to externally loaded source files |
54a0048b | 267 | pub filename: Option<String>, |
1a4d82fc | 268 | pub mod_path_stack: Vec<InternedString>, |
54a0048b SL |
269 | /// Stack of open delimiters and their spans. Used for error message. |
270 | pub open_braces: Vec<(token::DelimToken, Span)>, | |
1a4d82fc JJ |
271 | /// Flag if this parser "owns" the directory that it is currently parsing |
272 | /// in. This will affect how nested files are looked up. | |
273 | pub owns_directory: bool, | |
274 | /// Name of the root module this parser originated from. If `None`, then the | |
275 | /// name is not known. This does not change while the parser is descending | |
276 | /// into modules, and sub-parsers have new values for this name. | |
277 | pub root_module_name: Option<String>, | |
278 | pub expected_tokens: Vec<TokenType>, | |
279 | } | |
280 | ||
281 | #[derive(PartialEq, Eq, Clone)] | |
282 | pub enum TokenType { | |
283 | Token(token::Token), | |
85aaf69f | 284 | Keyword(keywords::Keyword), |
1a4d82fc JJ |
285 | Operator, |
286 | } | |
223e47cc | 287 | |
1a4d82fc JJ |
288 | impl TokenType { |
289 | fn to_string(&self) -> String { | |
290 | match *self { | |
291 | TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), | |
292 | TokenType::Operator => "an operator".to_string(), | |
a7813a04 | 293 | TokenType::Keyword(kw) => format!("`{}`", kw.name()), |
1a4d82fc JJ |
294 | } |
295 | } | |
223e47cc LB |
296 | } |
297 | ||
a7813a04 XL |
298 | fn is_ident_or_underscore(t: &token::Token) -> bool { |
299 | t.is_ident() || *t == token::Underscore | |
223e47cc LB |
300 | } |
301 | ||
c1a9b12d SL |
302 | /// Information about the path to a module. |
303 | pub struct ModulePath { | |
304 | pub name: String, | |
305 | pub path_exists: bool, | |
306 | pub result: Result<ModulePathSuccess, ModulePathError>, | |
307 | } | |
308 | ||
309 | pub struct ModulePathSuccess { | |
310 | pub path: ::std::path::PathBuf, | |
311 | pub owns_directory: bool, | |
312 | } | |
313 | ||
314 | pub struct ModulePathError { | |
315 | pub err_msg: String, | |
316 | pub help_msg: String, | |
317 | } | |
318 | ||
92a42be0 SL |
319 | pub enum LhsExpr { |
320 | NotYetParsed, | |
3157f602 | 321 | AttributesParsed(ThinVec<Attribute>), |
92a42be0 SL |
322 | AlreadyParsed(P<Expr>), |
323 | } | |
324 | ||
3157f602 XL |
325 | impl From<Option<ThinVec<Attribute>>> for LhsExpr { |
326 | fn from(o: Option<ThinVec<Attribute>>) -> Self { | |
92a42be0 SL |
327 | if let Some(attrs) = o { |
328 | LhsExpr::AttributesParsed(attrs) | |
329 | } else { | |
330 | LhsExpr::NotYetParsed | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
335 | impl From<P<Expr>> for LhsExpr { | |
336 | fn from(expr: P<Expr>) -> Self { | |
337 | LhsExpr::AlreadyParsed(expr) | |
338 | } | |
339 | } | |
c1a9b12d | 340 | |
1a4d82fc JJ |
341 | impl<'a> Parser<'a> { |
342 | pub fn new(sess: &'a ParseSess, | |
343 | cfg: ast::CrateConfig, | |
344 | mut rdr: Box<Reader+'a>) | |
345 | -> Parser<'a> | |
346 | { | |
347 | let tok0 = rdr.real_token(); | |
348 | let span = tok0.sp; | |
3157f602 | 349 | let filename = if span != syntax_pos::DUMMY_SP { |
54a0048b SL |
350 | Some(sess.codemap().span_to_filename(span)) |
351 | } else { None }; | |
1a4d82fc JJ |
352 | let placeholder = TokenAndSpan { |
353 | tok: token::Underscore, | |
354 | sp: span, | |
355 | }; | |
356 | ||
357 | Parser { | |
358 | reader: rdr, | |
1a4d82fc JJ |
359 | sess: sess, |
360 | cfg: cfg, | |
361 | token: tok0.tok, | |
362 | span: span, | |
363 | last_span: span, | |
364 | last_token: None, | |
7453a54e SL |
365 | last_token_interpolated: false, |
366 | last_token_eof: false, | |
1a4d82fc JJ |
367 | buffer: [ |
368 | placeholder.clone(), | |
369 | placeholder.clone(), | |
370 | placeholder.clone(), | |
371 | placeholder.clone(), | |
372 | ], | |
373 | buffer_start: 0, | |
374 | buffer_end: 0, | |
375 | tokens_consumed: 0, | |
d9579d0f | 376 | restrictions: Restrictions::empty(), |
1a4d82fc | 377 | quote_depth: 0, |
5bcae85e | 378 | parsing_token_tree: false, |
1a4d82fc JJ |
379 | obsolete_set: HashSet::new(), |
380 | mod_path_stack: Vec::new(), | |
54a0048b | 381 | filename: filename, |
1a4d82fc JJ |
382 | open_braces: Vec::new(), |
383 | owns_directory: true, | |
384 | root_module_name: None, | |
385 | expected_tokens: Vec::new(), | |
386 | } | |
387 | } | |
388 | ||
389 | /// Convert a token to a string using self's reader | |
390 | pub fn token_to_string(token: &token::Token) -> String { | |
391 | pprust::token_to_string(token) | |
392 | } | |
393 | ||
394 | /// Convert the current token to a string using self's reader | |
85aaf69f | 395 | pub fn this_token_to_string(&self) -> String { |
1a4d82fc JJ |
396 | Parser::token_to_string(&self.token) |
397 | } | |
398 | ||
a7813a04 XL |
399 | pub fn this_token_descr(&self) -> String { |
400 | let s = self.this_token_to_string(); | |
401 | if self.token.is_strict_keyword() { | |
402 | format!("keyword `{}`", s) | |
403 | } else if self.token.is_reserved_keyword() { | |
404 | format!("reserved keyword `{}`", s) | |
405 | } else { | |
406 | format!("`{}`", s) | |
407 | } | |
408 | } | |
409 | ||
9cc50fc6 | 410 | pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> { |
1a4d82fc JJ |
411 | let token_str = Parser::token_to_string(t); |
412 | let last_span = self.last_span; | |
9cc50fc6 | 413 | Err(self.span_fatal(last_span, &format!("unexpected token: `{}`", token_str))) |
1a4d82fc JJ |
414 | } |
415 | ||
9cc50fc6 | 416 | pub fn unexpected<T>(&mut self) -> PResult<'a, T> { |
9346a6ac | 417 | match self.expect_one_of(&[], &[]) { |
9cc50fc6 SL |
418 | Err(e) => Err(e), |
419 | Ok(_) => unreachable!(), | |
9346a6ac | 420 | } |
1a4d82fc JJ |
421 | } |
422 | ||
423 | /// Expect and consume the token t. Signal an error if | |
424 | /// the next token is not t. | |
9cc50fc6 | 425 | pub fn expect(&mut self, t: &token::Token) -> PResult<'a, ()> { |
1a4d82fc JJ |
426 | if self.expected_tokens.is_empty() { |
427 | if self.token == *t { | |
9cc50fc6 SL |
428 | self.bump(); |
429 | Ok(()) | |
1a4d82fc JJ |
430 | } else { |
431 | let token_str = Parser::token_to_string(t); | |
432 | let this_token_str = self.this_token_to_string(); | |
9346a6ac | 433 | Err(self.fatal(&format!("expected `{}`, found `{}`", |
1a4d82fc | 434 | token_str, |
9346a6ac | 435 | this_token_str))) |
1a4d82fc JJ |
436 | } |
437 | } else { | |
b039eaaf | 438 | self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[]) |
1a4d82fc JJ |
439 | } |
440 | } | |
441 | ||
442 | /// Expect next token to be edible or inedible token. If edible, | |
443 | /// then consume it; if inedible, then return without consuming | |
444 | /// anything. Signal a fatal error if next token is unexpected. | |
445 | pub fn expect_one_of(&mut self, | |
446 | edible: &[token::Token], | |
9cc50fc6 | 447 | inedible: &[token::Token]) -> PResult<'a, ()>{ |
1a4d82fc JJ |
448 | fn tokens_to_string(tokens: &[TokenType]) -> String { |
449 | let mut i = tokens.iter(); | |
450 | // This might be a sign we need a connect method on Iterator. | |
451 | let b = i.next() | |
452 | .map_or("".to_string(), |t| t.to_string()); | |
453 | i.enumerate().fold(b, |mut b, (i, ref a)| { | |
454 | if tokens.len() > 2 && i == tokens.len() - 2 { | |
455 | b.push_str(", or "); | |
456 | } else if tokens.len() == 2 && i == tokens.len() - 2 { | |
457 | b.push_str(" or "); | |
458 | } else { | |
459 | b.push_str(", "); | |
460 | } | |
7453a54e | 461 | b.push_str(&a.to_string()); |
1a4d82fc JJ |
462 | b |
463 | }) | |
464 | } | |
465 | if edible.contains(&self.token) { | |
9cc50fc6 SL |
466 | self.bump(); |
467 | Ok(()) | |
1a4d82fc JJ |
468 | } else if inedible.contains(&self.token) { |
469 | // leave it in the input | |
9346a6ac | 470 | Ok(()) |
1a4d82fc | 471 | } else { |
d9579d0f AL |
472 | let mut expected = edible.iter() |
473 | .map(|x| TokenType::Token(x.clone())) | |
474 | .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) | |
475 | .chain(self.expected_tokens.iter().cloned()) | |
476 | .collect::<Vec<_>>(); | |
1a4d82fc JJ |
477 | expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); |
478 | expected.dedup(); | |
85aaf69f | 479 | let expect = tokens_to_string(&expected[..]); |
1a4d82fc | 480 | let actual = self.this_token_to_string(); |
9346a6ac | 481 | Err(self.fatal( |
85aaf69f | 482 | &(if expected.len() > 1 { |
1a4d82fc JJ |
483 | (format!("expected one of {}, found `{}`", |
484 | expect, | |
485 | actual)) | |
9346a6ac | 486 | } else if expected.is_empty() { |
85aaf69f SL |
487 | (format!("unexpected token: `{}`", |
488 | actual)) | |
1a4d82fc JJ |
489 | } else { |
490 | (format!("expected {}, found `{}`", | |
491 | expect, | |
492 | actual)) | |
85aaf69f | 493 | })[..] |
9346a6ac | 494 | )) |
1a4d82fc | 495 | } |
970d7e83 LB |
496 | } |
497 | ||
7453a54e SL |
498 | /// returns the span of expr, if it was not interpolated or the span of the interpolated token |
499 | fn interpolated_or_expr_span(&self, | |
500 | expr: PResult<'a, P<Expr>>) | |
501 | -> PResult<'a, (Span, P<Expr>)> { | |
502 | expr.map(|e| { | |
503 | if self.last_token_interpolated { | |
504 | (self.last_span, e) | |
505 | } else { | |
506 | (e.span, e) | |
507 | } | |
508 | }) | |
509 | } | |
510 | ||
9cc50fc6 | 511 | pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { |
970d7e83 | 512 | self.check_strict_keywords(); |
9cc50fc6 | 513 | self.check_reserved_keywords(); |
1a4d82fc | 514 | match self.token { |
a7813a04 | 515 | token::Ident(i) => { |
9cc50fc6 | 516 | self.bump(); |
9346a6ac | 517 | Ok(i) |
970d7e83 | 518 | } |
1a4d82fc | 519 | token::Interpolated(token::NtIdent(..)) => { |
970d7e83 LB |
520 | self.bug("ident interpolation not converted to real token"); |
521 | } | |
522 | _ => { | |
54a0048b SL |
523 | let mut err = self.fatal(&format!("expected identifier, found `{}`", |
524 | self.this_token_to_string())); | |
525 | if self.token == token::Underscore { | |
a7813a04 | 526 | err.note("`_` is a wildcard pattern, not an identifier"); |
54a0048b SL |
527 | } |
528 | Err(err) | |
970d7e83 LB |
529 | } |
530 | } | |
531 | } | |
532 | ||
a7813a04 XL |
533 | fn parse_ident_into_path(&mut self) -> PResult<'a, ast::Path> { |
534 | let ident = self.parse_ident()?; | |
535 | Ok(ast::Path::from_ident(self.last_span, ident)) | |
970d7e83 LB |
536 | } |
537 | ||
1a4d82fc JJ |
538 | /// Check if the next token is `tok`, and return `true` if so. |
539 | /// | |
7453a54e | 540 | /// This method will automatically add `tok` to `expected_tokens` if `tok` is not |
1a4d82fc JJ |
541 | /// encountered. |
542 | pub fn check(&mut self, tok: &token::Token) -> bool { | |
543 | let is_present = self.token == *tok; | |
544 | if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } | |
545 | is_present | |
970d7e83 LB |
546 | } |
547 | ||
1a4d82fc JJ |
548 | /// Consume token 'tok' if it exists. Returns true if the given |
549 | /// token was present, false otherwise. | |
9cc50fc6 | 550 | pub fn eat(&mut self, tok: &token::Token) -> bool { |
1a4d82fc | 551 | let is_present = self.check(tok); |
9cc50fc6 SL |
552 | if is_present { self.bump() } |
553 | is_present | |
970d7e83 LB |
554 | } |
555 | ||
85aaf69f SL |
556 | pub fn check_keyword(&mut self, kw: keywords::Keyword) -> bool { |
557 | self.expected_tokens.push(TokenType::Keyword(kw)); | |
558 | self.token.is_keyword(kw) | |
559 | } | |
560 | ||
1a4d82fc JJ |
561 | /// If the next token is the given keyword, eat it and return |
562 | /// true. Otherwise, return false. | |
9cc50fc6 | 563 | pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool { |
85aaf69f | 564 | if self.check_keyword(kw) { |
9cc50fc6 SL |
565 | self.bump(); |
566 | true | |
85aaf69f | 567 | } else { |
9cc50fc6 | 568 | false |
85aaf69f SL |
569 | } |
570 | } | |
571 | ||
9cc50fc6 | 572 | pub fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool { |
1a4d82fc | 573 | if self.token.is_keyword(kw) { |
9cc50fc6 SL |
574 | self.bump(); |
575 | true | |
1a4d82fc | 576 | } else { |
9cc50fc6 | 577 | false |
1a4d82fc | 578 | } |
970d7e83 LB |
579 | } |
580 | ||
54a0048b | 581 | pub fn check_contextual_keyword(&mut self, ident: Ident) -> bool { |
a7813a04 XL |
582 | self.expected_tokens.push(TokenType::Token(token::Ident(ident))); |
583 | if let token::Ident(ref cur_ident) = self.token { | |
54a0048b SL |
584 | cur_ident.name == ident.name |
585 | } else { | |
586 | false | |
587 | } | |
588 | } | |
589 | ||
590 | pub fn eat_contextual_keyword(&mut self, ident: Ident) -> bool { | |
591 | if self.check_contextual_keyword(ident) { | |
592 | self.bump(); | |
593 | true | |
594 | } else { | |
595 | false | |
596 | } | |
597 | } | |
598 | ||
1a4d82fc JJ |
599 | /// If the given word is not a keyword, signal an error. |
600 | /// If the next token is not the given word, signal an error. | |
601 | /// Otherwise, eat it. | |
9cc50fc6 SL |
602 | pub fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> { |
603 | if !self.eat_keyword(kw) { | |
604 | self.unexpected() | |
9346a6ac AL |
605 | } else { |
606 | Ok(()) | |
970d7e83 LB |
607 | } |
608 | } | |
609 | ||
1a4d82fc JJ |
610 | /// Signal an error if the given string is a strict keyword |
611 | pub fn check_strict_keywords(&mut self) { | |
612 | if self.token.is_strict_keyword() { | |
613 | let token_str = self.this_token_to_string(); | |
614 | let span = self.span; | |
615 | self.span_err(span, | |
616 | &format!("expected identifier, found keyword `{}`", | |
85aaf69f | 617 | token_str)); |
970d7e83 LB |
618 | } |
619 | } | |
620 | ||
1a4d82fc | 621 | /// Signal an error if the current token is a reserved keyword |
9cc50fc6 | 622 | pub fn check_reserved_keywords(&mut self) { |
1a4d82fc JJ |
623 | if self.token.is_reserved_keyword() { |
624 | let token_str = self.this_token_to_string(); | |
9cc50fc6 | 625 | self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit() |
970d7e83 LB |
626 | } |
627 | } | |
628 | ||
1a4d82fc JJ |
629 | /// Expect and consume an `&`. If `&&` is seen, replace it with a single |
630 | /// `&` and continue. If an `&` is not seen, signal an error. | |
9cc50fc6 | 631 | fn expect_and(&mut self) -> PResult<'a, ()> { |
85aaf69f | 632 | self.expected_tokens.push(TokenType::Token(token::BinOp(token::And))); |
1a4d82fc | 633 | match self.token { |
9cc50fc6 SL |
634 | token::BinOp(token::And) => { |
635 | self.bump(); | |
636 | Ok(()) | |
637 | } | |
1a4d82fc JJ |
638 | token::AndAnd => { |
639 | let span = self.span; | |
640 | let lo = span.lo + BytePos(1); | |
7453a54e | 641 | Ok(self.bump_with(token::BinOp(token::And), lo, span.hi)) |
1a4d82fc | 642 | } |
9cc50fc6 | 643 | _ => self.unexpected() |
970d7e83 LB |
644 | } |
645 | } | |
646 | ||
85aaf69f | 647 | pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) { |
1a4d82fc JJ |
648 | match suffix { |
649 | None => {/* everything ok */} | |
650 | Some(suf) => { | |
651 | let text = suf.as_str(); | |
652 | if text.is_empty() { | |
653 | self.span_bug(sp, "found empty literal suffix in Some") | |
654 | } | |
7453a54e | 655 | self.span_err(sp, &format!("{} with a suffix is invalid", kind)); |
1a4d82fc JJ |
656 | } |
657 | } | |
658 | } | |
659 | ||
1a4d82fc JJ |
660 | /// Attempt to consume a `<`. If `<<` is seen, replace it with a single |
661 | /// `<` and continue. If a `<` is not seen, return false. | |
662 | /// | |
663 | /// This is meant to be used when parsing generics on a path to get the | |
664 | /// starting token. | |
9cc50fc6 | 665 | fn eat_lt(&mut self) -> bool { |
85aaf69f | 666 | self.expected_tokens.push(TokenType::Token(token::Lt)); |
1a4d82fc | 667 | match self.token { |
9cc50fc6 SL |
668 | token::Lt => { |
669 | self.bump(); | |
670 | true | |
671 | } | |
1a4d82fc JJ |
672 | token::BinOp(token::Shl) => { |
673 | let span = self.span; | |
674 | let lo = span.lo + BytePos(1); | |
7453a54e | 675 | self.bump_with(token::Lt, lo, span.hi); |
9cc50fc6 | 676 | true |
1a4d82fc | 677 | } |
9cc50fc6 | 678 | _ => false, |
1a4d82fc JJ |
679 | } |
680 | } | |
681 | ||
9cc50fc6 SL |
682 | fn expect_lt(&mut self) -> PResult<'a, ()> { |
683 | if !self.eat_lt() { | |
684 | self.unexpected() | |
9346a6ac AL |
685 | } else { |
686 | Ok(()) | |
1a4d82fc JJ |
687 | } |
688 | } | |
689 | ||
1a4d82fc JJ |
690 | /// Expect and consume a GT. if a >> is seen, replace it |
691 | /// with a single > and continue. If a GT is not seen, | |
692 | /// signal an error. | |
9cc50fc6 | 693 | pub fn expect_gt(&mut self) -> PResult<'a, ()> { |
85aaf69f | 694 | self.expected_tokens.push(TokenType::Token(token::Gt)); |
1a4d82fc | 695 | match self.token { |
9cc50fc6 SL |
696 | token::Gt => { |
697 | self.bump(); | |
698 | Ok(()) | |
699 | } | |
1a4d82fc JJ |
700 | token::BinOp(token::Shr) => { |
701 | let span = self.span; | |
702 | let lo = span.lo + BytePos(1); | |
7453a54e | 703 | Ok(self.bump_with(token::Gt, lo, span.hi)) |
1a4d82fc JJ |
704 | } |
705 | token::BinOpEq(token::Shr) => { | |
706 | let span = self.span; | |
707 | let lo = span.lo + BytePos(1); | |
7453a54e | 708 | Ok(self.bump_with(token::Ge, lo, span.hi)) |
1a4d82fc JJ |
709 | } |
710 | token::Ge => { | |
711 | let span = self.span; | |
712 | let lo = span.lo + BytePos(1); | |
7453a54e | 713 | Ok(self.bump_with(token::Eq, lo, span.hi)) |
1a4d82fc JJ |
714 | } |
715 | _ => { | |
716 | let gt_str = Parser::token_to_string(&token::Gt); | |
717 | let this_token_str = self.this_token_to_string(); | |
9346a6ac | 718 | Err(self.fatal(&format!("expected `{}`, found `{}`", |
1a4d82fc | 719 | gt_str, |
9346a6ac | 720 | this_token_str))) |
1a4d82fc JJ |
721 | } |
722 | } | |
723 | } | |
724 | ||
725 | pub fn parse_seq_to_before_gt_or_return<T, F>(&mut self, | |
726 | sep: Option<token::Token>, | |
727 | mut f: F) | |
9cc50fc6 SL |
728 | -> PResult<'a, (P<[T]>, bool)> |
729 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>, | |
1a4d82fc JJ |
730 | { |
731 | let mut v = Vec::new(); | |
732 | // This loop works by alternating back and forth between parsing types | |
733 | // and commas. For example, given a string `A, B,>`, the parser would | |
734 | // first parse `A`, then a comma, then `B`, then a comma. After that it | |
735 | // would encounter a `>` and stop. This lets the parser handle trailing | |
736 | // commas in generic parameters, because it can stop either after | |
737 | // parsing a type or after parsing a comma. | |
c34b1796 | 738 | for i in 0.. { |
1a4d82fc JJ |
739 | if self.check(&token::Gt) |
740 | || self.token == token::BinOp(token::Shr) | |
741 | || self.token == token::Ge | |
742 | || self.token == token::BinOpEq(token::Shr) { | |
743 | break; | |
744 | } | |
745 | ||
746 | if i % 2 == 0 { | |
54a0048b | 747 | match f(self)? { |
1a4d82fc | 748 | Some(result) => v.push(result), |
9cc50fc6 | 749 | None => return Ok((P::from_vec(v), true)) |
1a4d82fc JJ |
750 | } |
751 | } else { | |
9346a6ac | 752 | if let Some(t) = sep.as_ref() { |
54a0048b | 753 | self.expect(t)?; |
9346a6ac AL |
754 | } |
755 | ||
1a4d82fc JJ |
756 | } |
757 | } | |
9cc50fc6 | 758 | return Ok((P::from_vec(v), false)); |
1a4d82fc JJ |
759 | } |
760 | ||
761 | /// Parse a sequence bracketed by '<' and '>', stopping | |
762 | /// before the '>'. | |
763 | pub fn parse_seq_to_before_gt<T, F>(&mut self, | |
764 | sep: Option<token::Token>, | |
765 | mut f: F) | |
9cc50fc6 SL |
766 | -> PResult<'a, P<[T]>> where |
767 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
1a4d82fc | 768 | { |
54a0048b SL |
769 | let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |
770 | |p| Ok(Some(f(p)?)))?; | |
1a4d82fc | 771 | assert!(!returned); |
9346a6ac | 772 | return Ok(result); |
970d7e83 LB |
773 | } |
774 | ||
1a4d82fc JJ |
775 | pub fn parse_seq_to_gt<T, F>(&mut self, |
776 | sep: Option<token::Token>, | |
777 | f: F) | |
9cc50fc6 SL |
778 | -> PResult<'a, P<[T]>> where |
779 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
1a4d82fc | 780 | { |
54a0048b SL |
781 | let v = self.parse_seq_to_before_gt(sep, f)?; |
782 | self.expect_gt()?; | |
9346a6ac | 783 | return Ok(v); |
970d7e83 LB |
784 | } |
785 | ||
1a4d82fc JJ |
786 | pub fn parse_seq_to_gt_or_return<T, F>(&mut self, |
787 | sep: Option<token::Token>, | |
788 | f: F) | |
9cc50fc6 SL |
789 | -> PResult<'a, (P<[T]>, bool)> where |
790 | F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>, | |
1a4d82fc | 791 | { |
54a0048b | 792 | let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f)?; |
1a4d82fc | 793 | if !returned { |
54a0048b | 794 | self.expect_gt()?; |
1a4d82fc | 795 | } |
9346a6ac | 796 | return Ok((v, returned)); |
1a4d82fc JJ |
797 | } |
798 | ||
7453a54e SL |
799 | /// Eat and discard tokens until one of `kets` is encountered. Respects token trees, |
800 | /// passes through any errors encountered. Used for error recovery. | |
801 | pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) { | |
802 | self.parse_seq_to_before_tokens(kets, | |
803 | SeqSep::none(), | |
804 | |p| p.parse_token_tree(), | |
805 | |mut e| e.cancel()); | |
806 | } | |
807 | ||
1a4d82fc JJ |
808 | /// Parse a sequence, including the closing delimiter. The function |
809 | /// f must consume tokens until reaching the next separator or | |
810 | /// closing bracket. | |
811 | pub fn parse_seq_to_end<T, F>(&mut self, | |
812 | ket: &token::Token, | |
813 | sep: SeqSep, | |
814 | f: F) | |
9cc50fc6 SL |
815 | -> PResult<'a, Vec<T>> where |
816 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
1a4d82fc | 817 | { |
7453a54e | 818 | let val = self.parse_seq_to_before_end(ket, sep, f); |
9cc50fc6 | 819 | self.bump(); |
9346a6ac | 820 | Ok(val) |
970d7e83 LB |
821 | } |
822 | ||
1a4d82fc JJ |
823 | /// Parse a sequence, not including the closing delimiter. The function |
824 | /// f must consume tokens until reaching the next separator or | |
825 | /// closing bracket. | |
826 | pub fn parse_seq_to_before_end<T, F>(&mut self, | |
827 | ket: &token::Token, | |
828 | sep: SeqSep, | |
7453a54e SL |
829 | f: F) |
830 | -> Vec<T> | |
54a0048b | 831 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> |
7453a54e SL |
832 | { |
833 | self.parse_seq_to_before_tokens(&[ket], sep, f, |mut e| e.emit()) | |
834 | } | |
835 | ||
836 | // `fe` is an error handler. | |
837 | fn parse_seq_to_before_tokens<T, F, Fe>(&mut self, | |
838 | kets: &[&token::Token], | |
839 | sep: SeqSep, | |
840 | mut f: F, | |
841 | mut fe: Fe) | |
842 | -> Vec<T> | |
843 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
844 | Fe: FnMut(DiagnosticBuilder) | |
1a4d82fc | 845 | { |
970d7e83 | 846 | let mut first: bool = true; |
1a4d82fc | 847 | let mut v = vec!(); |
7453a54e | 848 | while !kets.contains(&&self.token) { |
970d7e83 | 849 | match sep.sep { |
7453a54e SL |
850 | Some(ref t) => { |
851 | if first { | |
852 | first = false; | |
853 | } else { | |
854 | if let Err(e) = self.expect(t) { | |
855 | fe(e); | |
856 | break; | |
857 | } | |
858 | } | |
859 | } | |
860 | _ => () | |
861 | } | |
862 | if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) { | |
863 | break; | |
864 | } | |
865 | ||
866 | match f(self) { | |
867 | Ok(t) => v.push(t), | |
868 | Err(e) => { | |
869 | fe(e); | |
870 | break; | |
871 | } | |
970d7e83 | 872 | } |
970d7e83 | 873 | } |
7453a54e SL |
874 | |
875 | v | |
970d7e83 LB |
876 | } |
877 | ||
1a4d82fc JJ |
878 | /// Parse a sequence, including the closing delimiter. The function |
879 | /// f must consume tokens until reaching the next separator or | |
880 | /// closing bracket. | |
881 | pub fn parse_unspanned_seq<T, F>(&mut self, | |
882 | bra: &token::Token, | |
883 | ket: &token::Token, | |
884 | sep: SeqSep, | |
885 | f: F) | |
9cc50fc6 SL |
886 | -> PResult<'a, Vec<T>> where |
887 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
1a4d82fc | 888 | { |
54a0048b | 889 | self.expect(bra)?; |
7453a54e SL |
890 | let result = self.parse_seq_to_before_end(ket, sep, f); |
891 | if self.token == *ket { | |
892 | self.bump(); | |
893 | } | |
9346a6ac | 894 | Ok(result) |
970d7e83 LB |
895 | } |
896 | ||
897 | // NB: Do not use this function unless you actually plan to place the | |
898 | // spanned list in the AST. | |
1a4d82fc JJ |
899 | pub fn parse_seq<T, F>(&mut self, |
900 | bra: &token::Token, | |
901 | ket: &token::Token, | |
902 | sep: SeqSep, | |
903 | f: F) | |
9cc50fc6 SL |
904 | -> PResult<'a, Spanned<Vec<T>>> where |
905 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | |
1a4d82fc | 906 | { |
970d7e83 | 907 | let lo = self.span.lo; |
54a0048b | 908 | self.expect(bra)?; |
7453a54e | 909 | let result = self.parse_seq_to_before_end(ket, sep, f); |
970d7e83 | 910 | let hi = self.span.hi; |
9cc50fc6 | 911 | self.bump(); |
9346a6ac | 912 | Ok(spanned(lo, hi, result)) |
970d7e83 LB |
913 | } |
914 | ||
1a4d82fc | 915 | /// Advance the parser by one token |
9cc50fc6 | 916 | pub fn bump(&mut self) { |
7453a54e SL |
917 | if self.last_token_eof { |
918 | // Bumping after EOF is a bad sign, usually an infinite loop. | |
919 | self.bug("attempted to bump the parser past EOF (may be stuck in a loop)"); | |
920 | } | |
921 | ||
922 | if self.token == token::Eof { | |
923 | self.last_token_eof = true; | |
924 | } | |
925 | ||
1a4d82fc JJ |
926 | self.last_span = self.span; |
927 | // Stash token for error recovery (sometimes; clone is not necessarily cheap). | |
bd371182 AL |
928 | self.last_token = if self.token.is_ident() || |
929 | self.token.is_path() || | |
930 | self.token == token::Comma { | |
931 | Some(Box::new(self.token.clone())) | |
223e47cc | 932 | } else { |
1a4d82fc JJ |
933 | None |
934 | }; | |
7453a54e | 935 | self.last_token_interpolated = self.token.is_interpolated(); |
1a4d82fc JJ |
936 | let next = if self.buffer_start == self.buffer_end { |
937 | self.reader.real_token() | |
938 | } else { | |
939 | // Avoid token copies with `replace`. | |
85aaf69f | 940 | let buffer_start = self.buffer_start as usize; |
c34b1796 | 941 | let next_index = (buffer_start + 1) & 3; |
85aaf69f | 942 | self.buffer_start = next_index as isize; |
1a4d82fc JJ |
943 | |
944 | let placeholder = TokenAndSpan { | |
945 | tok: token::Underscore, | |
946 | sp: self.span, | |
947 | }; | |
948 | mem::replace(&mut self.buffer[buffer_start], placeholder) | |
223e47cc | 949 | }; |
1a4d82fc JJ |
950 | self.span = next.sp; |
951 | self.token = next.tok; | |
85aaf69f | 952 | self.tokens_consumed += 1; |
1a4d82fc JJ |
953 | self.expected_tokens.clear(); |
954 | // check after each token | |
9cc50fc6 | 955 | self.check_unknown_macro_variable(); |
223e47cc | 956 | } |
1a4d82fc JJ |
957 | |
958 | /// Advance the parser by one token and return the bumped token. | |
9cc50fc6 | 959 | pub fn bump_and_get(&mut self) -> token::Token { |
1a4d82fc | 960 | let old_token = mem::replace(&mut self.token, token::Underscore); |
9cc50fc6 SL |
961 | self.bump(); |
962 | old_token | |
1a4d82fc JJ |
963 | } |
964 | ||
7453a54e SL |
965 | /// Advance the parser using provided token as a next one. Use this when |
966 | /// consuming a part of a token. For example a single `<` from `<<`. | |
967 | pub fn bump_with(&mut self, | |
968 | next: token::Token, | |
969 | lo: BytePos, | |
970 | hi: BytePos) { | |
1a4d82fc | 971 | self.last_span = mk_sp(self.span.lo, lo); |
7453a54e SL |
972 | // It would be incorrect to just stash current token, but fortunately |
973 | // for tokens currently using `bump_with`, last_token will be of no | |
974 | // use anyway. | |
975 | self.last_token = None; | |
976 | self.last_token_interpolated = false; | |
1a4d82fc | 977 | self.span = mk_sp(lo, hi); |
7453a54e SL |
978 | self.token = next; |
979 | self.expected_tokens.clear(); | |
223e47cc | 980 | } |
7453a54e | 981 | |
85aaf69f | 982 | pub fn buffer_length(&mut self) -> isize { |
1a4d82fc JJ |
983 | if self.buffer_start <= self.buffer_end { |
984 | return self.buffer_end - self.buffer_start; | |
223e47cc | 985 | } |
1a4d82fc | 986 | return (4 - self.buffer_start) + self.buffer_end; |
223e47cc | 987 | } |
85aaf69f | 988 | pub fn look_ahead<R, F>(&mut self, distance: usize, f: F) -> R where |
1a4d82fc JJ |
989 | F: FnOnce(&token::Token) -> R, |
990 | { | |
85aaf69f | 991 | let dist = distance as isize; |
223e47cc | 992 | while self.buffer_length() < dist { |
85aaf69f | 993 | self.buffer[self.buffer_end as usize] = self.reader.real_token(); |
1a4d82fc | 994 | self.buffer_end = (self.buffer_end + 1) & 3; |
223e47cc | 995 | } |
85aaf69f | 996 | f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok) |
223e47cc | 997 | } |
9cc50fc6 SL |
998 | pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { |
999 | self.sess.span_diagnostic.struct_span_fatal(self.span, m) | |
223e47cc | 1000 | } |
9cc50fc6 SL |
1001 | pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> { |
1002 | self.sess.span_diagnostic.struct_span_fatal(sp, m) | |
1a4d82fc | 1003 | } |
9cc50fc6 SL |
1004 | pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> { |
1005 | let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m); | |
a7813a04 | 1006 | err.help(help); |
9cc50fc6 | 1007 | err |
c34b1796 | 1008 | } |
85aaf69f | 1009 | pub fn bug(&self, m: &str) -> ! { |
1a4d82fc JJ |
1010 | self.sess.span_diagnostic.span_bug(self.span, m) |
1011 | } | |
85aaf69f | 1012 | pub fn warn(&self, m: &str) { |
1a4d82fc | 1013 | self.sess.span_diagnostic.span_warn(self.span, m) |
223e47cc | 1014 | } |
85aaf69f | 1015 | pub fn span_warn(&self, sp: Span, m: &str) { |
1a4d82fc | 1016 | self.sess.span_diagnostic.span_warn(sp, m) |
223e47cc | 1017 | } |
85aaf69f | 1018 | pub fn span_err(&self, sp: Span, m: &str) { |
223e47cc LB |
1019 | self.sess.span_diagnostic.span_err(sp, m) |
1020 | } | |
85aaf69f | 1021 | pub fn span_bug(&self, sp: Span, m: &str) -> ! { |
1a4d82fc JJ |
1022 | self.sess.span_diagnostic.span_bug(sp, m) |
1023 | } | |
85aaf69f | 1024 | pub fn abort_if_errors(&self) { |
9cc50fc6 SL |
1025 | self.sess.span_diagnostic.abort_if_errors(); |
1026 | } | |
1027 | ||
1028 | pub fn diagnostic(&self) -> &'a errors::Handler { | |
1029 | &self.sess.span_diagnostic | |
223e47cc | 1030 | } |
223e47cc | 1031 | |
1a4d82fc | 1032 | pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString { |
c1a9b12d | 1033 | id.name.as_str() |
223e47cc LB |
1034 | } |
1035 | ||
1a4d82fc JJ |
1036 | /// Is the current token one of the keywords that signals a bare function |
1037 | /// type? | |
1038 | pub fn token_is_bare_fn_keyword(&mut self) -> bool { | |
85aaf69f SL |
1039 | self.check_keyword(keywords::Fn) || |
1040 | self.check_keyword(keywords::Unsafe) || | |
1041 | self.check_keyword(keywords::Extern) | |
223e47cc LB |
1042 | } |
1043 | ||
1a4d82fc JJ |
1044 | pub fn get_lifetime(&mut self) -> ast::Ident { |
1045 | match self.token { | |
1046 | token::Lifetime(ref ident) => *ident, | |
970d7e83 LB |
1047 | _ => self.bug("not a lifetime"), |
1048 | } | |
1049 | } | |
1050 | ||
7453a54e | 1051 | pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> { |
223e47cc | 1052 | /* |
1a4d82fc | 1053 | Parses whatever can come after a `for` keyword in a type. |
5bcae85e | 1054 | The `for` hasn't been consumed. |
1a4d82fc JJ |
1055 | |
1056 | Deprecated: | |
1057 | ||
1058 | - for <'lt> |S| -> T | |
1059 | ||
1060 | Eventually: | |
1061 | ||
1062 | - for <'lt> [unsafe] [extern "ABI"] fn (S) -> T | |
1063 | - for <'lt> path::foo(a, b) | |
1064 | ||
1065 | */ | |
1066 | ||
1067 | // parse <'lt> | |
85aaf69f SL |
1068 | let lo = self.span.lo; |
1069 | ||
54a0048b | 1070 | let lifetime_defs = self.parse_late_bound_lifetime_defs()?; |
1a4d82fc JJ |
1071 | |
1072 | // examine next token to decide to do | |
c34b1796 AL |
1073 | if self.token_is_bare_fn_keyword() { |
1074 | self.parse_ty_bare_fn(lifetime_defs) | |
1075 | } else { | |
85aaf69f | 1076 | let hi = self.span.hi; |
54a0048b | 1077 | let trait_ref = self.parse_trait_ref()?; |
1a4d82fc | 1078 | let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs, |
85aaf69f SL |
1079 | trait_ref: trait_ref, |
1080 | span: mk_sp(lo, hi)}; | |
9cc50fc6 | 1081 | let other_bounds = if self.eat(&token::BinOp(token::Plus)) { |
54a0048b | 1082 | self.parse_ty_param_bounds(BoundParsingMode::Bare)? |
1a4d82fc | 1083 | } else { |
a7813a04 | 1084 | P::new() |
1a4d82fc JJ |
1085 | }; |
1086 | let all_bounds = | |
1087 | Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter() | |
62682a34 | 1088 | .chain(other_bounds.into_vec()) |
1a4d82fc | 1089 | .collect(); |
7453a54e | 1090 | Ok(ast::TyKind::PolyTraitRef(all_bounds)) |
1a4d82fc JJ |
1091 | } |
1092 | } | |
1093 | ||
5bcae85e SL |
1094 | pub fn parse_impl_trait_type(&mut self) -> PResult<'a, TyKind> { |
1095 | /* | |
1096 | Parses whatever can come after a `impl` keyword in a type. | |
1097 | The `impl` has already been consumed. | |
1098 | */ | |
1099 | ||
1100 | let bounds = self.parse_ty_param_bounds(BoundParsingMode::Modified)?; | |
1101 | ||
1102 | if !bounds.iter().any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) { | |
1103 | let last_span = self.last_span; | |
1104 | self.span_err(last_span, "at least one trait must be specified"); | |
1105 | } | |
1106 | ||
1107 | Ok(ast::TyKind::ImplTrait(bounds)) | |
1108 | } | |
1109 | ||
1110 | ||
7453a54e | 1111 | pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> { |
a7813a04 | 1112 | Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?)) |
1a4d82fc | 1113 | } |
223e47cc | 1114 | |
7453a54e SL |
1115 | /// parse a TyKind::BareFn type: |
1116 | pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) | |
1117 | -> PResult<'a, TyKind> { | |
1a4d82fc | 1118 | /* |
223e47cc | 1119 | |
54a0048b SL |
1120 | [unsafe] [extern "ABI"] fn (S) -> T |
1121 | ^~~~^ ^~~~^ ^~^ ^ | |
1122 | | | | | | |
1123 | | | | Return type | |
1124 | | | Argument types | |
1125 | | | | |
1a4d82fc JJ |
1126 | | ABI |
1127 | Function Style | |
223e47cc LB |
1128 | */ |
1129 | ||
54a0048b | 1130 | let unsafety = self.parse_unsafety()?; |
9cc50fc6 | 1131 | let abi = if self.eat_keyword(keywords::Extern) { |
54a0048b | 1132 | self.parse_opt_abi()?.unwrap_or(Abi::C) |
1a4d82fc | 1133 | } else { |
7453a54e | 1134 | Abi::Rust |
1a4d82fc JJ |
1135 | }; |
1136 | ||
54a0048b SL |
1137 | self.expect_keyword(keywords::Fn)?; |
1138 | let (inputs, variadic) = self.parse_fn_args(false, true)?; | |
1139 | let ret_ty = self.parse_ret_ty()?; | |
1a4d82fc JJ |
1140 | let decl = P(FnDecl { |
1141 | inputs: inputs, | |
1142 | output: ret_ty, | |
1143 | variadic: variadic | |
223e47cc | 1144 | }); |
7453a54e | 1145 | Ok(TyKind::BareFn(P(BareFnTy { |
1a4d82fc JJ |
1146 | abi: abi, |
1147 | unsafety: unsafety, | |
1148 | lifetimes: lifetime_defs, | |
1149 | decl: decl | |
9346a6ac | 1150 | }))) |
223e47cc LB |
1151 | } |
1152 | ||
85aaf69f | 1153 | /// Parses an obsolete closure kind (`&:`, `&mut:`, or `:`). |
9cc50fc6 | 1154 | pub fn parse_obsolete_closure_kind(&mut self) -> PResult<'a, ()> { |
85aaf69f SL |
1155 | let lo = self.span.lo; |
1156 | if | |
1157 | self.check(&token::BinOp(token::And)) && | |
1158 | self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && | |
1159 | self.look_ahead(2, |t| *t == token::Colon) | |
1160 | { | |
9cc50fc6 SL |
1161 | self.bump(); |
1162 | self.bump(); | |
1163 | self.bump(); | |
85aaf69f SL |
1164 | } else if |
1165 | self.token == token::BinOp(token::And) && | |
1166 | self.look_ahead(1, |t| *t == token::Colon) | |
1167 | { | |
9cc50fc6 SL |
1168 | self.bump(); |
1169 | self.bump(); | |
85aaf69f | 1170 | } else if |
9cc50fc6 | 1171 | self.eat(&token::Colon) |
85aaf69f SL |
1172 | { |
1173 | /* nothing */ | |
1174 | } else { | |
9346a6ac | 1175 | return Ok(()); |
1a4d82fc JJ |
1176 | } |
1177 | ||
9346a6ac AL |
1178 | let span = mk_sp(lo, self.span.hi); |
1179 | self.obsolete(span, ObsoleteSyntax::ClosureKind); | |
1180 | Ok(()) | |
223e47cc LB |
1181 | } |
1182 | ||
9cc50fc6 SL |
1183 | pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> { |
1184 | if self.eat_keyword(keywords::Unsafe) { | |
9346a6ac | 1185 | return Ok(Unsafety::Unsafe); |
1a4d82fc | 1186 | } else { |
9346a6ac | 1187 | return Ok(Unsafety::Normal); |
1a4d82fc JJ |
1188 | } |
1189 | } | |
1190 | ||
1a4d82fc | 1191 | /// Parse the items in a trait declaration |
3157f602 XL |
1192 | pub fn parse_trait_item(&mut self) -> PResult<'a, TraitItem> { |
1193 | maybe_whole!(no_clone_from_p self, NtTraitItem); | |
1194 | let mut attrs = self.parse_outer_attributes()?; | |
1195 | let lo = self.span.lo; | |
1196 | ||
1197 | let (name, node) = if self.eat_keyword(keywords::Type) { | |
1198 | let TyParam {ident, bounds, default, ..} = self.parse_ty_param()?; | |
1199 | self.expect(&token::Semi)?; | |
1200 | (ident, TraitItemKind::Type(bounds, default)) | |
1201 | } else if self.is_const_item() { | |
1202 | self.expect_keyword(keywords::Const)?; | |
1203 | let ident = self.parse_ident()?; | |
1204 | self.expect(&token::Colon)?; | |
1205 | let ty = self.parse_ty_sum()?; | |
1206 | let default = if self.check(&token::Eq) { | |
1207 | self.bump(); | |
1208 | let expr = self.parse_expr()?; | |
5bcae85e | 1209 | self.expect(&token::Semi)?; |
3157f602 XL |
1210 | Some(expr) |
1211 | } else { | |
1212 | self.expect(&token::Semi)?; | |
1213 | None | |
1214 | }; | |
1215 | (ident, TraitItemKind::Const(ty, default)) | |
1216 | } else if !self.token.is_any_keyword() | |
1217 | && self.look_ahead(1, |t| *t == token::Not) | |
1218 | && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) | |
1219 | || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { | |
1220 | // trait item macro. | |
1221 | // code copied from parse_macro_use_or_failure... abstraction! | |
1222 | let lo = self.span.lo; | |
1223 | let pth = self.parse_ident_into_path()?; | |
1224 | self.expect(&token::Not)?; | |
1225 | ||
1226 | // eat a matched-delimiter token tree: | |
1227 | let delim = self.expect_open_delim()?; | |
1228 | let tts = self.parse_seq_to_end(&token::CloseDelim(delim), | |
1229 | SeqSep::none(), | |
1230 | |pp| pp.parse_token_tree())?; | |
1231 | let m_ = Mac_ { path: pth, tts: tts }; | |
1232 | let m: ast::Mac = codemap::Spanned { node: m_, | |
1233 | span: mk_sp(lo, | |
1234 | self.last_span.hi) }; | |
1235 | if delim != token::Brace { | |
1236 | self.expect(&token::Semi)? | |
1237 | } | |
1238 | (keywords::Invalid.ident(), ast::TraitItemKind::Macro(m)) | |
1a4d82fc | 1239 | } else { |
3157f602 | 1240 | let (constness, unsafety, abi) = match self.parse_fn_front_matter() { |
7453a54e SL |
1241 | Ok(cua) => cua, |
1242 | Err(e) => { | |
1243 | loop { | |
3157f602 | 1244 | match self.token { |
7453a54e | 1245 | token::Eof => break, |
7453a54e SL |
1246 | token::CloseDelim(token::Brace) | |
1247 | token::Semi => { | |
3157f602 | 1248 | self.bump(); |
7453a54e SL |
1249 | break; |
1250 | } | |
7453a54e | 1251 | token::OpenDelim(token::Brace) => { |
3157f602 | 1252 | self.parse_token_tree()?; |
7453a54e SL |
1253 | break; |
1254 | } | |
3157f602 | 1255 | _ => self.bump() |
7453a54e SL |
1256 | } |
1257 | } | |
1258 | ||
1259 | return Err(e); | |
1260 | } | |
1261 | }; | |
1a4d82fc | 1262 | |
3157f602 XL |
1263 | let ident = self.parse_ident()?; |
1264 | let mut generics = self.parse_generics()?; | |
1a4d82fc | 1265 | |
3157f602 | 1266 | let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>|{ |
1a4d82fc JJ |
1267 | // This is somewhat dubious; We don't want to allow |
1268 | // argument names to be left off if there is a | |
1269 | // definition... | |
1270 | p.parse_arg_general(false) | |
54a0048b | 1271 | })?; |
1a4d82fc | 1272 | |
3157f602 | 1273 | generics.where_clause = self.parse_where_clause()?; |
c34b1796 | 1274 | let sig = ast::MethodSig { |
62682a34 SL |
1275 | unsafety: unsafety, |
1276 | constness: constness, | |
c34b1796 AL |
1277 | decl: d, |
1278 | generics: generics, | |
1279 | abi: abi, | |
c34b1796 | 1280 | }; |
1a4d82fc | 1281 | |
3157f602 XL |
1282 | let body = match self.token { |
1283 | token::Semi => { | |
1284 | self.bump(); | |
1285 | debug!("parse_trait_methods(): parsing required method"); | |
1286 | None | |
1287 | } | |
1288 | token::OpenDelim(token::Brace) => { | |
1289 | debug!("parse_trait_methods(): parsing provided method"); | |
1290 | let (inner_attrs, body) = | |
1291 | self.parse_inner_attrs_and_block()?; | |
1292 | attrs.extend(inner_attrs.iter().cloned()); | |
1293 | Some(body) | |
1294 | } | |
1a4d82fc | 1295 | |
3157f602 XL |
1296 | _ => { |
1297 | let token_str = self.this_token_to_string(); | |
1298 | return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`", | |
1299 | token_str)[..])) | |
1300 | } | |
c34b1796 | 1301 | }; |
7453a54e | 1302 | (ident, ast::TraitItemKind::Method(sig, body)) |
c34b1796 | 1303 | }; |
3157f602 XL |
1304 | Ok(TraitItem { |
1305 | id: ast::DUMMY_NODE_ID, | |
1306 | ident: name, | |
1307 | attrs: attrs, | |
1308 | node: node, | |
1309 | span: mk_sp(lo, self.last_span.hi), | |
1310 | }) | |
1311 | } | |
c34b1796 | 1312 | |
3157f602 XL |
1313 | |
1314 | /// Parse the items in a trait declaration | |
1315 | pub fn parse_trait_items(&mut self) -> PResult<'a, Vec<TraitItem>> { | |
1316 | self.parse_unspanned_seq( | |
1317 | &token::OpenDelim(token::Brace), | |
1318 | &token::CloseDelim(token::Brace), | |
1319 | SeqSep::none(), | |
1320 | |p| -> PResult<'a, TraitItem> { | |
1321 | p.parse_trait_item() | |
7453a54e | 1322 | }) |
223e47cc LB |
1323 | } |
1324 | ||
1a4d82fc | 1325 | /// Parse a possibly mutable type |
9cc50fc6 | 1326 | pub fn parse_mt(&mut self) -> PResult<'a, MutTy> { |
54a0048b SL |
1327 | let mutbl = self.parse_mutability()?; |
1328 | let t = self.parse_ty()?; | |
9346a6ac | 1329 | Ok(MutTy { ty: t, mutbl: mutbl }) |
223e47cc LB |
1330 | } |
1331 | ||
1a4d82fc | 1332 | /// Parse optional return type [ -> TY ] in function decl |
9cc50fc6 SL |
1333 | pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> { |
1334 | if self.eat(&token::RArrow) { | |
5bcae85e | 1335 | Ok(FunctionRetTy::Ty(self.parse_ty()?)) |
223e47cc LB |
1336 | } else { |
1337 | let pos = self.span.lo; | |
7453a54e | 1338 | Ok(FunctionRetTy::Default(mk_sp(pos, pos))) |
1a4d82fc JJ |
1339 | } |
1340 | } | |
1341 | ||
1342 | /// Parse a type in a context where `T1+T2` is allowed. | |
9cc50fc6 | 1343 | pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> { |
1a4d82fc | 1344 | let lo = self.span.lo; |
54a0048b | 1345 | let lhs = self.parse_ty()?; |
1a4d82fc | 1346 | |
9cc50fc6 | 1347 | if !self.eat(&token::BinOp(token::Plus)) { |
9346a6ac | 1348 | return Ok(lhs); |
1a4d82fc JJ |
1349 | } |
1350 | ||
54a0048b | 1351 | let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?; |
1a4d82fc JJ |
1352 | |
1353 | // In type grammar, `+` is treated like a binary operator, | |
1354 | // and hence both L and R side are required. | |
9346a6ac | 1355 | if bounds.is_empty() { |
1a4d82fc JJ |
1356 | let last_span = self.last_span; |
1357 | self.span_err(last_span, | |
1358 | "at least one type parameter bound \ | |
1359 | must be specified"); | |
223e47cc | 1360 | } |
1a4d82fc JJ |
1361 | |
1362 | let sp = mk_sp(lo, self.last_span.hi); | |
7453a54e | 1363 | let sum = ast::TyKind::ObjectSum(lhs, bounds); |
9346a6ac | 1364 | Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})) |
223e47cc LB |
1365 | } |
1366 | ||
1a4d82fc | 1367 | /// Parse a type. |
9cc50fc6 | 1368 | pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> { |
1a4d82fc | 1369 | maybe_whole!(no_clone self, NtTy); |
223e47cc LB |
1370 | |
1371 | let lo = self.span.lo; | |
1372 | ||
1a4d82fc | 1373 | let t = if self.check(&token::OpenDelim(token::Paren)) { |
9cc50fc6 | 1374 | self.bump(); |
1a4d82fc JJ |
1375 | |
1376 | // (t) is a parenthesized ty | |
1377 | // (t,) is the type of a tuple with only one field, | |
1378 | // of type t | |
1379 | let mut ts = vec![]; | |
1380 | let mut last_comma = false; | |
1381 | while self.token != token::CloseDelim(token::Paren) { | |
54a0048b | 1382 | ts.push(self.parse_ty_sum()?); |
1a4d82fc JJ |
1383 | if self.check(&token::Comma) { |
1384 | last_comma = true; | |
9cc50fc6 | 1385 | self.bump(); |
223e47cc | 1386 | } else { |
1a4d82fc JJ |
1387 | last_comma = false; |
1388 | break; | |
1389 | } | |
223e47cc | 1390 | } |
1a4d82fc | 1391 | |
54a0048b | 1392 | self.expect(&token::CloseDelim(token::Paren))?; |
1a4d82fc | 1393 | if ts.len() == 1 && !last_comma { |
7453a54e | 1394 | TyKind::Paren(ts.into_iter().nth(0).unwrap()) |
1a4d82fc | 1395 | } else { |
7453a54e | 1396 | TyKind::Tup(ts) |
1a4d82fc | 1397 | } |
5bcae85e SL |
1398 | } else if self.eat(&token::Not) { |
1399 | TyKind::Never | |
1a4d82fc | 1400 | } else if self.check(&token::BinOp(token::Star)) { |
970d7e83 | 1401 | // STAR POINTER (bare pointer?) |
9cc50fc6 | 1402 | self.bump(); |
54a0048b | 1403 | TyKind::Ptr(self.parse_ptr()?) |
1a4d82fc | 1404 | } else if self.check(&token::OpenDelim(token::Bracket)) { |
970d7e83 | 1405 | // VECTOR |
54a0048b SL |
1406 | self.expect(&token::OpenDelim(token::Bracket))?; |
1407 | let t = self.parse_ty_sum()?; | |
223e47cc | 1408 | |
85aaf69f | 1409 | // Parse the `; e` in `[ i32; e ]` |
223e47cc | 1410 | // where `e` is a const expression |
54a0048b | 1411 | let t = match self.maybe_parse_fixed_length_of_vec()? { |
7453a54e SL |
1412 | None => TyKind::Vec(t), |
1413 | Some(suffix) => TyKind::FixedLengthVec(t, suffix) | |
223e47cc | 1414 | }; |
54a0048b | 1415 | self.expect(&token::CloseDelim(token::Bracket))?; |
223e47cc | 1416 | t |
1a4d82fc JJ |
1417 | } else if self.check(&token::BinOp(token::And)) || |
1418 | self.token == token::AndAnd { | |
970d7e83 | 1419 | // BORROWED POINTER |
54a0048b SL |
1420 | self.expect_and()?; |
1421 | self.parse_borrowed_pointee()? | |
85aaf69f | 1422 | } else if self.check_keyword(keywords::For) { |
54a0048b | 1423 | self.parse_for_in_type()? |
5bcae85e SL |
1424 | } else if self.eat_keyword(keywords::Impl) { |
1425 | self.parse_impl_trait_type()? | |
c34b1796 AL |
1426 | } else if self.token_is_bare_fn_keyword() { |
1427 | // BARE FUNCTION | |
54a0048b | 1428 | self.parse_ty_bare_fn(Vec::new())? |
9cc50fc6 | 1429 | } else if self.eat_keyword_noexpect(keywords::Typeof) { |
1a4d82fc JJ |
1430 | // TYPEOF |
1431 | // In order to not be ambiguous, the type must be surrounded by parens. | |
54a0048b SL |
1432 | self.expect(&token::OpenDelim(token::Paren))?; |
1433 | let e = self.parse_expr()?; | |
1434 | self.expect(&token::CloseDelim(token::Paren))?; | |
7453a54e | 1435 | TyKind::Typeof(e) |
9cc50fc6 | 1436 | } else if self.eat_lt() { |
c34b1796 | 1437 | |
d9579d0f | 1438 | let (qself, path) = |
a7813a04 | 1439 | self.parse_qualified_path(PathStyle::Type)?; |
c34b1796 | 1440 | |
7453a54e | 1441 | TyKind::Path(Some(qself), path) |
a7813a04 XL |
1442 | } else if self.token.is_path_start() { |
1443 | let path = self.parse_path(PathStyle::Type)?; | |
e9174d1e SL |
1444 | if self.check(&token::Not) { |
1445 | // MACRO INVOCATION | |
9cc50fc6 | 1446 | self.bump(); |
54a0048b SL |
1447 | let delim = self.expect_open_delim()?; |
1448 | let tts = self.parse_seq_to_end(&token::CloseDelim(delim), | |
1449 | SeqSep::none(), | |
1450 | |p| p.parse_token_tree())?; | |
e9174d1e | 1451 | let hi = self.span.hi; |
3157f602 | 1452 | TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts })) |
e9174d1e SL |
1453 | } else { |
1454 | // NAMED TYPE | |
7453a54e | 1455 | TyKind::Path(None, path) |
e9174d1e | 1456 | } |
9cc50fc6 | 1457 | } else if self.eat(&token::Underscore) { |
1a4d82fc | 1458 | // TYPE TO BE INFERRED |
7453a54e | 1459 | TyKind::Infer |
223e47cc | 1460 | } else { |
a7813a04 XL |
1461 | let msg = format!("expected type, found {}", self.this_token_descr()); |
1462 | return Err(self.fatal(&msg)); | |
223e47cc LB |
1463 | }; |
1464 | ||
1465 | let sp = mk_sp(lo, self.last_span.hi); | |
9346a6ac | 1466 | Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp})) |
223e47cc LB |
1467 | } |
1468 | ||
7453a54e | 1469 | pub fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { |
223e47cc | 1470 | // look for `&'lt` or `&'foo ` and interpret `foo` as the region name: |
54a0048b | 1471 | let opt_lifetime = self.parse_opt_lifetime()?; |
223e47cc | 1472 | |
54a0048b | 1473 | let mt = self.parse_mt()?; |
7453a54e | 1474 | return Ok(TyKind::Rptr(opt_lifetime, mt)); |
1a4d82fc JJ |
1475 | } |
1476 | ||
9cc50fc6 SL |
1477 | pub fn parse_ptr(&mut self) -> PResult<'a, MutTy> { |
1478 | let mutbl = if self.eat_keyword(keywords::Mut) { | |
7453a54e | 1479 | Mutability::Mutable |
9cc50fc6 | 1480 | } else if self.eat_keyword(keywords::Const) { |
7453a54e | 1481 | Mutability::Immutable |
223e47cc | 1482 | } else { |
1a4d82fc JJ |
1483 | let span = self.last_span; |
1484 | self.span_err(span, | |
a7813a04 XL |
1485 | "expected mut or const in raw pointer type (use \ |
1486 | `*mut T` or `*const T` as appropriate)"); | |
7453a54e | 1487 | Mutability::Immutable |
1a4d82fc | 1488 | }; |
54a0048b | 1489 | let t = self.parse_ty()?; |
9346a6ac | 1490 | Ok(MutTy { ty: t, mutbl: mutbl }) |
223e47cc LB |
1491 | } |
1492 | ||
1a4d82fc JJ |
1493 | pub fn is_named_argument(&mut self) -> bool { |
1494 | let offset = match self.token { | |
1495 | token::BinOp(token::And) => 1, | |
1496 | token::AndAnd => 1, | |
1497 | _ if self.token.is_keyword(keywords::Mut) => 1, | |
1498 | _ => 0 | |
1499 | }; | |
1500 | ||
1501 | debug!("parser is_named_argument offset:{}", offset); | |
1502 | ||
223e47cc | 1503 | if offset == 0 { |
a7813a04 | 1504 | is_ident_or_underscore(&self.token) |
1a4d82fc | 1505 | && self.look_ahead(1, |t| *t == token::Colon) |
223e47cc | 1506 | } else { |
a7813a04 | 1507 | self.look_ahead(offset, |t| is_ident_or_underscore(t)) |
1a4d82fc | 1508 | && self.look_ahead(offset + 1, |t| *t == token::Colon) |
223e47cc LB |
1509 | } |
1510 | } | |
1511 | ||
1a4d82fc JJ |
1512 | /// This version of parse arg doesn't necessarily require |
1513 | /// identifier names. | |
9cc50fc6 | 1514 | pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { |
92a42be0 SL |
1515 | maybe_whole!(no_clone self, NtArg); |
1516 | ||
223e47cc | 1517 | let pat = if require_name || self.is_named_argument() { |
1a4d82fc JJ |
1518 | debug!("parse_arg_general parse_pat (require_name:{})", |
1519 | require_name); | |
54a0048b | 1520 | let pat = self.parse_pat()?; |
970d7e83 | 1521 | |
54a0048b | 1522 | self.expect(&token::Colon)?; |
223e47cc LB |
1523 | pat |
1524 | } else { | |
1a4d82fc | 1525 | debug!("parse_arg_general ident_to_pat"); |
54a0048b | 1526 | let sp = self.last_span; |
a7813a04 | 1527 | let spanned = Spanned { span: sp, node: keywords::Invalid.ident() }; |
54a0048b SL |
1528 | P(Pat { |
1529 | id: ast::DUMMY_NODE_ID, | |
1530 | node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), | |
1531 | spanned, None), | |
1532 | span: sp | |
1533 | }) | |
223e47cc LB |
1534 | }; |
1535 | ||
54a0048b | 1536 | let t = self.parse_ty_sum()?; |
223e47cc | 1537 | |
9346a6ac | 1538 | Ok(Arg { |
970d7e83 LB |
1539 | ty: t, |
1540 | pat: pat, | |
1a4d82fc | 1541 | id: ast::DUMMY_NODE_ID, |
9346a6ac | 1542 | }) |
223e47cc LB |
1543 | } |
1544 | ||
1a4d82fc | 1545 | /// Parse a single function argument |
9cc50fc6 | 1546 | pub fn parse_arg(&mut self) -> PResult<'a, Arg> { |
1a4d82fc | 1547 | self.parse_arg_general(true) |
223e47cc LB |
1548 | } |
1549 | ||
1a4d82fc | 1550 | /// Parse an argument in a lambda header e.g. |arg, arg| |
9cc50fc6 | 1551 | pub fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { |
54a0048b | 1552 | let pat = self.parse_pat()?; |
9cc50fc6 | 1553 | let t = if self.eat(&token::Colon) { |
54a0048b | 1554 | self.parse_ty_sum()? |
223e47cc | 1555 | } else { |
1a4d82fc JJ |
1556 | P(Ty { |
1557 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 1558 | node: TyKind::Infer, |
223e47cc | 1559 | span: mk_sp(self.span.lo, self.span.hi), |
1a4d82fc | 1560 | }) |
223e47cc | 1561 | }; |
9346a6ac | 1562 | Ok(Arg { |
223e47cc LB |
1563 | ty: t, |
1564 | pat: pat, | |
1a4d82fc | 1565 | id: ast::DUMMY_NODE_ID |
9346a6ac | 1566 | }) |
223e47cc LB |
1567 | } |
1568 | ||
9cc50fc6 | 1569 | pub fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> { |
1a4d82fc | 1570 | if self.check(&token::Semi) { |
9cc50fc6 | 1571 | self.bump(); |
54a0048b | 1572 | Ok(Some(self.parse_expr()?)) |
223e47cc | 1573 | } else { |
9346a6ac | 1574 | Ok(None) |
223e47cc LB |
1575 | } |
1576 | } | |
1577 | ||
1a4d82fc | 1578 | /// Matches token_lit = LIT_INTEGER | ... |
a7813a04 XL |
1579 | pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { |
1580 | let out = match self.token { | |
1a4d82fc JJ |
1581 | token::Interpolated(token::NtExpr(ref v)) => { |
1582 | match v.node { | |
a7813a04 XL |
1583 | ExprKind::Lit(ref lit) => { lit.node.clone() } |
1584 | _ => { return self.unexpected_last(&self.token); } | |
1a4d82fc JJ |
1585 | } |
1586 | } | |
1587 | token::Literal(lit, suf) => { | |
1588 | let (suffix_illegal, out) = match lit { | |
7453a54e SL |
1589 | token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)), |
1590 | token::Char(i) => (true, LitKind::Char(parse::char_lit(&i.as_str()).0)), | |
1a4d82fc JJ |
1591 | |
1592 | // there are some valid suffixes for integer and | |
1593 | // float literals, so all the handling is done | |
1594 | // internally. | |
1595 | token::Integer(s) => { | |
c1a9b12d | 1596 | (false, parse::integer_lit(&s.as_str(), |
1a4d82fc JJ |
1597 | suf.as_ref().map(|s| s.as_str()), |
1598 | &self.sess.span_diagnostic, | |
a7813a04 | 1599 | self.span)) |
1a4d82fc JJ |
1600 | } |
1601 | token::Float(s) => { | |
c1a9b12d | 1602 | (false, parse::float_lit(&s.as_str(), |
1a4d82fc JJ |
1603 | suf.as_ref().map(|s| s.as_str()), |
1604 | &self.sess.span_diagnostic, | |
a7813a04 | 1605 | self.span)) |
1a4d82fc JJ |
1606 | } |
1607 | ||
1608 | token::Str_(s) => { | |
1609 | (true, | |
7453a54e SL |
1610 | LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())), |
1611 | ast::StrStyle::Cooked)) | |
1a4d82fc JJ |
1612 | } |
1613 | token::StrRaw(s, n) => { | |
1614 | (true, | |
7453a54e | 1615 | LitKind::Str( |
c1a9b12d | 1616 | token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())), |
7453a54e | 1617 | ast::StrStyle::Raw(n))) |
1a4d82fc | 1618 | } |
e9174d1e | 1619 | token::ByteStr(i) => |
7453a54e | 1620 | (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))), |
e9174d1e | 1621 | token::ByteStrRaw(i, _) => |
1a4d82fc | 1622 | (true, |
7453a54e | 1623 | LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))), |
1a4d82fc JJ |
1624 | }; |
1625 | ||
1626 | if suffix_illegal { | |
a7813a04 | 1627 | let sp = self.span; |
7453a54e | 1628 | self.expect_no_suffix(sp, &format!("{} literal", lit.short_name()), suf) |
1a4d82fc JJ |
1629 | } |
1630 | ||
a7813a04 | 1631 | out |
1a4d82fc | 1632 | } |
a7813a04 XL |
1633 | _ => { return self.unexpected_last(&self.token); } |
1634 | }; | |
1635 | ||
1636 | self.bump(); | |
1637 | Ok(out) | |
223e47cc LB |
1638 | } |
1639 | ||
1a4d82fc | 1640 | /// Matches lit = true | false | token_lit |
9cc50fc6 | 1641 | pub fn parse_lit(&mut self) -> PResult<'a, Lit> { |
223e47cc | 1642 | let lo = self.span.lo; |
9cc50fc6 | 1643 | let lit = if self.eat_keyword(keywords::True) { |
7453a54e | 1644 | LitKind::Bool(true) |
9cc50fc6 | 1645 | } else if self.eat_keyword(keywords::False) { |
7453a54e | 1646 | LitKind::Bool(false) |
223e47cc | 1647 | } else { |
a7813a04 | 1648 | let lit = self.parse_lit_token()?; |
1a4d82fc | 1649 | lit |
223e47cc | 1650 | }; |
9346a6ac | 1651 | Ok(codemap::Spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }) |
223e47cc LB |
1652 | } |
1653 | ||
1a4d82fc | 1654 | /// matches '-' lit | lit |
9cc50fc6 | 1655 | pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { |
970d7e83 | 1656 | let minus_lo = self.span.lo; |
9cc50fc6 | 1657 | let minus_present = self.eat(&token::BinOp(token::Minus)); |
970d7e83 | 1658 | let lo = self.span.lo; |
54a0048b | 1659 | let literal = P(self.parse_lit()?); |
b039eaaf | 1660 | let hi = self.last_span.hi; |
3157f602 | 1661 | let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), ThinVec::new()); |
970d7e83 LB |
1662 | |
1663 | if minus_present { | |
b039eaaf | 1664 | let minus_hi = self.last_span.hi; |
7453a54e | 1665 | let unary = self.mk_unary(UnOp::Neg, expr); |
3157f602 | 1666 | Ok(self.mk_expr(minus_lo, minus_hi, unary, ThinVec::new())) |
970d7e83 | 1667 | } else { |
9346a6ac | 1668 | Ok(expr) |
970d7e83 LB |
1669 | } |
1670 | } | |
1671 | ||
a7813a04 XL |
1672 | pub fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> { |
1673 | match self.token { | |
1674 | token::Ident(sid) if self.token.is_path_segment_keyword() => { | |
1675 | self.bump(); | |
1676 | Ok(sid) | |
1677 | } | |
1678 | _ => self.parse_ident(), | |
1679 | } | |
1680 | } | |
1681 | ||
b039eaaf SL |
1682 | /// Parses qualified path. |
1683 | /// | |
1684 | /// Assumes that the leading `<` has been parsed already. | |
1685 | /// | |
1686 | /// Qualifed paths are a part of the universal function call | |
1687 | /// syntax (UFCS). | |
1688 | /// | |
1689 | /// `qualified_path = <type [as trait_ref]>::path` | |
1690 | /// | |
1691 | /// See `parse_path` for `mode` meaning. | |
1692 | /// | |
1693 | /// # Examples: | |
1694 | /// | |
1695 | /// `<T as U>::a` | |
1696 | /// `<T as U>::F::a::<S>` | |
a7813a04 | 1697 | pub fn parse_qualified_path(&mut self, mode: PathStyle) |
9cc50fc6 | 1698 | -> PResult<'a, (QSelf, ast::Path)> { |
c1a9b12d | 1699 | let span = self.last_span; |
54a0048b | 1700 | let self_type = self.parse_ty_sum()?; |
9cc50fc6 | 1701 | let mut path = if self.eat_keyword(keywords::As) { |
a7813a04 | 1702 | self.parse_path(PathStyle::Type)? |
d9579d0f AL |
1703 | } else { |
1704 | ast::Path { | |
c1a9b12d | 1705 | span: span, |
d9579d0f AL |
1706 | global: false, |
1707 | segments: vec![] | |
1708 | } | |
1709 | }; | |
1710 | ||
1711 | let qself = QSelf { | |
1712 | ty: self_type, | |
1713 | position: path.segments.len() | |
1714 | }; | |
1715 | ||
54a0048b SL |
1716 | self.expect(&token::Gt)?; |
1717 | self.expect(&token::ModSep)?; | |
d9579d0f AL |
1718 | |
1719 | let segments = match mode { | |
a7813a04 | 1720 | PathStyle::Type => { |
54a0048b | 1721 | self.parse_path_segments_without_colons()? |
d9579d0f | 1722 | } |
a7813a04 | 1723 | PathStyle::Expr => { |
54a0048b | 1724 | self.parse_path_segments_with_colons()? |
d9579d0f | 1725 | } |
a7813a04 | 1726 | PathStyle::Mod => { |
54a0048b | 1727 | self.parse_path_segments_without_types()? |
d9579d0f AL |
1728 | } |
1729 | }; | |
1730 | path.segments.extend(segments); | |
1731 | ||
d9579d0f AL |
1732 | path.span.hi = self.last_span.hi; |
1733 | ||
1734 | Ok((qself, path)) | |
1735 | } | |
1736 | ||
1a4d82fc JJ |
1737 | /// Parses a path and optional type parameter bounds, depending on the |
1738 | /// mode. The `mode` parameter determines whether lifetimes, types, and/or | |
1739 | /// bounds are permitted and whether `::` must precede type parameter | |
1740 | /// groups. | |
a7813a04 | 1741 | pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { |
1a4d82fc JJ |
1742 | // Check for a whole path... |
1743 | let found = match self.token { | |
9cc50fc6 | 1744 | token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), |
1a4d82fc JJ |
1745 | _ => None, |
1746 | }; | |
d9579d0f AL |
1747 | if let Some(token::Interpolated(token::NtPath(path))) = found { |
1748 | return Ok(*path); | |
1a4d82fc | 1749 | } |
970d7e83 | 1750 | |
223e47cc | 1751 | let lo = self.span.lo; |
9cc50fc6 | 1752 | let is_global = self.eat(&token::ModSep); |
1a4d82fc JJ |
1753 | |
1754 | // Parse any number of segments and bound sets. A segment is an | |
1755 | // identifier followed by an optional lifetime and a set of types. | |
1756 | // A bound set is a set of type parameter bounds. | |
1757 | let segments = match mode { | |
a7813a04 | 1758 | PathStyle::Type => { |
54a0048b | 1759 | self.parse_path_segments_without_colons()? |
223e47cc | 1760 | } |
a7813a04 | 1761 | PathStyle::Expr => { |
54a0048b | 1762 | self.parse_path_segments_with_colons()? |
1a4d82fc | 1763 | } |
a7813a04 | 1764 | PathStyle::Mod => { |
54a0048b | 1765 | self.parse_path_segments_without_types()? |
1a4d82fc JJ |
1766 | } |
1767 | }; | |
970d7e83 | 1768 | |
1a4d82fc JJ |
1769 | // Assemble the span. |
1770 | let span = mk_sp(lo, self.last_span.hi); | |
1771 | ||
1772 | // Assemble the result. | |
9346a6ac | 1773 | Ok(ast::Path { |
1a4d82fc JJ |
1774 | span: span, |
1775 | global: is_global, | |
1776 | segments: segments, | |
9346a6ac | 1777 | }) |
223e47cc LB |
1778 | } |
1779 | ||
1a4d82fc JJ |
1780 | /// Examples: |
1781 | /// - `a::b<T,U>::c<V,W>` | |
1782 | /// - `a::b<T,U>::c(V) -> W` | |
1783 | /// - `a::b<T,U>::c(V)` | |
9cc50fc6 | 1784 | pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> { |
1a4d82fc JJ |
1785 | let mut segments = Vec::new(); |
1786 | loop { | |
1787 | // First, parse an identifier. | |
a7813a04 | 1788 | let identifier = self.parse_path_segment_ident()?; |
223e47cc | 1789 | |
1a4d82fc | 1790 | // Parse types, optionally. |
9cc50fc6 | 1791 | let parameters = if self.eat_lt() { |
54a0048b | 1792 | let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?; |
223e47cc | 1793 | |
9cc50fc6 | 1794 | ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { |
1a4d82fc | 1795 | lifetimes: lifetimes, |
9cc50fc6 SL |
1796 | types: P::from_vec(types), |
1797 | bindings: P::from_vec(bindings), | |
1a4d82fc | 1798 | }) |
9cc50fc6 | 1799 | } else if self.eat(&token::OpenDelim(token::Paren)) { |
85aaf69f SL |
1800 | let lo = self.last_span.lo; |
1801 | ||
54a0048b | 1802 | let inputs = self.parse_seq_to_end( |
1a4d82fc | 1803 | &token::CloseDelim(token::Paren), |
7453a54e | 1804 | SeqSep::trailing_allowed(token::Comma), |
54a0048b | 1805 | |p| p.parse_ty_sum())?; |
1a4d82fc | 1806 | |
9cc50fc6 | 1807 | let output_ty = if self.eat(&token::RArrow) { |
54a0048b | 1808 | Some(self.parse_ty()?) |
1a4d82fc JJ |
1809 | } else { |
1810 | None | |
1811 | }; | |
970d7e83 | 1812 | |
85aaf69f SL |
1813 | let hi = self.last_span.hi; |
1814 | ||
9cc50fc6 | 1815 | ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData { |
85aaf69f | 1816 | span: mk_sp(lo, hi), |
1a4d82fc | 1817 | inputs: inputs, |
85aaf69f | 1818 | output: output_ty, |
1a4d82fc | 1819 | }) |
223e47cc | 1820 | } else { |
1a4d82fc JJ |
1821 | ast::PathParameters::none() |
1822 | }; | |
1823 | ||
1824 | // Assemble and push the result. | |
1825 | segments.push(ast::PathSegment { identifier: identifier, | |
1826 | parameters: parameters }); | |
1827 | ||
1828 | // Continue only if we see a `::` | |
9cc50fc6 | 1829 | if !self.eat(&token::ModSep) { |
9346a6ac | 1830 | return Ok(segments); |
223e47cc | 1831 | } |
1a4d82fc JJ |
1832 | } |
1833 | } | |
223e47cc | 1834 | |
1a4d82fc JJ |
1835 | /// Examples: |
1836 | /// - `a::b::<T,U>::c` | |
9cc50fc6 | 1837 | pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> { |
1a4d82fc JJ |
1838 | let mut segments = Vec::new(); |
1839 | loop { | |
1840 | // First, parse an identifier. | |
a7813a04 | 1841 | let identifier = self.parse_path_segment_ident()?; |
1a4d82fc JJ |
1842 | |
1843 | // If we do not see a `::`, stop. | |
9cc50fc6 | 1844 | if !self.eat(&token::ModSep) { |
1a4d82fc JJ |
1845 | segments.push(ast::PathSegment { |
1846 | identifier: identifier, | |
85aaf69f | 1847 | parameters: ast::PathParameters::none() |
1a4d82fc | 1848 | }); |
9346a6ac | 1849 | return Ok(segments); |
1a4d82fc | 1850 | } |
223e47cc | 1851 | |
1a4d82fc | 1852 | // Check for a type segment. |
9cc50fc6 | 1853 | if self.eat_lt() { |
1a4d82fc | 1854 | // Consumed `a::b::<`, go look for types |
54a0048b | 1855 | let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?; |
9cc50fc6 SL |
1856 | let parameters = ast::AngleBracketedParameterData { |
1857 | lifetimes: lifetimes, | |
1858 | types: P::from_vec(types), | |
1859 | bindings: P::from_vec(bindings), | |
1860 | }; | |
1a4d82fc JJ |
1861 | segments.push(ast::PathSegment { |
1862 | identifier: identifier, | |
9cc50fc6 | 1863 | parameters: ast::PathParameters::AngleBracketed(parameters), |
1a4d82fc JJ |
1864 | }); |
1865 | ||
1866 | // Consumed `a::b::<T,U>`, check for `::` before proceeding | |
9cc50fc6 | 1867 | if !self.eat(&token::ModSep) { |
9346a6ac | 1868 | return Ok(segments); |
223e47cc | 1869 | } |
1a4d82fc JJ |
1870 | } else { |
1871 | // Consumed `a::`, go look for `b` | |
1872 | segments.push(ast::PathSegment { | |
1873 | identifier: identifier, | |
1874 | parameters: ast::PathParameters::none(), | |
1875 | }); | |
223e47cc | 1876 | } |
1a4d82fc | 1877 | } |
223e47cc LB |
1878 | } |
1879 | ||
1a4d82fc JJ |
1880 | /// Examples: |
1881 | /// - `a::b::c` | |
a7813a04 XL |
1882 | pub fn parse_path_segments_without_types(&mut self) |
1883 | -> PResult<'a, Vec<ast::PathSegment>> { | |
1a4d82fc JJ |
1884 | let mut segments = Vec::new(); |
1885 | loop { | |
1886 | // First, parse an identifier. | |
a7813a04 | 1887 | let identifier = self.parse_path_segment_ident()?; |
970d7e83 | 1888 | |
1a4d82fc JJ |
1889 | // Assemble and push the result. |
1890 | segments.push(ast::PathSegment { | |
1891 | identifier: identifier, | |
1892 | parameters: ast::PathParameters::none() | |
1893 | }); | |
223e47cc | 1894 | |
a7813a04 XL |
1895 | // If we do not see a `::` or see `::{`/`::*`, stop. |
1896 | if !self.check(&token::ModSep) || self.is_import_coupler() { | |
9346a6ac | 1897 | return Ok(segments); |
a7813a04 XL |
1898 | } else { |
1899 | self.bump(); | |
223e47cc | 1900 | } |
1a4d82fc JJ |
1901 | } |
1902 | } | |
223e47cc | 1903 | |
1a4d82fc | 1904 | /// parses 0 or 1 lifetime |
9cc50fc6 | 1905 | pub fn parse_opt_lifetime(&mut self) -> PResult<'a, Option<ast::Lifetime>> { |
1a4d82fc JJ |
1906 | match self.token { |
1907 | token::Lifetime(..) => { | |
54a0048b | 1908 | Ok(Some(self.parse_lifetime()?)) |
1a4d82fc | 1909 | } |
223e47cc | 1910 | _ => { |
9346a6ac | 1911 | Ok(None) |
223e47cc LB |
1912 | } |
1913 | } | |
1914 | } | |
1915 | ||
970d7e83 | 1916 | /// Parses a single lifetime |
1a4d82fc | 1917 | /// Matches lifetime = LIFETIME |
9cc50fc6 | 1918 | pub fn parse_lifetime(&mut self) -> PResult<'a, ast::Lifetime> { |
1a4d82fc JJ |
1919 | match self.token { |
1920 | token::Lifetime(i) => { | |
1921 | let span = self.span; | |
9cc50fc6 | 1922 | self.bump(); |
9346a6ac | 1923 | return Ok(ast::Lifetime { |
1a4d82fc JJ |
1924 | id: ast::DUMMY_NODE_ID, |
1925 | span: span, | |
1926 | name: i.name | |
9346a6ac | 1927 | }); |
223e47cc | 1928 | } |
223e47cc | 1929 | _ => { |
92a42be0 | 1930 | return Err(self.fatal("expected a lifetime name")); |
223e47cc LB |
1931 | } |
1932 | } | |
1933 | } | |
1934 | ||
1a4d82fc JJ |
1935 | /// Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` where `lifetime_def = |
1936 | /// lifetime [':' lifetimes]` | |
9cc50fc6 | 1937 | pub fn parse_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> { |
223e47cc | 1938 | |
1a4d82fc | 1939 | let mut res = Vec::new(); |
223e47cc | 1940 | loop { |
1a4d82fc JJ |
1941 | match self.token { |
1942 | token::Lifetime(_) => { | |
54a0048b | 1943 | let lifetime = self.parse_lifetime()?; |
1a4d82fc | 1944 | let bounds = |
9cc50fc6 | 1945 | if self.eat(&token::Colon) { |
54a0048b | 1946 | self.parse_lifetimes(token::BinOp(token::Plus))? |
1a4d82fc JJ |
1947 | } else { |
1948 | Vec::new() | |
1949 | }; | |
1950 | res.push(ast::LifetimeDef { lifetime: lifetime, | |
1951 | bounds: bounds }); | |
223e47cc | 1952 | } |
1a4d82fc | 1953 | |
223e47cc | 1954 | _ => { |
9346a6ac | 1955 | return Ok(res); |
223e47cc LB |
1956 | } |
1957 | } | |
1958 | ||
1a4d82fc | 1959 | match self.token { |
9cc50fc6 | 1960 | token::Comma => { self.bump();} |
9346a6ac AL |
1961 | token::Gt => { return Ok(res); } |
1962 | token::BinOp(token::Shr) => { return Ok(res); } | |
223e47cc | 1963 | _ => { |
1a4d82fc JJ |
1964 | let this_token_str = self.this_token_to_string(); |
1965 | let msg = format!("expected `,` or `>` after lifetime \ | |
1966 | name, found `{}`", | |
1967 | this_token_str); | |
9346a6ac | 1968 | return Err(self.fatal(&msg[..])); |
223e47cc LB |
1969 | } |
1970 | } | |
1971 | } | |
1972 | } | |
1973 | ||
1a4d82fc JJ |
1974 | /// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) actually, it matches the empty |
1975 | /// one too, but putting that in there messes up the grammar.... | |
1976 | /// | |
1977 | /// Parses zero or more comma separated lifetimes. Expects each lifetime to be followed by | |
1978 | /// either a comma or `>`. Used when parsing type parameter lists, where we expect something | |
1979 | /// like `<'a, 'b, T>`. | |
9cc50fc6 | 1980 | pub fn parse_lifetimes(&mut self, sep: token::Token) -> PResult<'a, Vec<ast::Lifetime>> { |
1a4d82fc JJ |
1981 | |
1982 | let mut res = Vec::new(); | |
1983 | loop { | |
1984 | match self.token { | |
1985 | token::Lifetime(_) => { | |
54a0048b | 1986 | res.push(self.parse_lifetime()?); |
1a4d82fc JJ |
1987 | } |
1988 | _ => { | |
9346a6ac | 1989 | return Ok(res); |
1a4d82fc JJ |
1990 | } |
1991 | } | |
1992 | ||
1993 | if self.token != sep { | |
9346a6ac | 1994 | return Ok(res); |
1a4d82fc JJ |
1995 | } |
1996 | ||
9cc50fc6 | 1997 | self.bump(); |
1a4d82fc | 1998 | } |
223e47cc LB |
1999 | } |
2000 | ||
a7813a04 | 2001 | /// Parse mutability (`mut` or nothing). |
9cc50fc6 SL |
2002 | pub fn parse_mutability(&mut self) -> PResult<'a, Mutability> { |
2003 | if self.eat_keyword(keywords::Mut) { | |
7453a54e | 2004 | Ok(Mutability::Mutable) |
223e47cc | 2005 | } else { |
7453a54e | 2006 | Ok(Mutability::Immutable) |
223e47cc LB |
2007 | } |
2008 | } | |
2009 | ||
5bcae85e SL |
2010 | pub fn parse_field_name(&mut self) -> PResult<'a, Ident> { |
2011 | if let token::Literal(token::Integer(name), None) = self.token { | |
2012 | self.bump(); | |
2013 | Ok(Ident::with_empty_ctxt(name)) | |
2014 | } else { | |
2015 | self.parse_ident() | |
2016 | } | |
2017 | } | |
2018 | ||
1a4d82fc | 2019 | /// Parse ident COLON expr |
9cc50fc6 | 2020 | pub fn parse_field(&mut self) -> PResult<'a, Field> { |
223e47cc | 2021 | let lo = self.span.lo; |
5bcae85e | 2022 | let i = self.parse_field_name()?; |
1a4d82fc | 2023 | let hi = self.last_span.hi; |
54a0048b SL |
2024 | self.expect(&token::Colon)?; |
2025 | let e = self.parse_expr()?; | |
9346a6ac | 2026 | Ok(ast::Field { |
1a4d82fc JJ |
2027 | ident: spanned(lo, hi, i), |
2028 | span: mk_sp(lo, e.span.hi), | |
2029 | expr: e, | |
9346a6ac | 2030 | }) |
223e47cc LB |
2031 | } |
2032 | ||
3157f602 XL |
2033 | pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: ExprKind, attrs: ThinVec<Attribute>) |
2034 | -> P<Expr> { | |
1a4d82fc JJ |
2035 | P(Expr { |
2036 | id: ast::DUMMY_NODE_ID, | |
223e47cc LB |
2037 | node: node, |
2038 | span: mk_sp(lo, hi), | |
3157f602 | 2039 | attrs: attrs.into(), |
1a4d82fc JJ |
2040 | }) |
2041 | } | |
2042 | ||
7453a54e SL |
2043 | pub fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind { |
2044 | ExprKind::Unary(unop, expr) | |
1a4d82fc JJ |
2045 | } |
2046 | ||
7453a54e SL |
2047 | pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind { |
2048 | ExprKind::Binary(binop, lhs, rhs) | |
223e47cc LB |
2049 | } |
2050 | ||
7453a54e SL |
2051 | pub fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind { |
2052 | ExprKind::Call(f, args) | |
970d7e83 LB |
2053 | } |
2054 | ||
1a4d82fc JJ |
2055 | fn mk_method_call(&mut self, |
2056 | ident: ast::SpannedIdent, | |
2057 | tps: Vec<P<Ty>>, | |
2058 | args: Vec<P<Expr>>) | |
7453a54e SL |
2059 | -> ast::ExprKind { |
2060 | ExprKind::MethodCall(ident, tps, args) | |
970d7e83 LB |
2061 | } |
2062 | ||
7453a54e SL |
2063 | pub fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind { |
2064 | ExprKind::Index(expr, idx) | |
970d7e83 LB |
2065 | } |
2066 | ||
1a4d82fc JJ |
2067 | pub fn mk_range(&mut self, |
2068 | start: Option<P<Expr>>, | |
54a0048b SL |
2069 | end: Option<P<Expr>>, |
2070 | limits: RangeLimits) | |
2071 | -> PResult<'a, ast::ExprKind> { | |
2072 | if end.is_none() && limits == RangeLimits::Closed { | |
2073 | Err(self.span_fatal_help(self.span, | |
2074 | "inclusive range with no end", | |
2075 | "inclusive ranges must be bounded at the end \ | |
2076 | (`...b` or `a...b`)")) | |
2077 | } else { | |
2078 | Ok(ExprKind::Range(start, end, limits)) | |
2079 | } | |
970d7e83 LB |
2080 | } |
2081 | ||
7453a54e SL |
2082 | pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::ExprKind { |
2083 | ExprKind::Field(expr, ident) | |
970d7e83 LB |
2084 | } |
2085 | ||
7453a54e SL |
2086 | pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::ExprKind { |
2087 | ExprKind::TupField(expr, idx) | |
970d7e83 LB |
2088 | } |
2089 | ||
1a4d82fc | 2090 | pub fn mk_assign_op(&mut self, binop: ast::BinOp, |
7453a54e SL |
2091 | lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind { |
2092 | ExprKind::AssignOp(binop, lhs, rhs) | |
970d7e83 LB |
2093 | } |
2094 | ||
92a42be0 | 2095 | pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, |
3157f602 | 2096 | m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> { |
1a4d82fc JJ |
2097 | P(Expr { |
2098 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 2099 | node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}), |
223e47cc | 2100 | span: mk_sp(lo, hi), |
92a42be0 | 2101 | attrs: attrs, |
1a4d82fc | 2102 | }) |
223e47cc LB |
2103 | } |
2104 | ||
3157f602 | 2105 | pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec<Attribute>) -> P<Expr> { |
1a4d82fc JJ |
2106 | let span = &self.span; |
2107 | let lv_lit = P(codemap::Spanned { | |
7453a54e | 2108 | node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)), |
223e47cc | 2109 | span: *span |
1a4d82fc | 2110 | }); |
223e47cc | 2111 | |
1a4d82fc JJ |
2112 | P(Expr { |
2113 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 2114 | node: ExprKind::Lit(lv_lit), |
223e47cc | 2115 | span: *span, |
92a42be0 | 2116 | attrs: attrs, |
1a4d82fc JJ |
2117 | }) |
2118 | } | |
2119 | ||
9cc50fc6 | 2120 | fn expect_open_delim(&mut self) -> PResult<'a, token::DelimToken> { |
85aaf69f | 2121 | self.expected_tokens.push(TokenType::Token(token::Gt)); |
1a4d82fc JJ |
2122 | match self.token { |
2123 | token::OpenDelim(delim) => { | |
9cc50fc6 | 2124 | self.bump(); |
9346a6ac | 2125 | Ok(delim) |
1a4d82fc | 2126 | }, |
9346a6ac | 2127 | _ => Err(self.fatal("expected open delimiter")), |
223e47cc LB |
2128 | } |
2129 | } | |
2130 | ||
1a4d82fc JJ |
2131 | /// At the bottom (top?) of the precedence hierarchy, |
2132 | /// parse things like parenthesized exprs, | |
2133 | /// macros, return, etc. | |
92a42be0 SL |
2134 | /// |
2135 | /// NB: This does not parse outer attributes, | |
2136 | /// and is private because it only works | |
2137 | /// correctly if called from parse_dot_or_call_expr(). | |
9cc50fc6 | 2138 | fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> { |
223e47cc LB |
2139 | maybe_whole_expr!(self); |
2140 | ||
92a42be0 SL |
2141 | // Outer attributes are already parsed and will be |
2142 | // added to the return value after the fact. | |
2143 | // | |
2144 | // Therefore, prevent sub-parser from parsing | |
2145 | // attributes by giving them a empty "already parsed" list. | |
3157f602 | 2146 | let mut attrs = ThinVec::new(); |
92a42be0 | 2147 | |
223e47cc LB |
2148 | let lo = self.span.lo; |
2149 | let mut hi = self.span.hi; | |
2150 | ||
7453a54e | 2151 | let ex: ExprKind; |
223e47cc | 2152 | |
85aaf69f | 2153 | // Note: when adding new syntax here, don't forget to adjust Token::can_begin_expr(). |
1a4d82fc JJ |
2154 | match self.token { |
2155 | token::OpenDelim(token::Paren) => { | |
9cc50fc6 | 2156 | self.bump(); |
1a4d82fc | 2157 | |
3157f602 | 2158 | attrs.extend(self.parse_inner_attributes()?); |
92a42be0 | 2159 | |
1a4d82fc JJ |
2160 | // (e) is parenthesized e |
2161 | // (e,) is a tuple with only one field, e | |
2162 | let mut es = vec![]; | |
2163 | let mut trailing_comma = false; | |
2164 | while self.token != token::CloseDelim(token::Paren) { | |
54a0048b | 2165 | es.push(self.parse_expr()?); |
5bcae85e | 2166 | self.expect_one_of(&[], &[token::Comma, token::CloseDelim(token::Paren)])?; |
1a4d82fc JJ |
2167 | if self.check(&token::Comma) { |
2168 | trailing_comma = true; | |
2169 | ||
9cc50fc6 | 2170 | self.bump(); |
1a4d82fc JJ |
2171 | } else { |
2172 | trailing_comma = false; | |
2173 | break; | |
2174 | } | |
223e47cc | 2175 | } |
9cc50fc6 | 2176 | self.bump(); |
1a4d82fc | 2177 | |
9346a6ac | 2178 | hi = self.last_span.hi; |
1a4d82fc | 2179 | return if es.len() == 1 && !trailing_comma { |
7453a54e | 2180 | Ok(self.mk_expr(lo, hi, ExprKind::Paren(es.into_iter().nth(0).unwrap()), attrs)) |
1a4d82fc | 2181 | } else { |
7453a54e | 2182 | Ok(self.mk_expr(lo, hi, ExprKind::Tup(es), attrs)) |
223e47cc | 2183 | } |
1a4d82fc JJ |
2184 | }, |
2185 | token::OpenDelim(token::Brace) => { | |
7453a54e | 2186 | return self.parse_block_expr(lo, BlockCheckMode::Default, attrs); |
1a4d82fc JJ |
2187 | }, |
2188 | token::BinOp(token::Or) | token::OrOr => { | |
62682a34 | 2189 | let lo = self.span.lo; |
7453a54e | 2190 | return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs); |
1a4d82fc | 2191 | }, |
1a4d82fc | 2192 | token::OpenDelim(token::Bracket) => { |
9cc50fc6 | 2193 | self.bump(); |
223e47cc | 2194 | |
3157f602 | 2195 | attrs.extend(self.parse_inner_attributes()?); |
92a42be0 | 2196 | |
1a4d82fc JJ |
2197 | if self.check(&token::CloseDelim(token::Bracket)) { |
2198 | // Empty vector. | |
9cc50fc6 | 2199 | self.bump(); |
7453a54e | 2200 | ex = ExprKind::Vec(Vec::new()); |
223e47cc | 2201 | } else { |
1a4d82fc | 2202 | // Nonempty vector. |
54a0048b | 2203 | let first_expr = self.parse_expr()?; |
1a4d82fc | 2204 | if self.check(&token::Semi) { |
e9174d1e | 2205 | // Repeating array syntax: [ 0; 512 ] |
9cc50fc6 | 2206 | self.bump(); |
54a0048b SL |
2207 | let count = self.parse_expr()?; |
2208 | self.expect(&token::CloseDelim(token::Bracket))?; | |
7453a54e | 2209 | ex = ExprKind::Repeat(first_expr, count); |
1a4d82fc JJ |
2210 | } else if self.check(&token::Comma) { |
2211 | // Vector with two or more elements. | |
9cc50fc6 | 2212 | self.bump(); |
54a0048b | 2213 | let remaining_exprs = self.parse_seq_to_end( |
1a4d82fc | 2214 | &token::CloseDelim(token::Bracket), |
7453a54e | 2215 | SeqSep::trailing_allowed(token::Comma), |
54a0048b SL |
2216 | |p| Ok(p.parse_expr()?) |
2217 | )?; | |
1a4d82fc | 2218 | let mut exprs = vec!(first_expr); |
62682a34 | 2219 | exprs.extend(remaining_exprs); |
7453a54e | 2220 | ex = ExprKind::Vec(exprs); |
1a4d82fc JJ |
2221 | } else { |
2222 | // Vector with one element. | |
54a0048b | 2223 | self.expect(&token::CloseDelim(token::Bracket))?; |
7453a54e | 2224 | ex = ExprKind::Vec(vec!(first_expr)); |
1a4d82fc | 2225 | } |
223e47cc | 2226 | } |
1a4d82fc | 2227 | hi = self.last_span.hi; |
223e47cc | 2228 | } |
1a4d82fc | 2229 | _ => { |
9cc50fc6 | 2230 | if self.eat_lt() { |
d9579d0f | 2231 | let (qself, path) = |
a7813a04 | 2232 | self.parse_qualified_path(PathStyle::Expr)?; |
62682a34 | 2233 | hi = path.span.hi; |
7453a54e | 2234 | return Ok(self.mk_expr(lo, hi, ExprKind::Path(Some(qself), path), attrs)); |
85aaf69f | 2235 | } |
9cc50fc6 | 2236 | if self.eat_keyword(keywords::Move) { |
62682a34 | 2237 | let lo = self.last_span.lo; |
7453a54e | 2238 | return self.parse_lambda_expr(lo, CaptureBy::Value, attrs); |
1a4d82fc | 2239 | } |
9cc50fc6 | 2240 | if self.eat_keyword(keywords::If) { |
92a42be0 | 2241 | return self.parse_if_expr(attrs); |
1a4d82fc | 2242 | } |
9cc50fc6 | 2243 | if self.eat_keyword(keywords::For) { |
c1a9b12d | 2244 | let lo = self.last_span.lo; |
92a42be0 | 2245 | return self.parse_for_expr(None, lo, attrs); |
1a4d82fc | 2246 | } |
9cc50fc6 | 2247 | if self.eat_keyword(keywords::While) { |
c1a9b12d | 2248 | let lo = self.last_span.lo; |
92a42be0 | 2249 | return self.parse_while_expr(None, lo, attrs); |
1a4d82fc JJ |
2250 | } |
2251 | if self.token.is_lifetime() { | |
3157f602 XL |
2252 | let label = Spanned { node: self.get_lifetime(), |
2253 | span: self.span }; | |
c1a9b12d | 2254 | let lo = self.span.lo; |
9cc50fc6 | 2255 | self.bump(); |
54a0048b | 2256 | self.expect(&token::Colon)?; |
9cc50fc6 | 2257 | if self.eat_keyword(keywords::While) { |
3157f602 | 2258 | return self.parse_while_expr(Some(label), lo, attrs) |
1a4d82fc | 2259 | } |
9cc50fc6 | 2260 | if self.eat_keyword(keywords::For) { |
3157f602 | 2261 | return self.parse_for_expr(Some(label), lo, attrs) |
1a4d82fc | 2262 | } |
9cc50fc6 | 2263 | if self.eat_keyword(keywords::Loop) { |
3157f602 | 2264 | return self.parse_loop_expr(Some(label), lo, attrs) |
1a4d82fc | 2265 | } |
9346a6ac | 2266 | return Err(self.fatal("expected `while`, `for`, or `loop` after a label")) |
1a4d82fc | 2267 | } |
9cc50fc6 | 2268 | if self.eat_keyword(keywords::Loop) { |
c1a9b12d | 2269 | let lo = self.last_span.lo; |
92a42be0 | 2270 | return self.parse_loop_expr(None, lo, attrs); |
1a4d82fc | 2271 | } |
9cc50fc6 | 2272 | if self.eat_keyword(keywords::Continue) { |
1a4d82fc | 2273 | let ex = if self.token.is_lifetime() { |
3157f602 | 2274 | let ex = ExprKind::Continue(Some(Spanned{ |
e9174d1e SL |
2275 | node: self.get_lifetime(), |
2276 | span: self.span | |
2277 | })); | |
9cc50fc6 | 2278 | self.bump(); |
e9174d1e | 2279 | ex |
1a4d82fc | 2280 | } else { |
3157f602 | 2281 | ExprKind::Continue(None) |
1a4d82fc | 2282 | }; |
e9174d1e | 2283 | let hi = self.last_span.hi; |
92a42be0 | 2284 | return Ok(self.mk_expr(lo, hi, ex, attrs)); |
1a4d82fc | 2285 | } |
9cc50fc6 | 2286 | if self.eat_keyword(keywords::Match) { |
92a42be0 | 2287 | return self.parse_match_expr(attrs); |
1a4d82fc | 2288 | } |
9cc50fc6 | 2289 | if self.eat_keyword(keywords::Unsafe) { |
1a4d82fc JJ |
2290 | return self.parse_block_expr( |
2291 | lo, | |
7453a54e | 2292 | BlockCheckMode::Unsafe(ast::UserProvided), |
92a42be0 | 2293 | attrs); |
1a4d82fc | 2294 | } |
9cc50fc6 | 2295 | if self.eat_keyword(keywords::Return) { |
1a4d82fc | 2296 | if self.token.can_begin_expr() { |
54a0048b | 2297 | let e = self.parse_expr()?; |
1a4d82fc | 2298 | hi = e.span.hi; |
7453a54e | 2299 | ex = ExprKind::Ret(Some(e)); |
1a4d82fc | 2300 | } else { |
7453a54e | 2301 | ex = ExprKind::Ret(None); |
1a4d82fc | 2302 | } |
9cc50fc6 | 2303 | } else if self.eat_keyword(keywords::Break) { |
1a4d82fc | 2304 | if self.token.is_lifetime() { |
7453a54e | 2305 | ex = ExprKind::Break(Some(Spanned { |
e9174d1e SL |
2306 | node: self.get_lifetime(), |
2307 | span: self.span | |
2308 | })); | |
9cc50fc6 | 2309 | self.bump(); |
1a4d82fc | 2310 | } else { |
7453a54e | 2311 | ex = ExprKind::Break(None); |
1a4d82fc | 2312 | } |
e9174d1e | 2313 | hi = self.last_span.hi; |
7453a54e SL |
2314 | } else if self.token.is_keyword(keywords::Let) { |
2315 | // Catch this syntax error here, instead of in `check_strict_keywords`, so | |
2316 | // that we can explicitly mention that let is not to be used as an expression | |
2317 | let mut db = self.fatal("expected expression, found statement (`let`)"); | |
2318 | db.note("variable declaration using `let` is a statement"); | |
2319 | return Err(db); | |
a7813a04 XL |
2320 | } else if self.token.is_path_start() { |
2321 | let pth = self.parse_path(PathStyle::Expr)?; | |
1a4d82fc JJ |
2322 | |
2323 | // `!`, as an operator, is prefix, so we know this isn't that | |
2324 | if self.check(&token::Not) { | |
2325 | // MACRO INVOCATION expression | |
9cc50fc6 | 2326 | self.bump(); |
223e47cc | 2327 | |
54a0048b SL |
2328 | let delim = self.expect_open_delim()?; |
2329 | let tts = self.parse_seq_to_end( | |
1a4d82fc | 2330 | &token::CloseDelim(delim), |
7453a54e | 2331 | SeqSep::none(), |
54a0048b | 2332 | |p| p.parse_token_tree())?; |
9346a6ac | 2333 | let hi = self.last_span.hi; |
223e47cc | 2334 | |
9346a6ac AL |
2335 | return Ok(self.mk_mac_expr(lo, |
2336 | hi, | |
3157f602 | 2337 | Mac_ { path: pth, tts: tts }, |
92a42be0 | 2338 | attrs)); |
1a4d82fc JJ |
2339 | } |
2340 | if self.check(&token::OpenDelim(token::Brace)) { | |
2341 | // This is a struct literal, unless we're prohibited | |
2342 | // from parsing struct literals here. | |
d9579d0f AL |
2343 | let prohibited = self.restrictions.contains( |
2344 | Restrictions::RESTRICTION_NO_STRUCT_LITERAL | |
2345 | ); | |
2346 | if !prohibited { | |
1a4d82fc | 2347 | // It's a struct literal. |
9cc50fc6 | 2348 | self.bump(); |
1a4d82fc JJ |
2349 | let mut fields = Vec::new(); |
2350 | let mut base = None; | |
223e47cc | 2351 | |
3157f602 | 2352 | attrs.extend(self.parse_inner_attributes()?); |
92a42be0 | 2353 | |
1a4d82fc | 2354 | while self.token != token::CloseDelim(token::Brace) { |
9cc50fc6 | 2355 | if self.eat(&token::DotDot) { |
7453a54e SL |
2356 | match self.parse_expr() { |
2357 | Ok(e) => { | |
2358 | base = Some(e); | |
2359 | } | |
2360 | Err(mut e) => { | |
2361 | e.emit(); | |
2362 | self.recover_stmt(); | |
2363 | } | |
2364 | } | |
1a4d82fc JJ |
2365 | break; |
2366 | } | |
223e47cc | 2367 | |
7453a54e SL |
2368 | match self.parse_field() { |
2369 | Ok(f) => fields.push(f), | |
2370 | Err(mut e) => { | |
2371 | e.emit(); | |
2372 | self.recover_stmt(); | |
2373 | break; | |
2374 | } | |
2375 | } | |
2376 | ||
5bcae85e SL |
2377 | match self.expect_one_of(&[token::Comma], |
2378 | &[token::CloseDelim(token::Brace)]) { | |
7453a54e SL |
2379 | Ok(()) => {} |
2380 | Err(mut e) => { | |
2381 | e.emit(); | |
2382 | self.recover_stmt(); | |
2383 | break; | |
2384 | } | |
2385 | } | |
1a4d82fc | 2386 | } |
223e47cc | 2387 | |
1a4d82fc | 2388 | hi = self.span.hi; |
54a0048b | 2389 | self.expect(&token::CloseDelim(token::Brace))?; |
7453a54e | 2390 | ex = ExprKind::Struct(pth, fields, base); |
92a42be0 | 2391 | return Ok(self.mk_expr(lo, hi, ex, attrs)); |
223e47cc | 2392 | } |
223e47cc LB |
2393 | } |
2394 | ||
2395 | hi = pth.span.hi; | |
7453a54e | 2396 | ex = ExprKind::Path(None, pth); |
1a4d82fc | 2397 | } else { |
a7813a04 XL |
2398 | match self.parse_lit() { |
2399 | Ok(lit) => { | |
2400 | hi = lit.span.hi; | |
2401 | ex = ExprKind::Lit(P(lit)); | |
2402 | } | |
2403 | Err(mut err) => { | |
2404 | err.cancel(); | |
2405 | let msg = format!("expected expression, found {}", | |
2406 | self.this_token_descr()); | |
2407 | return Err(self.fatal(&msg)); | |
2408 | } | |
2409 | } | |
223e47cc LB |
2410 | } |
2411 | } | |
223e47cc LB |
2412 | } |
2413 | ||
92a42be0 SL |
2414 | return Ok(self.mk_expr(lo, hi, ex, attrs)); |
2415 | } | |
2416 | ||
2417 | fn parse_or_use_outer_attributes(&mut self, | |
3157f602 XL |
2418 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
2419 | -> PResult<'a, ThinVec<Attribute>> { | |
92a42be0 SL |
2420 | if let Some(attrs) = already_parsed_attrs { |
2421 | Ok(attrs) | |
2422 | } else { | |
3157f602 | 2423 | self.parse_outer_attributes().map(|a| a.into()) |
92a42be0 | 2424 | } |
223e47cc LB |
2425 | } |
2426 | ||
1a4d82fc | 2427 | /// Parse a block or unsafe block |
92a42be0 | 2428 | pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode, |
3157f602 | 2429 | outer_attrs: ThinVec<Attribute>) |
9cc50fc6 | 2430 | -> PResult<'a, P<Expr>> { |
92a42be0 | 2431 | |
54a0048b | 2432 | self.expect(&token::OpenDelim(token::Brace))?; |
92a42be0 | 2433 | |
3157f602 XL |
2434 | let mut attrs = outer_attrs; |
2435 | attrs.extend(self.parse_inner_attributes()?); | |
92a42be0 | 2436 | |
54a0048b | 2437 | let blk = self.parse_block_tail(lo, blk_mode)?; |
7453a54e | 2438 | return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs)); |
223e47cc LB |
2439 | } |
2440 | ||
1a4d82fc | 2441 | /// parse a.b or a(13) or a[4] or just a |
92a42be0 | 2442 | pub fn parse_dot_or_call_expr(&mut self, |
3157f602 | 2443 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
9cc50fc6 | 2444 | -> PResult<'a, P<Expr>> { |
54a0048b | 2445 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; |
92a42be0 | 2446 | |
7453a54e | 2447 | let b = self.parse_bottom_expr(); |
54a0048b | 2448 | let (span, b) = self.interpolated_or_expr_span(b)?; |
7453a54e | 2449 | self.parse_dot_or_call_expr_with(b, span.lo, attrs) |
92a42be0 SL |
2450 | } |
2451 | ||
2452 | pub fn parse_dot_or_call_expr_with(&mut self, | |
2453 | e0: P<Expr>, | |
7453a54e | 2454 | lo: BytePos, |
3157f602 | 2455 | mut attrs: ThinVec<Attribute>) |
9cc50fc6 | 2456 | -> PResult<'a, P<Expr>> { |
92a42be0 SL |
2457 | // Stitch the list of outer attributes onto the return value. |
2458 | // A little bit ugly, but the best way given the current code | |
2459 | // structure | |
7453a54e | 2460 | self.parse_dot_or_call_expr_with_(e0, lo) |
92a42be0 SL |
2461 | .map(|expr| |
2462 | expr.map(|mut expr| { | |
3157f602 XL |
2463 | attrs.extend::<Vec<_>>(expr.attrs.into()); |
2464 | expr.attrs = attrs; | |
92a42be0 | 2465 | match expr.node { |
7453a54e | 2466 | ExprKind::If(..) | ExprKind::IfLet(..) => { |
3157f602 | 2467 | if !expr.attrs.is_empty() { |
92a42be0 | 2468 | // Just point to the first attribute in there... |
3157f602 | 2469 | let span = expr.attrs[0].span; |
92a42be0 SL |
2470 | |
2471 | self.span_err(span, | |
2472 | "attributes are not yet allowed on `if` \ | |
2473 | expressions"); | |
2474 | } | |
2475 | } | |
2476 | _ => {} | |
2477 | } | |
2478 | expr | |
2479 | }) | |
2480 | ) | |
223e47cc LB |
2481 | } |
2482 | ||
7453a54e SL |
2483 | // Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue |
2484 | // parsing into an expression. | |
2485 | fn parse_dot_suffix(&mut self, | |
2486 | ident: Ident, | |
2487 | ident_span: Span, | |
2488 | self_value: P<Expr>, | |
2489 | lo: BytePos) | |
2490 | -> PResult<'a, P<Expr>> { | |
2491 | let (_, tys, bindings) = if self.eat(&token::ModSep) { | |
54a0048b SL |
2492 | self.expect_lt()?; |
2493 | self.parse_generic_values_after_lt()? | |
7453a54e SL |
2494 | } else { |
2495 | (Vec::new(), Vec::new(), Vec::new()) | |
2496 | }; | |
2497 | ||
2498 | if !bindings.is_empty() { | |
2499 | let last_span = self.last_span; | |
2500 | self.span_err(last_span, "type bindings are only permitted on trait paths"); | |
2501 | } | |
2502 | ||
2503 | Ok(match self.token { | |
2504 | // expr.f() method call. | |
2505 | token::OpenDelim(token::Paren) => { | |
54a0048b | 2506 | let mut es = self.parse_unspanned_seq( |
7453a54e SL |
2507 | &token::OpenDelim(token::Paren), |
2508 | &token::CloseDelim(token::Paren), | |
2509 | SeqSep::trailing_allowed(token::Comma), | |
54a0048b SL |
2510 | |p| Ok(p.parse_expr()?) |
2511 | )?; | |
7453a54e SL |
2512 | let hi = self.last_span.hi; |
2513 | ||
2514 | es.insert(0, self_value); | |
2515 | let id = spanned(ident_span.lo, ident_span.hi, ident); | |
2516 | let nd = self.mk_method_call(id, tys, es); | |
3157f602 | 2517 | self.mk_expr(lo, hi, nd, ThinVec::new()) |
7453a54e SL |
2518 | } |
2519 | // Field access. | |
2520 | _ => { | |
2521 | if !tys.is_empty() { | |
2522 | let last_span = self.last_span; | |
2523 | self.span_err(last_span, | |
2524 | "field expressions may not \ | |
2525 | have type parameters"); | |
2526 | } | |
2527 | ||
2528 | let id = spanned(ident_span.lo, ident_span.hi, ident); | |
2529 | let field = self.mk_field(self_value, id); | |
3157f602 | 2530 | self.mk_expr(lo, ident_span.hi, field, ThinVec::new()) |
7453a54e SL |
2531 | } |
2532 | }) | |
2533 | } | |
2534 | ||
2535 | fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: BytePos) -> PResult<'a, P<Expr>> { | |
223e47cc | 2536 | let mut e = e0; |
223e47cc LB |
2537 | let mut hi; |
2538 | loop { | |
54a0048b SL |
2539 | // expr? |
2540 | while self.eat(&token::Question) { | |
a7813a04 | 2541 | let hi = self.last_span.hi; |
3157f602 | 2542 | e = self.mk_expr(lo, hi, ExprKind::Try(e), ThinVec::new()); |
54a0048b SL |
2543 | } |
2544 | ||
223e47cc | 2545 | // expr.f |
9cc50fc6 | 2546 | if self.eat(&token::Dot) { |
1a4d82fc | 2547 | match self.token { |
a7813a04 | 2548 | token::Ident(i) => { |
7453a54e | 2549 | let dot_pos = self.last_span.hi; |
223e47cc | 2550 | hi = self.span.hi; |
9cc50fc6 | 2551 | self.bump(); |
1a4d82fc | 2552 | |
54a0048b | 2553 | e = self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e, lo)?; |
1a4d82fc JJ |
2554 | } |
2555 | token::Literal(token::Integer(n), suf) => { | |
2556 | let sp = self.span; | |
2557 | ||
2558 | // A tuple index may not have a suffix | |
2559 | self.expect_no_suffix(sp, "tuple index", suf); | |
2560 | ||
2561 | let dot = self.last_span.hi; | |
2562 | hi = self.span.hi; | |
9cc50fc6 | 2563 | self.bump(); |
1a4d82fc | 2564 | |
85aaf69f | 2565 | let index = n.as_str().parse::<usize>().ok(); |
1a4d82fc JJ |
2566 | match index { |
2567 | Some(n) => { | |
2568 | let id = spanned(dot, hi, n); | |
2569 | let field = self.mk_tup_field(e, id); | |
3157f602 | 2570 | e = self.mk_expr(lo, hi, field, ThinVec::new()); |
1a4d82fc JJ |
2571 | } |
2572 | None => { | |
2573 | let last_span = self.last_span; | |
2574 | self.span_err(last_span, "invalid tuple or tuple struct index"); | |
223e47cc LB |
2575 | } |
2576 | } | |
2577 | } | |
1a4d82fc | 2578 | token::Literal(token::Float(n), _suf) => { |
9cc50fc6 | 2579 | self.bump(); |
1a4d82fc JJ |
2580 | let last_span = self.last_span; |
2581 | let fstr = n.as_str(); | |
9cc50fc6 SL |
2582 | let mut err = self.diagnostic().struct_span_err(last_span, |
2583 | &format!("unexpected token: `{}`", n.as_str())); | |
c34b1796 | 2584 | if fstr.chars().all(|x| "0123456789.".contains(x)) { |
85aaf69f | 2585 | let float = match fstr.parse::<f64>().ok() { |
1a4d82fc JJ |
2586 | Some(f) => f, |
2587 | None => continue, | |
2588 | }; | |
a7813a04 XL |
2589 | err.help(&format!("try parenthesizing the first index; e.g., `(foo.{}){}`", |
2590 | float.trunc() as usize, | |
2591 | format!(".{}", fstr.splitn(2, ".").last().unwrap()))); | |
1a4d82fc | 2592 | } |
7453a54e | 2593 | return Err(err); |
1a4d82fc JJ |
2594 | |
2595 | } | |
7453a54e SL |
2596 | _ => { |
2597 | // FIXME Could factor this out into non_fatal_unexpected or something. | |
2598 | let actual = self.this_token_to_string(); | |
2599 | self.span_err(self.span, &format!("unexpected token: `{}`", actual)); | |
2600 | ||
2601 | let dot_pos = self.last_span.hi; | |
a7813a04 | 2602 | e = self.parse_dot_suffix(keywords::Invalid.ident(), |
54a0048b SL |
2603 | mk_sp(dot_pos, dot_pos), |
2604 | e, lo)?; | |
7453a54e | 2605 | } |
223e47cc | 2606 | } |
1a4d82fc | 2607 | continue; |
223e47cc | 2608 | } |
7453a54e | 2609 | if self.expr_is_complete(&e) { break; } |
1a4d82fc | 2610 | match self.token { |
223e47cc | 2611 | // expr(...) |
1a4d82fc | 2612 | token::OpenDelim(token::Paren) => { |
54a0048b | 2613 | let es = self.parse_unspanned_seq( |
1a4d82fc JJ |
2614 | &token::OpenDelim(token::Paren), |
2615 | &token::CloseDelim(token::Paren), | |
7453a54e | 2616 | SeqSep::trailing_allowed(token::Comma), |
54a0048b SL |
2617 | |p| Ok(p.parse_expr()?) |
2618 | )?; | |
1a4d82fc | 2619 | hi = self.last_span.hi; |
223e47cc | 2620 | |
1a4d82fc | 2621 | let nd = self.mk_call(e, es); |
3157f602 | 2622 | e = self.mk_expr(lo, hi, nd, ThinVec::new()); |
223e47cc LB |
2623 | } |
2624 | ||
2625 | // expr[...] | |
1a4d82fc JJ |
2626 | // Could be either an index expression or a slicing expression. |
2627 | token::OpenDelim(token::Bracket) => { | |
9cc50fc6 | 2628 | self.bump(); |
54a0048b | 2629 | let ix = self.parse_expr()?; |
c34b1796 | 2630 | hi = self.span.hi; |
5bcae85e | 2631 | self.expect(&token::CloseDelim(token::Bracket))?; |
c34b1796 | 2632 | let index = self.mk_index(e, ix); |
3157f602 | 2633 | e = self.mk_expr(lo, hi, index, ThinVec::new()) |
1a4d82fc | 2634 | } |
9346a6ac | 2635 | _ => return Ok(e) |
223e47cc LB |
2636 | } |
2637 | } | |
9346a6ac | 2638 | return Ok(e); |
223e47cc LB |
2639 | } |
2640 | ||
1a4d82fc | 2641 | // Parse unquoted tokens after a `$` in a token tree |
9cc50fc6 | 2642 | fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> { |
1a4d82fc | 2643 | let mut sp = self.span; |
a7813a04 | 2644 | let name = match self.token { |
1a4d82fc | 2645 | token::Dollar => { |
9cc50fc6 | 2646 | self.bump(); |
223e47cc | 2647 | |
1a4d82fc | 2648 | if self.token == token::OpenDelim(token::Paren) { |
54a0048b | 2649 | let Spanned { node: seq, span: seq_span } = self.parse_seq( |
1a4d82fc JJ |
2650 | &token::OpenDelim(token::Paren), |
2651 | &token::CloseDelim(token::Paren), | |
7453a54e | 2652 | SeqSep::none(), |
223e47cc | 2653 | |p| p.parse_token_tree() |
54a0048b SL |
2654 | )?; |
2655 | let (sep, repeat) = self.parse_sep_and_kleene_op()?; | |
85aaf69f | 2656 | let name_num = macro_parser::count_names(&seq); |
5bcae85e SL |
2657 | return Ok(TokenTree::Sequence(mk_sp(sp.lo, seq_span.hi), |
2658 | Rc::new(SequenceRepetition { | |
2659 | tts: seq, | |
2660 | separator: sep, | |
2661 | op: repeat, | |
2662 | num_captures: name_num | |
2663 | }))); | |
a7813a04 | 2664 | } else if self.token.is_keyword(keywords::Crate) { |
9cc50fc6 | 2665 | self.bump(); |
92a42be0 | 2666 | return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))); |
223e47cc | 2667 | } else { |
1a4d82fc | 2668 | sp = mk_sp(sp.lo, self.span.hi); |
3157f602 XL |
2669 | self.parse_ident().unwrap_or_else(|mut e| { |
2670 | e.emit(); | |
2671 | keywords::Invalid.ident() | |
2672 | }) | |
223e47cc | 2673 | } |
223e47cc | 2674 | } |
a7813a04 | 2675 | token::SubstNt(name) => { |
9cc50fc6 | 2676 | self.bump(); |
a7813a04 | 2677 | name |
1a4d82fc JJ |
2678 | } |
2679 | _ => unreachable!() | |
2680 | }; | |
2681 | // continue by trying to parse the `:ident` after `$name` | |
a7813a04 XL |
2682 | if self.token == token::Colon && |
2683 | self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword()) { | |
9cc50fc6 | 2684 | self.bump(); |
1a4d82fc | 2685 | sp = mk_sp(sp.lo, self.span.hi); |
54a0048b | 2686 | let nt_kind = self.parse_ident()?; |
a7813a04 | 2687 | Ok(TokenTree::Token(sp, MatchNt(name, nt_kind))) |
1a4d82fc | 2688 | } else { |
a7813a04 | 2689 | Ok(TokenTree::Token(sp, SubstNt(name))) |
223e47cc | 2690 | } |
1a4d82fc | 2691 | } |
223e47cc | 2692 | |
9cc50fc6 | 2693 | pub fn check_unknown_macro_variable(&mut self) { |
5bcae85e | 2694 | if self.quote_depth == 0 && !self.parsing_token_tree { |
1a4d82fc | 2695 | match self.token { |
a7813a04 | 2696 | token::SubstNt(name) => |
9cc50fc6 | 2697 | self.fatal(&format!("unknown macro variable `{}`", name)).emit(), |
1a4d82fc JJ |
2698 | _ => {} |
2699 | } | |
223e47cc | 2700 | } |
1a4d82fc | 2701 | } |
223e47cc | 2702 | |
1a4d82fc JJ |
2703 | /// Parse an optional separator followed by a Kleene-style |
2704 | /// repetition token (+ or *). | |
9cc50fc6 | 2705 | pub fn parse_sep_and_kleene_op(&mut self) |
3157f602 XL |
2706 | -> PResult<'a, (Option<token::Token>, tokenstream::KleeneOp)> { |
2707 | fn parse_kleene_op<'a>(parser: &mut Parser<'a>) -> | |
2708 | PResult<'a, Option<tokenstream::KleeneOp>> { | |
1a4d82fc JJ |
2709 | match parser.token { |
2710 | token::BinOp(token::Star) => { | |
9cc50fc6 | 2711 | parser.bump(); |
3157f602 | 2712 | Ok(Some(tokenstream::KleeneOp::ZeroOrMore)) |
1a4d82fc JJ |
2713 | }, |
2714 | token::BinOp(token::Plus) => { | |
9cc50fc6 | 2715 | parser.bump(); |
3157f602 | 2716 | Ok(Some(tokenstream::KleeneOp::OneOrMore)) |
1a4d82fc | 2717 | }, |
9346a6ac | 2718 | _ => Ok(None) |
223e47cc | 2719 | } |
1a4d82fc JJ |
2720 | }; |
2721 | ||
3157f602 XL |
2722 | if let Some(kleene_op) = parse_kleene_op(self)? { |
2723 | return Ok((None, kleene_op)); | |
223e47cc | 2724 | } |
223e47cc | 2725 | |
9cc50fc6 | 2726 | let separator = self.bump_and_get(); |
54a0048b | 2727 | match parse_kleene_op(self)? { |
9346a6ac AL |
2728 | Some(zerok) => Ok((Some(separator), zerok)), |
2729 | None => return Err(self.fatal("expected `*` or `+`")) | |
223e47cc | 2730 | } |
223e47cc LB |
2731 | } |
2732 | ||
1a4d82fc | 2733 | /// parse a single token tree from the input. |
9cc50fc6 | 2734 | pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> { |
1a4d82fc | 2735 | // FIXME #6994: currently, this is too eager. It |
92a42be0 | 2736 | // parses token trees but also identifies TokenType::Sequence's |
1a4d82fc JJ |
2737 | // and token::SubstNt's; it's too early to know yet |
2738 | // whether something will be a nonterminal or a seq | |
2739 | // yet. | |
2740 | maybe_whole!(deref self, NtTT); | |
2741 | ||
1a4d82fc JJ |
2742 | match self.token { |
2743 | token::Eof => { | |
9cc50fc6 | 2744 | let mut err: DiagnosticBuilder<'a> = |
7453a54e SL |
2745 | self.diagnostic().struct_span_err(self.span, |
2746 | "this file contains an un-closed delimiter"); | |
54a0048b SL |
2747 | for &(_, sp) in &self.open_braces { |
2748 | err.span_help(sp, "did you mean to close this delimiter?"); | |
1a4d82fc | 2749 | } |
7453a54e SL |
2750 | |
2751 | Err(err) | |
1a4d82fc JJ |
2752 | }, |
2753 | token::OpenDelim(delim) => { | |
5bcae85e | 2754 | let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true); |
1a4d82fc JJ |
2755 | // The span for beginning of the delimited section |
2756 | let pre_span = self.span; | |
223e47cc | 2757 | |
1a4d82fc | 2758 | // Parse the open delimiter. |
54a0048b | 2759 | self.open_braces.push((delim, self.span)); |
1a4d82fc | 2760 | let open_span = self.span; |
9cc50fc6 | 2761 | self.bump(); |
223e47cc | 2762 | |
54a0048b SL |
2763 | // Parse the token trees within the delimiters. |
2764 | // We stop at any delimiter so we can try to recover if the user | |
2765 | // uses an incorrect delimiter. | |
2766 | let tts = self.parse_seq_to_before_tokens(&[&token::CloseDelim(token::Brace), | |
2767 | &token::CloseDelim(token::Paren), | |
2768 | &token::CloseDelim(token::Bracket)], | |
2769 | SeqSep::none(), | |
2770 | |p| p.parse_token_tree(), | |
2771 | |mut e| e.emit()); | |
223e47cc | 2772 | |
1a4d82fc | 2773 | let close_span = self.span; |
1a4d82fc | 2774 | // Expand to cover the entire delimited token tree |
85aaf69f | 2775 | let span = Span { hi: close_span.hi, ..pre_span }; |
223e47cc | 2776 | |
54a0048b | 2777 | match self.token { |
3157f602 | 2778 | // Correct delimiter. |
54a0048b SL |
2779 | token::CloseDelim(d) if d == delim => { |
2780 | self.open_braces.pop().unwrap(); | |
2781 | ||
2782 | // Parse the close delimiter. | |
2783 | self.bump(); | |
2784 | } | |
3157f602 | 2785 | // Incorrect delimiter. |
54a0048b SL |
2786 | token::CloseDelim(other) => { |
2787 | let token_str = self.this_token_to_string(); | |
2788 | let mut err = self.diagnostic().struct_span_err(self.span, | |
2789 | &format!("incorrect close delimiter: `{}`", token_str)); | |
2790 | // This is a conservative error: only report the last unclosed delimiter. | |
2791 | // The previous unclosed delimiters could actually be closed! The parser | |
2792 | // just hasn't gotten to them yet. | |
2793 | if let Some(&(_, sp)) = self.open_braces.last() { | |
2794 | err.span_note(sp, "unclosed delimiter"); | |
2795 | }; | |
2796 | err.emit(); | |
2797 | ||
2798 | self.open_braces.pop().unwrap(); | |
2799 | ||
3157f602 | 2800 | // If the incorrect delimiter matches an earlier opening |
54a0048b | 2801 | // delimiter, then don't consume it (it can be used to |
3157f602 | 2802 | // close the earlier one). Otherwise, consume it. |
54a0048b SL |
2803 | // E.g., we try to recover from: |
2804 | // fn foo() { | |
2805 | // bar(baz( | |
2806 | // } // Incorrect delimiter but matches the earlier `{` | |
2807 | if !self.open_braces.iter().any(|&(b, _)| b == other) { | |
2808 | self.bump(); | |
2809 | } | |
2810 | } | |
2811 | token::Eof => { | |
2812 | // Silently recover, the EOF token will be seen again | |
2813 | // and an error emitted then. Thus we don't pop from | |
2814 | // self.open_braces here. | |
2815 | }, | |
3157f602 | 2816 | _ => {} |
54a0048b SL |
2817 | } |
2818 | ||
5bcae85e SL |
2819 | self.parsing_token_tree = parsing_token_tree; |
2820 | Ok(TokenTree::Delimited(span, Rc::new(Delimited { | |
1a4d82fc JJ |
2821 | delim: delim, |
2822 | open_span: open_span, | |
2823 | tts: tts, | |
2824 | close_span: close_span, | |
5bcae85e | 2825 | }))) |
1a4d82fc | 2826 | }, |
7453a54e SL |
2827 | _ => { |
2828 | // invariants: the current token is not a left-delimiter, | |
2829 | // not an EOF, and not the desired right-delimiter (if | |
2830 | // it were, parse_seq_to_before_end would have prevented | |
3157f602 | 2831 | // reaching this point). |
7453a54e SL |
2832 | maybe_whole!(deref self, NtTT); |
2833 | match self.token { | |
2834 | token::CloseDelim(_) => { | |
54a0048b SL |
2835 | // An unexpected closing delimiter (i.e., there is no |
2836 | // matching opening delimiter). | |
7453a54e | 2837 | let token_str = self.this_token_to_string(); |
54a0048b SL |
2838 | let err = self.diagnostic().struct_span_err(self.span, |
2839 | &format!("unexpected close delimiter: `{}`", token_str)); | |
7453a54e SL |
2840 | Err(err) |
2841 | }, | |
2842 | /* we ought to allow different depths of unquotation */ | |
2843 | token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { | |
2844 | self.parse_unquoted() | |
2845 | } | |
2846 | _ => { | |
2847 | Ok(TokenTree::Token(self.span, self.bump_and_get())) | |
2848 | } | |
2849 | } | |
2850 | } | |
1a4d82fc | 2851 | } |
223e47cc LB |
2852 | } |
2853 | ||
1a4d82fc JJ |
2854 | // parse a stream of tokens into a list of TokenTree's, |
2855 | // up to EOF. | |
9cc50fc6 | 2856 | pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> { |
1a4d82fc JJ |
2857 | let mut tts = Vec::new(); |
2858 | while self.token != token::Eof { | |
54a0048b | 2859 | tts.push(self.parse_token_tree()?); |
1a4d82fc | 2860 | } |
9346a6ac | 2861 | Ok(tts) |
223e47cc LB |
2862 | } |
2863 | ||
92a42be0 SL |
2864 | /// Parse a prefix-unary-operator expr |
2865 | pub fn parse_prefix_expr(&mut self, | |
3157f602 | 2866 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
9cc50fc6 | 2867 | -> PResult<'a, P<Expr>> { |
54a0048b | 2868 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; |
223e47cc | 2869 | let lo = self.span.lo; |
970d7e83 | 2870 | let hi; |
85aaf69f | 2871 | // Note: when adding new unary operators, don't forget to adjust Token::can_begin_expr() |
92a42be0 SL |
2872 | let ex = match self.token { |
2873 | token::Not => { | |
9cc50fc6 | 2874 | self.bump(); |
7453a54e | 2875 | let e = self.parse_prefix_expr(None); |
54a0048b | 2876 | let (span, e) = self.interpolated_or_expr_span(e)?; |
7453a54e SL |
2877 | hi = span.hi; |
2878 | self.mk_unary(UnOp::Not, e) | |
92a42be0 SL |
2879 | } |
2880 | token::BinOp(token::Minus) => { | |
9cc50fc6 | 2881 | self.bump(); |
7453a54e | 2882 | let e = self.parse_prefix_expr(None); |
54a0048b | 2883 | let (span, e) = self.interpolated_or_expr_span(e)?; |
7453a54e SL |
2884 | hi = span.hi; |
2885 | self.mk_unary(UnOp::Neg, e) | |
92a42be0 SL |
2886 | } |
2887 | token::BinOp(token::Star) => { | |
9cc50fc6 | 2888 | self.bump(); |
7453a54e | 2889 | let e = self.parse_prefix_expr(None); |
54a0048b | 2890 | let (span, e) = self.interpolated_or_expr_span(e)?; |
7453a54e SL |
2891 | hi = span.hi; |
2892 | self.mk_unary(UnOp::Deref, e) | |
92a42be0 SL |
2893 | } |
2894 | token::BinOp(token::And) | token::AndAnd => { | |
54a0048b SL |
2895 | self.expect_and()?; |
2896 | let m = self.parse_mutability()?; | |
7453a54e | 2897 | let e = self.parse_prefix_expr(None); |
54a0048b | 2898 | let (span, e) = self.interpolated_or_expr_span(e)?; |
7453a54e SL |
2899 | hi = span.hi; |
2900 | ExprKind::AddrOf(m, e) | |
92a42be0 SL |
2901 | } |
2902 | token::Ident(..) if self.token.is_keyword(keywords::In) => { | |
9cc50fc6 | 2903 | self.bump(); |
54a0048b | 2904 | let place = self.parse_expr_res( |
92a42be0 SL |
2905 | Restrictions::RESTRICTION_NO_STRUCT_LITERAL, |
2906 | None, | |
54a0048b SL |
2907 | )?; |
2908 | let blk = self.parse_block()?; | |
92a42be0 SL |
2909 | let span = blk.span; |
2910 | hi = span.hi; | |
3157f602 | 2911 | let blk_expr = self.mk_expr(span.lo, hi, ExprKind::Block(blk), ThinVec::new()); |
7453a54e | 2912 | ExprKind::InPlace(place, blk_expr) |
92a42be0 SL |
2913 | } |
2914 | token::Ident(..) if self.token.is_keyword(keywords::Box) => { | |
9cc50fc6 | 2915 | self.bump(); |
7453a54e | 2916 | let e = self.parse_prefix_expr(None); |
54a0048b | 2917 | let (span, e) = self.interpolated_or_expr_span(e)?; |
7453a54e SL |
2918 | hi = span.hi; |
2919 | ExprKind::Box(e) | |
92a42be0 SL |
2920 | } |
2921 | _ => return self.parse_dot_or_call_expr(Some(attrs)) | |
2922 | }; | |
2923 | return Ok(self.mk_expr(lo, hi, ex, attrs)); | |
223e47cc LB |
2924 | } |
2925 | ||
92a42be0 SL |
2926 | /// Parse an associative expression |
2927 | /// | |
2928 | /// This parses an expression accounting for associativity and precedence of the operators in | |
2929 | /// the expression. | |
2930 | pub fn parse_assoc_expr(&mut self, | |
3157f602 | 2931 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
9cc50fc6 | 2932 | -> PResult<'a, P<Expr>> { |
92a42be0 | 2933 | self.parse_assoc_expr_with(0, already_parsed_attrs.into()) |
223e47cc LB |
2934 | } |
2935 | ||
92a42be0 SL |
2936 | /// Parse an associative expression with operators of at least `min_prec` precedence |
2937 | pub fn parse_assoc_expr_with(&mut self, | |
2938 | min_prec: usize, | |
2939 | lhs: LhsExpr) | |
9cc50fc6 | 2940 | -> PResult<'a, P<Expr>> { |
92a42be0 SL |
2941 | let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs { |
2942 | expr | |
2943 | } else { | |
2944 | let attrs = match lhs { | |
2945 | LhsExpr::AttributesParsed(attrs) => Some(attrs), | |
2946 | _ => None, | |
2947 | }; | |
54a0048b | 2948 | if self.token == token::DotDot || self.token == token::DotDotDot { |
92a42be0 SL |
2949 | return self.parse_prefix_range_expr(attrs); |
2950 | } else { | |
54a0048b | 2951 | self.parse_prefix_expr(attrs)? |
92a42be0 SL |
2952 | } |
2953 | }; | |
7453a54e | 2954 | |
7453a54e | 2955 | if self.expr_is_complete(&lhs) { |
92a42be0 SL |
2956 | // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 |
2957 | return Ok(lhs); | |
2958 | } | |
1a4d82fc | 2959 | self.expected_tokens.push(TokenType::Operator); |
92a42be0 | 2960 | while let Some(op) = AssocOp::from_token(&self.token) { |
7453a54e SL |
2961 | |
2962 | let lhs_span = if self.last_token_interpolated { | |
2963 | self.last_span | |
2964 | } else { | |
2965 | lhs.span | |
2966 | }; | |
2967 | ||
92a42be0 SL |
2968 | let cur_op_span = self.span; |
2969 | let restrictions = if op.is_assign_like() { | |
2970 | self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL | |
2971 | } else { | |
2972 | self.restrictions | |
2973 | }; | |
2974 | if op.precedence() < min_prec { | |
2975 | break; | |
2976 | } | |
9cc50fc6 | 2977 | self.bump(); |
92a42be0 | 2978 | if op.is_comparison() { |
7453a54e | 2979 | self.check_no_chained_comparison(&lhs, &op); |
92a42be0 SL |
2980 | } |
2981 | // Special cases: | |
2982 | if op == AssocOp::As { | |
54a0048b | 2983 | let rhs = self.parse_ty()?; |
3157f602 XL |
2984 | let (lo, hi) = (lhs_span.lo, rhs.span.hi); |
2985 | lhs = self.mk_expr(lo, hi, ExprKind::Cast(lhs, rhs), ThinVec::new()); | |
92a42be0 | 2986 | continue |
9cc50fc6 | 2987 | } else if op == AssocOp::Colon { |
54a0048b | 2988 | let rhs = self.parse_ty()?; |
3157f602 XL |
2989 | let (lo, hi) = (lhs_span.lo, rhs.span.hi); |
2990 | lhs = self.mk_expr(lo, hi, ExprKind::Type(lhs, rhs), ThinVec::new()); | |
9cc50fc6 | 2991 | continue |
54a0048b SL |
2992 | } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot { |
2993 | // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to | |
2994 | // generalise it to the Fixity::None code. | |
2995 | // | |
2996 | // We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other | |
2997 | // two variants are handled with `parse_prefix_range_expr` call above. | |
2998 | let rhs = if self.is_at_start_of_range_notation_rhs() { | |
a7813a04 XL |
2999 | Some(self.parse_assoc_expr_with(op.precedence() + 1, |
3000 | LhsExpr::NotYetParsed)?) | |
54a0048b SL |
3001 | } else { |
3002 | None | |
3003 | }; | |
3004 | let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs { | |
3005 | x.span | |
3006 | } else { | |
3007 | cur_op_span | |
3008 | }); | |
3009 | let limits = if op == AssocOp::DotDot { | |
3010 | RangeLimits::HalfOpen | |
3011 | } else { | |
3012 | RangeLimits::Closed | |
3013 | }; | |
3014 | ||
3015 | let r = try!(self.mk_range(Some(lhs), rhs, limits)); | |
3157f602 | 3016 | lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, ThinVec::new()); |
54a0048b | 3017 | break |
92a42be0 | 3018 | } |
1a4d82fc | 3019 | |
54a0048b | 3020 | let rhs = match op.fixity() { |
9cc50fc6 SL |
3021 | Fixity::Right => self.with_res( |
3022 | restrictions - Restrictions::RESTRICTION_STMT_EXPR, | |
3023 | |this| { | |
3024 | this.parse_assoc_expr_with(op.precedence(), | |
3025 | LhsExpr::NotYetParsed) | |
92a42be0 | 3026 | }), |
9cc50fc6 SL |
3027 | Fixity::Left => self.with_res( |
3028 | restrictions - Restrictions::RESTRICTION_STMT_EXPR, | |
3029 | |this| { | |
3030 | this.parse_assoc_expr_with(op.precedence() + 1, | |
3031 | LhsExpr::NotYetParsed) | |
92a42be0 SL |
3032 | }), |
3033 | // We currently have no non-associative operators that are not handled above by | |
3034 | // the special cases. The code is here only for future convenience. | |
9cc50fc6 SL |
3035 | Fixity::None => self.with_res( |
3036 | restrictions - Restrictions::RESTRICTION_STMT_EXPR, | |
3037 | |this| { | |
3038 | this.parse_assoc_expr_with(op.precedence() + 1, | |
3039 | LhsExpr::NotYetParsed) | |
92a42be0 | 3040 | }), |
54a0048b | 3041 | }?; |
92a42be0 | 3042 | |
3157f602 | 3043 | let (lo, hi) = (lhs_span.lo, rhs.span.hi); |
92a42be0 SL |
3044 | lhs = match op { |
3045 | AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | | |
3046 | AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor | | |
3047 | AssocOp::BitAnd | AssocOp::BitOr | AssocOp::ShiftLeft | AssocOp::ShiftRight | | |
3048 | AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual | | |
3049 | AssocOp::Greater | AssocOp::GreaterEqual => { | |
3050 | let ast_op = op.to_ast_binop().unwrap(); | |
92a42be0 | 3051 | let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs); |
3157f602 | 3052 | self.mk_expr(lo, hi, binary, ThinVec::new()) |
1a4d82fc | 3053 | } |
92a42be0 | 3054 | AssocOp::Assign => |
3157f602 | 3055 | self.mk_expr(lo, hi, ExprKind::Assign(lhs, rhs), ThinVec::new()), |
92a42be0 | 3056 | AssocOp::Inplace => |
3157f602 | 3057 | self.mk_expr(lo, hi, ExprKind::InPlace(lhs, rhs), ThinVec::new()), |
92a42be0 SL |
3058 | AssocOp::AssignOp(k) => { |
3059 | let aop = match k { | |
7453a54e SL |
3060 | token::Plus => BinOpKind::Add, |
3061 | token::Minus => BinOpKind::Sub, | |
3062 | token::Star => BinOpKind::Mul, | |
3063 | token::Slash => BinOpKind::Div, | |
3064 | token::Percent => BinOpKind::Rem, | |
3065 | token::Caret => BinOpKind::BitXor, | |
3066 | token::And => BinOpKind::BitAnd, | |
3067 | token::Or => BinOpKind::BitOr, | |
3068 | token::Shl => BinOpKind::Shl, | |
3069 | token::Shr => BinOpKind::Shr, | |
92a42be0 | 3070 | }; |
92a42be0 | 3071 | let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs); |
3157f602 | 3072 | self.mk_expr(lo, hi, aopexpr, ThinVec::new()) |
223e47cc | 3073 | } |
54a0048b SL |
3074 | AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => { |
3075 | self.bug("As, Colon, DotDot or DotDotDot branch reached") | |
9cc50fc6 | 3076 | } |
92a42be0 SL |
3077 | }; |
3078 | ||
3079 | if op.fixity() == Fixity::None { break } | |
223e47cc | 3080 | } |
92a42be0 | 3081 | Ok(lhs) |
223e47cc LB |
3082 | } |
3083 | ||
1a4d82fc JJ |
3084 | /// Produce an error if comparison operators are chained (RFC #558). |
3085 | /// We only need to check lhs, not rhs, because all comparison ops | |
3086 | /// have same precedence and are left-associative | |
92a42be0 SL |
3087 | fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) { |
3088 | debug_assert!(outer_op.is_comparison()); | |
1a4d82fc | 3089 | match lhs.node { |
7453a54e | 3090 | ExprKind::Binary(op, _, _) if op.node.is_comparison() => { |
85aaf69f SL |
3091 | // respan to include both operators |
3092 | let op_span = mk_sp(op.span.lo, self.span.hi); | |
9cc50fc6 | 3093 | let mut err = self.diagnostic().struct_span_err(op_span, |
85aaf69f | 3094 | "chained comparison operators require parentheses"); |
7453a54e | 3095 | if op.node == BinOpKind::Lt && *outer_op == AssocOp::Greater { |
a7813a04 | 3096 | err.help( |
85aaf69f | 3097 | "use `::<...>` instead of `<...>` if you meant to specify type arguments"); |
1a4d82fc | 3098 | } |
9cc50fc6 | 3099 | err.emit(); |
1a4d82fc JJ |
3100 | } |
3101 | _ => {} | |
3102 | } | |
3103 | } | |
3104 | ||
54a0048b | 3105 | /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr` |
92a42be0 | 3106 | fn parse_prefix_range_expr(&mut self, |
3157f602 | 3107 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
9cc50fc6 | 3108 | -> PResult<'a, P<Expr>> { |
54a0048b SL |
3109 | debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); |
3110 | let tok = self.token.clone(); | |
3111 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; | |
92a42be0 SL |
3112 | let lo = self.span.lo; |
3113 | let mut hi = self.span.hi; | |
9cc50fc6 | 3114 | self.bump(); |
92a42be0 | 3115 | let opt_end = if self.is_at_start_of_range_notation_rhs() { |
54a0048b SL |
3116 | // RHS must be parsed with more associativity than the dots. |
3117 | let next_prec = AssocOp::from_token(&tok).unwrap().precedence() + 1; | |
3118 | Some(self.parse_assoc_expr_with(next_prec, | |
3119 | LhsExpr::NotYetParsed) | |
3120 | .map(|x|{ | |
3121 | hi = x.span.hi; | |
3122 | x | |
3123 | })?) | |
92a42be0 SL |
3124 | } else { |
3125 | None | |
3126 | }; | |
54a0048b SL |
3127 | let limits = if tok == token::DotDot { |
3128 | RangeLimits::HalfOpen | |
3129 | } else { | |
3130 | RangeLimits::Closed | |
3131 | }; | |
3132 | ||
3133 | let r = try!(self.mk_range(None, | |
3134 | opt_end, | |
3135 | limits)); | |
92a42be0 | 3136 | Ok(self.mk_expr(lo, hi, r, attrs)) |
223e47cc LB |
3137 | } |
3138 | ||
85aaf69f SL |
3139 | fn is_at_start_of_range_notation_rhs(&self) -> bool { |
3140 | if self.token.can_begin_expr() { | |
3141 | // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. | |
3142 | if self.token == token::OpenDelim(token::Brace) { | |
d9579d0f | 3143 | return !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL); |
85aaf69f SL |
3144 | } |
3145 | true | |
3146 | } else { | |
3147 | false | |
3148 | } | |
3149 | } | |
3150 | ||
1a4d82fc | 3151 | /// Parse an 'if' or 'if let' expression ('if' token already eaten) |
3157f602 | 3152 | pub fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
85aaf69f | 3153 | if self.check_keyword(keywords::Let) { |
92a42be0 | 3154 | return self.parse_if_let_expr(attrs); |
1a4d82fc | 3155 | } |
223e47cc | 3156 | let lo = self.last_span.lo; |
54a0048b SL |
3157 | let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; |
3158 | let thn = self.parse_block()?; | |
1a4d82fc | 3159 | let mut els: Option<P<Expr>> = None; |
223e47cc | 3160 | let mut hi = thn.span.hi; |
9cc50fc6 | 3161 | if self.eat_keyword(keywords::Else) { |
54a0048b | 3162 | let elexpr = self.parse_else_expr()?; |
223e47cc | 3163 | hi = elexpr.span.hi; |
1a4d82fc | 3164 | els = Some(elexpr); |
223e47cc | 3165 | } |
7453a54e | 3166 | Ok(self.mk_expr(lo, hi, ExprKind::If(cond, thn, els), attrs)) |
223e47cc LB |
3167 | } |
3168 | ||
1a4d82fc | 3169 | /// Parse an 'if let' expression ('if' token already eaten) |
3157f602 | 3170 | pub fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>) |
9cc50fc6 | 3171 | -> PResult<'a, P<Expr>> { |
1a4d82fc | 3172 | let lo = self.last_span.lo; |
54a0048b SL |
3173 | self.expect_keyword(keywords::Let)?; |
3174 | let pat = self.parse_pat()?; | |
3175 | self.expect(&token::Eq)?; | |
3176 | let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; | |
3177 | let thn = self.parse_block()?; | |
9cc50fc6 | 3178 | let (hi, els) = if self.eat_keyword(keywords::Else) { |
54a0048b | 3179 | let expr = self.parse_else_expr()?; |
1a4d82fc JJ |
3180 | (expr.span.hi, Some(expr)) |
3181 | } else { | |
3182 | (thn.span.hi, None) | |
3183 | }; | |
7453a54e | 3184 | Ok(self.mk_expr(lo, hi, ExprKind::IfLet(pat, expr, thn, els), attrs)) |
223e47cc LB |
3185 | } |
3186 | ||
a7813a04 XL |
3187 | // `move |args| expr` |
3188 | pub fn parse_lambda_expr(&mut self, | |
3189 | lo: BytePos, | |
7453a54e | 3190 | capture_clause: CaptureBy, |
3157f602 | 3191 | attrs: ThinVec<Attribute>) |
9cc50fc6 | 3192 | -> PResult<'a, P<Expr>> |
1a4d82fc | 3193 | { |
54a0048b | 3194 | let decl = self.parse_fn_block_decl()?; |
a7813a04 | 3195 | let decl_hi = self.last_span.hi; |
c34b1796 | 3196 | let body = match decl.output { |
7453a54e | 3197 | FunctionRetTy::Default(_) => { |
c34b1796 AL |
3198 | // If no explicit return type is given, parse any |
3199 | // expr and wrap it up in a dummy block: | |
54a0048b | 3200 | let body_expr = self.parse_expr()?; |
c34b1796 AL |
3201 | P(ast::Block { |
3202 | id: ast::DUMMY_NODE_ID, | |
c34b1796 | 3203 | span: body_expr.span, |
3157f602 XL |
3204 | stmts: vec![Stmt { |
3205 | span: body_expr.span, | |
3206 | node: StmtKind::Expr(body_expr), | |
3207 | id: ast::DUMMY_NODE_ID, | |
3208 | }], | |
7453a54e | 3209 | rules: BlockCheckMode::Default, |
c34b1796 AL |
3210 | }) |
3211 | } | |
3212 | _ => { | |
3213 | // If an explicit return type is given, require a | |
3214 | // block to appear (RFC 968). | |
54a0048b | 3215 | self.parse_block()? |
c34b1796 AL |
3216 | } |
3217 | }; | |
1a4d82fc | 3218 | |
9346a6ac | 3219 | Ok(self.mk_expr( |
1a4d82fc | 3220 | lo, |
c34b1796 | 3221 | body.span.hi, |
a7813a04 XL |
3222 | ExprKind::Closure(capture_clause, decl, body, mk_sp(lo, decl_hi)), |
3223 | attrs)) | |
223e47cc LB |
3224 | } |
3225 | ||
92a42be0 | 3226 | // `else` token already eaten |
9cc50fc6 SL |
3227 | pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { |
3228 | if self.eat_keyword(keywords::If) { | |
3157f602 | 3229 | return self.parse_if_expr(ThinVec::new()); |
223e47cc | 3230 | } else { |
54a0048b | 3231 | let blk = self.parse_block()?; |
3157f602 | 3232 | return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), ThinVec::new())); |
223e47cc LB |
3233 | } |
3234 | } | |
3235 | ||
1a4d82fc | 3236 | /// Parse a 'for' .. 'in' expression ('for' token already eaten) |
3157f602 | 3237 | pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, |
92a42be0 | 3238 | span_lo: BytePos, |
3157f602 | 3239 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
1a4d82fc JJ |
3240 | // Parse: `for <src_pat> in <src_expr> <src_loop_block>` |
3241 | ||
54a0048b SL |
3242 | let pat = self.parse_pat()?; |
3243 | self.expect_keyword(keywords::In)?; | |
3244 | let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; | |
3245 | let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; | |
3157f602 | 3246 | attrs.extend(iattrs); |
92a42be0 | 3247 | |
9346a6ac | 3248 | let hi = self.last_span.hi; |
970d7e83 | 3249 | |
92a42be0 | 3250 | Ok(self.mk_expr(span_lo, hi, |
7453a54e | 3251 | ExprKind::ForLoop(pat, expr, loop_block, opt_ident), |
92a42be0 | 3252 | attrs)) |
223e47cc LB |
3253 | } |
3254 | ||
1a4d82fc | 3255 | /// Parse a 'while' or 'while let' expression ('while' token already eaten) |
3157f602 | 3256 | pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, |
92a42be0 | 3257 | span_lo: BytePos, |
3157f602 | 3258 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
1a4d82fc | 3259 | if self.token.is_keyword(keywords::Let) { |
92a42be0 | 3260 | return self.parse_while_let_expr(opt_ident, span_lo, attrs); |
1a4d82fc | 3261 | } |
54a0048b SL |
3262 | let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; |
3263 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | |
3157f602 | 3264 | attrs.extend(iattrs); |
1a4d82fc | 3265 | let hi = body.span.hi; |
7453a54e | 3266 | return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident), |
92a42be0 | 3267 | attrs)); |
223e47cc LB |
3268 | } |
3269 | ||
1a4d82fc | 3270 | /// Parse a 'while let' expression ('while' token already eaten) |
3157f602 | 3271 | pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, |
92a42be0 | 3272 | span_lo: BytePos, |
3157f602 | 3273 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
54a0048b SL |
3274 | self.expect_keyword(keywords::Let)?; |
3275 | let pat = self.parse_pat()?; | |
3276 | self.expect(&token::Eq)?; | |
3277 | let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?; | |
3278 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | |
3157f602 | 3279 | attrs.extend(iattrs); |
1a4d82fc | 3280 | let hi = body.span.hi; |
7453a54e | 3281 | return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs)); |
1a4d82fc | 3282 | } |
223e47cc | 3283 | |
92a42be0 | 3284 | // parse `loop {...}`, `loop` token already eaten |
3157f602 | 3285 | pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>, |
92a42be0 | 3286 | span_lo: BytePos, |
3157f602 | 3287 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
54a0048b | 3288 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; |
3157f602 | 3289 | attrs.extend(iattrs); |
1a4d82fc | 3290 | let hi = body.span.hi; |
7453a54e | 3291 | Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs)) |
1a4d82fc | 3292 | } |
223e47cc | 3293 | |
92a42be0 | 3294 | // `match` token already eaten |
3157f602 | 3295 | fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { |
92a42be0 | 3296 | let match_span = self.last_span; |
1a4d82fc | 3297 | let lo = self.last_span.lo; |
54a0048b SL |
3298 | let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, |
3299 | None)?; | |
5bcae85e | 3300 | if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { |
92a42be0 | 3301 | if self.token == token::Token::Semi { |
9cc50fc6 | 3302 | e.span_note(match_span, "did you mean to remove this `match` keyword?"); |
92a42be0 SL |
3303 | } |
3304 | return Err(e) | |
3305 | } | |
3157f602 XL |
3306 | attrs.extend(self.parse_inner_attributes()?); |
3307 | ||
1a4d82fc JJ |
3308 | let mut arms: Vec<Arm> = Vec::new(); |
3309 | while self.token != token::CloseDelim(token::Brace) { | |
7453a54e SL |
3310 | match self.parse_arm() { |
3311 | Ok(arm) => arms.push(arm), | |
3312 | Err(mut e) => { | |
3313 | // Recover by skipping to the end of the block. | |
3314 | e.emit(); | |
3315 | self.recover_stmt(); | |
3316 | let hi = self.span.hi; | |
3317 | if self.token == token::CloseDelim(token::Brace) { | |
3318 | self.bump(); | |
3319 | } | |
3320 | return Ok(self.mk_expr(lo, hi, ExprKind::Match(discriminant, arms), attrs)); | |
3321 | } | |
3322 | } | |
223e47cc | 3323 | } |
970d7e83 | 3324 | let hi = self.span.hi; |
9cc50fc6 | 3325 | self.bump(); |
7453a54e | 3326 | return Ok(self.mk_expr(lo, hi, ExprKind::Match(discriminant, arms), attrs)); |
223e47cc LB |
3327 | } |
3328 | ||
9cc50fc6 | 3329 | pub fn parse_arm(&mut self) -> PResult<'a, Arm> { |
d9579d0f AL |
3330 | maybe_whole!(no_clone self, NtArm); |
3331 | ||
54a0048b SL |
3332 | let attrs = self.parse_outer_attributes()?; |
3333 | let pats = self.parse_pats()?; | |
1a4d82fc | 3334 | let mut guard = None; |
9cc50fc6 | 3335 | if self.eat_keyword(keywords::If) { |
54a0048b | 3336 | guard = Some(self.parse_expr()?); |
1a4d82fc | 3337 | } |
54a0048b SL |
3338 | self.expect(&token::FatArrow)?; |
3339 | let expr = self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR, None)?; | |
1a4d82fc JJ |
3340 | |
3341 | let require_comma = | |
7453a54e | 3342 | !classify::expr_is_simple_block(&expr) |
1a4d82fc JJ |
3343 | && self.token != token::CloseDelim(token::Brace); |
3344 | ||
3345 | if require_comma { | |
5bcae85e | 3346 | self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])?; |
1a4d82fc | 3347 | } else { |
9cc50fc6 | 3348 | self.eat(&token::Comma); |
1a4d82fc JJ |
3349 | } |
3350 | ||
9346a6ac | 3351 | Ok(ast::Arm { |
1a4d82fc JJ |
3352 | attrs: attrs, |
3353 | pats: pats, | |
3354 | guard: guard, | |
3355 | body: expr, | |
9346a6ac | 3356 | }) |
1a4d82fc JJ |
3357 | } |
3358 | ||
3359 | /// Parse an expression | |
9cc50fc6 | 3360 | pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> { |
92a42be0 | 3361 | self.parse_expr_res(Restrictions::empty(), None) |
223e47cc LB |
3362 | } |
3363 | ||
92a42be0 SL |
3364 | /// Evaluate the closure with restrictions in place. |
3365 | /// | |
3366 | /// After the closure is evaluated, restrictions are reset. | |
7453a54e SL |
3367 | pub fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T |
3368 | where F: FnOnce(&mut Self) -> T | |
9cc50fc6 | 3369 | { |
1a4d82fc JJ |
3370 | let old = self.restrictions; |
3371 | self.restrictions = r; | |
92a42be0 | 3372 | let r = f(self); |
1a4d82fc | 3373 | self.restrictions = old; |
92a42be0 SL |
3374 | return r; |
3375 | ||
3376 | } | |
3377 | ||
3378 | /// Parse an expression, subject to the given restrictions | |
3379 | pub fn parse_expr_res(&mut self, r: Restrictions, | |
3157f602 | 3380 | already_parsed_attrs: Option<ThinVec<Attribute>>) |
9cc50fc6 | 3381 | -> PResult<'a, P<Expr>> { |
92a42be0 | 3382 | self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) |
223e47cc LB |
3383 | } |
3384 | ||
1a4d82fc | 3385 | /// Parse the RHS of a local variable declaration (e.g. '= 14;') |
9cc50fc6 | 3386 | fn parse_initializer(&mut self) -> PResult<'a, Option<P<Expr>>> { |
1a4d82fc | 3387 | if self.check(&token::Eq) { |
9cc50fc6 | 3388 | self.bump(); |
54a0048b | 3389 | Ok(Some(self.parse_expr()?)) |
1a4d82fc | 3390 | } else { |
9346a6ac | 3391 | Ok(None) |
223e47cc LB |
3392 | } |
3393 | } | |
3394 | ||
1a4d82fc | 3395 | /// Parse patterns, separated by '|' s |
9cc50fc6 | 3396 | fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> { |
1a4d82fc | 3397 | let mut pats = Vec::new(); |
223e47cc | 3398 | loop { |
54a0048b | 3399 | pats.push(self.parse_pat()?); |
9cc50fc6 | 3400 | if self.check(&token::BinOp(token::Or)) { self.bump();} |
9346a6ac | 3401 | else { return Ok(pats); } |
223e47cc LB |
3402 | }; |
3403 | } | |
3404 | ||
3157f602 XL |
3405 | fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool) |
3406 | -> PResult<'a, (Vec<P<Pat>>, Option<usize>)> { | |
9346a6ac | 3407 | let mut fields = vec![]; |
3157f602 XL |
3408 | let mut ddpos = None; |
3409 | ||
3410 | while !self.check(&token::CloseDelim(token::Paren)) { | |
3411 | if ddpos.is_none() && self.eat(&token::DotDot) { | |
3412 | ddpos = Some(fields.len()); | |
3413 | if self.eat(&token::Comma) { | |
3414 | // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. | |
54a0048b | 3415 | fields.push(self.parse_pat()?); |
9346a6ac | 3416 | } |
3157f602 XL |
3417 | } else if ddpos.is_some() && self.eat(&token::DotDot) { |
3418 | // Emit a friendly error, ignore `..` and continue parsing | |
3419 | self.span_err(self.last_span, "`..` can only be used once per \ | |
3420 | tuple or tuple struct pattern"); | |
3421 | } else { | |
3422 | fields.push(self.parse_pat()?); | |
9346a6ac | 3423 | } |
3157f602 XL |
3424 | |
3425 | if !self.check(&token::CloseDelim(token::Paren)) || | |
3426 | (unary_needs_comma && fields.len() == 1 && ddpos.is_none()) { | |
54a0048b | 3427 | self.expect(&token::Comma)?; |
9346a6ac AL |
3428 | } |
3429 | } | |
3157f602 XL |
3430 | |
3431 | Ok((fields, ddpos)) | |
9346a6ac AL |
3432 | } |
3433 | ||
223e47cc | 3434 | fn parse_pat_vec_elements( |
1a4d82fc | 3435 | &mut self, |
9cc50fc6 | 3436 | ) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> { |
1a4d82fc | 3437 | let mut before = Vec::new(); |
223e47cc | 3438 | let mut slice = None; |
1a4d82fc | 3439 | let mut after = Vec::new(); |
223e47cc LB |
3440 | let mut first = true; |
3441 | let mut before_slice = true; | |
3442 | ||
1a4d82fc JJ |
3443 | while self.token != token::CloseDelim(token::Bracket) { |
3444 | if first { | |
3445 | first = false; | |
3446 | } else { | |
54a0048b | 3447 | self.expect(&token::Comma)?; |
1a4d82fc JJ |
3448 | |
3449 | if self.token == token::CloseDelim(token::Bracket) | |
9346a6ac | 3450 | && (before_slice || !after.is_empty()) { |
1a4d82fc JJ |
3451 | break |
3452 | } | |
3453 | } | |
223e47cc | 3454 | |
223e47cc | 3455 | if before_slice { |
1a4d82fc | 3456 | if self.check(&token::DotDot) { |
9cc50fc6 | 3457 | self.bump(); |
1a4d82fc JJ |
3458 | |
3459 | if self.check(&token::Comma) || | |
3460 | self.check(&token::CloseDelim(token::Bracket)) { | |
3461 | slice = Some(P(ast::Pat { | |
3462 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 3463 | node: PatKind::Wild, |
1a4d82fc JJ |
3464 | span: self.span, |
3465 | })); | |
3466 | before_slice = false; | |
1a4d82fc JJ |
3467 | } |
3468 | continue | |
223e47cc LB |
3469 | } |
3470 | } | |
3471 | ||
54a0048b | 3472 | let subpat = self.parse_pat()?; |
1a4d82fc | 3473 | if before_slice && self.check(&token::DotDot) { |
9cc50fc6 | 3474 | self.bump(); |
223e47cc | 3475 | slice = Some(subpat); |
1a4d82fc JJ |
3476 | before_slice = false; |
3477 | } else if before_slice { | |
3478 | before.push(subpat); | |
223e47cc | 3479 | } else { |
1a4d82fc | 3480 | after.push(subpat); |
223e47cc LB |
3481 | } |
3482 | } | |
3483 | ||
9346a6ac | 3484 | Ok((before, slice, after)) |
223e47cc LB |
3485 | } |
3486 | ||
1a4d82fc | 3487 | /// Parse the fields of a struct-like pattern |
3157f602 | 3488 | fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>>, bool)> { |
1a4d82fc | 3489 | let mut fields = Vec::new(); |
223e47cc LB |
3490 | let mut etc = false; |
3491 | let mut first = true; | |
1a4d82fc JJ |
3492 | while self.token != token::CloseDelim(token::Brace) { |
3493 | if first { | |
3494 | first = false; | |
3495 | } else { | |
54a0048b | 3496 | self.expect(&token::Comma)?; |
1a4d82fc JJ |
3497 | // accept trailing commas |
3498 | if self.check(&token::CloseDelim(token::Brace)) { break } | |
3499 | } | |
3500 | ||
3501 | let lo = self.span.lo; | |
3502 | let hi; | |
223e47cc | 3503 | |
1a4d82fc | 3504 | if self.check(&token::DotDot) { |
9cc50fc6 | 3505 | self.bump(); |
1a4d82fc JJ |
3506 | if self.token != token::CloseDelim(token::Brace) { |
3507 | let token_str = self.this_token_to_string(); | |
9346a6ac AL |
3508 | return Err(self.fatal(&format!("expected `{}`, found `{}`", "}", |
3509 | token_str))) | |
223e47cc LB |
3510 | } |
3511 | etc = true; | |
3512 | break; | |
3513 | } | |
3514 | ||
85aaf69f SL |
3515 | // Check if a colon exists one ahead. This means we're parsing a fieldname. |
3516 | let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { | |
3517 | // Parsing a pattern of the form "fieldname: pat" | |
5bcae85e | 3518 | let fieldname = self.parse_field_name()?; |
9cc50fc6 | 3519 | self.bump(); |
54a0048b | 3520 | let pat = self.parse_pat()?; |
1a4d82fc | 3521 | hi = pat.span.hi; |
85aaf69f | 3522 | (pat, fieldname, false) |
223e47cc | 3523 | } else { |
85aaf69f | 3524 | // Parsing a pattern of the form "(box) (ref) (mut) fieldname" |
9cc50fc6 | 3525 | let is_box = self.eat_keyword(keywords::Box); |
85aaf69f | 3526 | let boxed_span_lo = self.span.lo; |
9cc50fc6 SL |
3527 | let is_ref = self.eat_keyword(keywords::Ref); |
3528 | let is_mut = self.eat_keyword(keywords::Mut); | |
54a0048b | 3529 | let fieldname = self.parse_ident()?; |
1a4d82fc | 3530 | hi = self.last_span.hi; |
85aaf69f SL |
3531 | |
3532 | let bind_type = match (is_ref, is_mut) { | |
7453a54e SL |
3533 | (true, true) => BindingMode::ByRef(Mutability::Mutable), |
3534 | (true, false) => BindingMode::ByRef(Mutability::Immutable), | |
3535 | (false, true) => BindingMode::ByValue(Mutability::Mutable), | |
3536 | (false, false) => BindingMode::ByValue(Mutability::Immutable), | |
85aaf69f SL |
3537 | }; |
3538 | let fieldpath = codemap::Spanned{span:self.last_span, node:fieldname}; | |
3539 | let fieldpat = P(ast::Pat{ | |
1a4d82fc | 3540 | id: ast::DUMMY_NODE_ID, |
7453a54e | 3541 | node: PatKind::Ident(bind_type, fieldpath, None), |
85aaf69f SL |
3542 | span: mk_sp(boxed_span_lo, hi), |
3543 | }); | |
3544 | ||
3545 | let subpat = if is_box { | |
3546 | P(ast::Pat{ | |
3547 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 3548 | node: PatKind::Box(fieldpat), |
85aaf69f SL |
3549 | span: mk_sp(lo, hi), |
3550 | }) | |
3551 | } else { | |
3552 | fieldpat | |
3553 | }; | |
3554 | (subpat, fieldname, true) | |
1a4d82fc | 3555 | }; |
85aaf69f | 3556 | |
1a4d82fc | 3557 | fields.push(codemap::Spanned { span: mk_sp(lo, hi), |
3157f602 XL |
3558 | node: ast::FieldPat { ident: fieldname, |
3559 | pat: subpat, | |
3560 | is_shorthand: is_shorthand }}); | |
223e47cc | 3561 | } |
9346a6ac AL |
3562 | return Ok((fields, etc)); |
3563 | } | |
3564 | ||
9cc50fc6 | 3565 | fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> { |
a7813a04 | 3566 | if self.token.is_path_start() { |
9346a6ac | 3567 | let lo = self.span.lo; |
9cc50fc6 | 3568 | let (qself, path) = if self.eat_lt() { |
d9579d0f AL |
3569 | // Parse a qualified path |
3570 | let (qself, path) = | |
a7813a04 | 3571 | self.parse_qualified_path(PathStyle::Expr)?; |
d9579d0f AL |
3572 | (Some(qself), path) |
3573 | } else { | |
3574 | // Parse an unqualified path | |
a7813a04 | 3575 | (None, self.parse_path(PathStyle::Expr)?) |
d9579d0f | 3576 | }; |
9346a6ac | 3577 | let hi = self.last_span.hi; |
3157f602 | 3578 | Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new())) |
9346a6ac | 3579 | } else { |
92a42be0 | 3580 | self.parse_pat_literal_maybe_minus() |
9346a6ac AL |
3581 | } |
3582 | } | |
3583 | ||
1a4d82fc | 3584 | /// Parse a pattern. |
9cc50fc6 | 3585 | pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> { |
1a4d82fc | 3586 | maybe_whole!(self, NtPat); |
223e47cc LB |
3587 | |
3588 | let lo = self.span.lo; | |
970d7e83 | 3589 | let pat; |
1a4d82fc | 3590 | match self.token { |
1a4d82fc | 3591 | token::Underscore => { |
9346a6ac | 3592 | // Parse _ |
9cc50fc6 | 3593 | self.bump(); |
7453a54e | 3594 | pat = PatKind::Wild; |
223e47cc | 3595 | } |
1a4d82fc | 3596 | token::BinOp(token::And) | token::AndAnd => { |
9346a6ac | 3597 | // Parse &pat / &mut pat |
54a0048b SL |
3598 | self.expect_and()?; |
3599 | let mutbl = self.parse_mutability()?; | |
b039eaaf SL |
3600 | if let token::Lifetime(ident) = self.token { |
3601 | return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident))); | |
3602 | } | |
3603 | ||
54a0048b | 3604 | let subpat = self.parse_pat()?; |
7453a54e | 3605 | pat = PatKind::Ref(subpat, mutbl); |
223e47cc | 3606 | } |
1a4d82fc | 3607 | token::OpenDelim(token::Paren) => { |
9346a6ac | 3608 | // Parse (pat,pat,pat,...) as tuple pattern |
9cc50fc6 | 3609 | self.bump(); |
3157f602 | 3610 | let (fields, ddpos) = self.parse_pat_tuple_elements(true)?; |
54a0048b | 3611 | self.expect(&token::CloseDelim(token::Paren))?; |
3157f602 | 3612 | pat = PatKind::Tuple(fields, ddpos); |
223e47cc | 3613 | } |
1a4d82fc | 3614 | token::OpenDelim(token::Bracket) => { |
e9174d1e | 3615 | // Parse [pat,pat,...] as slice pattern |
9cc50fc6 | 3616 | self.bump(); |
54a0048b SL |
3617 | let (before, slice, after) = self.parse_pat_vec_elements()?; |
3618 | self.expect(&token::CloseDelim(token::Bracket))?; | |
7453a54e | 3619 | pat = PatKind::Vec(before, slice, after); |
223e47cc | 3620 | } |
9346a6ac AL |
3621 | _ => { |
3622 | // At this point, token != _, &, &&, (, [ | |
9cc50fc6 | 3623 | if self.eat_keyword(keywords::Mut) { |
9346a6ac | 3624 | // Parse mut ident @ pat |
54a0048b | 3625 | pat = self.parse_pat_ident(BindingMode::ByValue(Mutability::Mutable))?; |
9cc50fc6 | 3626 | } else if self.eat_keyword(keywords::Ref) { |
9346a6ac | 3627 | // Parse ref ident @ pat / ref mut ident @ pat |
54a0048b SL |
3628 | let mutbl = self.parse_mutability()?; |
3629 | pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; | |
9cc50fc6 | 3630 | } else if self.eat_keyword(keywords::Box) { |
9346a6ac | 3631 | // Parse box pat |
54a0048b | 3632 | let subpat = self.parse_pat()?; |
7453a54e | 3633 | pat = PatKind::Box(subpat); |
a7813a04 | 3634 | } else if self.token.is_path_start() { |
9346a6ac | 3635 | // Parse pattern starting with a path |
a7813a04 | 3636 | if self.token.is_ident() && self.look_ahead(1, |t| *t != token::DotDotDot && |
9346a6ac AL |
3637 | *t != token::OpenDelim(token::Brace) && |
3638 | *t != token::OpenDelim(token::Paren) && | |
9346a6ac AL |
3639 | *t != token::ModSep) { |
3640 | // Plain idents have some extra abilities here compared to general paths | |
3641 | if self.look_ahead(1, |t| *t == token::Not) { | |
3642 | // Parse macro invocation | |
a7813a04 | 3643 | let path = self.parse_ident_into_path()?; |
9cc50fc6 | 3644 | self.bump(); |
54a0048b SL |
3645 | let delim = self.expect_open_delim()?; |
3646 | let tts = self.parse_seq_to_end( | |
3647 | &token::CloseDelim(delim), | |
3648 | SeqSep::none(), |p| p.parse_token_tree())?; | |
3157f602 | 3649 | let mac = Mac_ { path: path, tts: tts }; |
7453a54e | 3650 | pat = PatKind::Mac(codemap::Spanned {node: mac, |
3157f602 | 3651 | span: mk_sp(lo, self.last_span.hi)}); |
223e47cc | 3652 | } else { |
9346a6ac AL |
3653 | // Parse ident @ pat |
3654 | // This can give false positives and parse nullary enums, | |
3655 | // they are dealt with later in resolve | |
7453a54e | 3656 | let binding_mode = BindingMode::ByValue(Mutability::Immutable); |
54a0048b | 3657 | pat = self.parse_pat_ident(binding_mode)?; |
970d7e83 | 3658 | } |
9346a6ac | 3659 | } else { |
9cc50fc6 | 3660 | let (qself, path) = if self.eat_lt() { |
d9579d0f AL |
3661 | // Parse a qualified path |
3662 | let (qself, path) = | |
a7813a04 | 3663 | self.parse_qualified_path(PathStyle::Expr)?; |
d9579d0f AL |
3664 | (Some(qself), path) |
3665 | } else { | |
3666 | // Parse an unqualified path | |
a7813a04 | 3667 | (None, self.parse_path(PathStyle::Expr)?) |
d9579d0f | 3668 | }; |
9346a6ac AL |
3669 | match self.token { |
3670 | token::DotDotDot => { | |
3671 | // Parse range | |
c34b1796 | 3672 | let hi = self.last_span.hi; |
3157f602 XL |
3673 | let begin = |
3674 | self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new()); | |
9cc50fc6 | 3675 | self.bump(); |
54a0048b | 3676 | let end = self.parse_pat_range_end()?; |
7453a54e | 3677 | pat = PatKind::Range(begin, end); |
9346a6ac AL |
3678 | } |
3679 | token::OpenDelim(token::Brace) => { | |
d9579d0f | 3680 | if qself.is_some() { |
b039eaaf | 3681 | return Err(self.fatal("unexpected `{` after qualified path")); |
d9579d0f | 3682 | } |
b039eaaf | 3683 | // Parse struct pattern |
9cc50fc6 | 3684 | self.bump(); |
7453a54e SL |
3685 | let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { |
3686 | e.emit(); | |
3687 | self.recover_stmt(); | |
3688 | (vec![], false) | |
3689 | }); | |
9cc50fc6 | 3690 | self.bump(); |
7453a54e | 3691 | pat = PatKind::Struct(path, fields, etc); |
9346a6ac AL |
3692 | } |
3693 | token::OpenDelim(token::Paren) => { | |
d9579d0f | 3694 | if qself.is_some() { |
b039eaaf | 3695 | return Err(self.fatal("unexpected `(` after qualified path")); |
d9579d0f | 3696 | } |
9346a6ac | 3697 | // Parse tuple struct or enum pattern |
3157f602 XL |
3698 | self.bump(); |
3699 | let (fields, ddpos) = self.parse_pat_tuple_elements(false)?; | |
3700 | self.expect(&token::CloseDelim(token::Paren))?; | |
3701 | pat = PatKind::TupleStruct(path, fields, ddpos) | |
9346a6ac AL |
3702 | } |
3703 | _ => { | |
3157f602 | 3704 | pat = PatKind::Path(qself, path); |
9346a6ac | 3705 | } |
223e47cc LB |
3706 | } |
3707 | } | |
9346a6ac AL |
3708 | } else { |
3709 | // Try to parse everything else as literal with optional minus | |
a7813a04 XL |
3710 | match self.parse_pat_literal_maybe_minus() { |
3711 | Ok(begin) => { | |
3712 | if self.eat(&token::DotDotDot) { | |
3713 | let end = self.parse_pat_range_end()?; | |
3714 | pat = PatKind::Range(begin, end); | |
3715 | } else { | |
3716 | pat = PatKind::Lit(begin); | |
3717 | } | |
3718 | } | |
3719 | Err(mut err) => { | |
3720 | err.cancel(); | |
3721 | let msg = format!("expected pattern, found {}", self.this_token_descr()); | |
3722 | return Err(self.fatal(&msg)); | |
3723 | } | |
9346a6ac | 3724 | } |
223e47cc | 3725 | } |
9346a6ac | 3726 | } |
223e47cc | 3727 | } |
9346a6ac AL |
3728 | |
3729 | let hi = self.last_span.hi; | |
3730 | Ok(P(ast::Pat { | |
1a4d82fc JJ |
3731 | id: ast::DUMMY_NODE_ID, |
3732 | node: pat, | |
3733 | span: mk_sp(lo, hi), | |
9346a6ac | 3734 | })) |
223e47cc LB |
3735 | } |
3736 | ||
1a4d82fc JJ |
3737 | /// Parse ident or ident @ pat |
3738 | /// used by the copy foo and ref foo patterns to give a good | |
3739 | /// error message when parsing mistakes like ref foo(a,b) | |
3740 | fn parse_pat_ident(&mut self, | |
3741 | binding_mode: ast::BindingMode) | |
7453a54e | 3742 | -> PResult<'a, PatKind> { |
54a0048b | 3743 | let ident = self.parse_ident()?; |
1a4d82fc JJ |
3744 | let last_span = self.last_span; |
3745 | let name = codemap::Spanned{span: last_span, node: ident}; | |
9cc50fc6 | 3746 | let sub = if self.eat(&token::At) { |
54a0048b | 3747 | Some(self.parse_pat()?) |
970d7e83 LB |
3748 | } else { |
3749 | None | |
3750 | }; | |
223e47cc LB |
3751 | |
3752 | // just to be friendly, if they write something like | |
3753 | // ref Some(i) | |
3754 | // we end up here with ( as the current token. This shortly | |
3755 | // leads to a parse error. Note that if there is no explicit | |
3756 | // binding mode then we do not end up here, because the lookahead | |
3757 | // will direct us over to parse_enum_variant() | |
1a4d82fc JJ |
3758 | if self.token == token::OpenDelim(token::Paren) { |
3759 | let last_span = self.last_span; | |
9346a6ac | 3760 | return Err(self.span_fatal( |
1a4d82fc | 3761 | last_span, |
9346a6ac | 3762 | "expected identifier, found enum pattern")) |
223e47cc LB |
3763 | } |
3764 | ||
7453a54e | 3765 | Ok(PatKind::Ident(binding_mode, name, sub)) |
223e47cc LB |
3766 | } |
3767 | ||
1a4d82fc | 3768 | /// Parse a local variable declaration |
3157f602 | 3769 | fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> { |
223e47cc | 3770 | let lo = self.span.lo; |
54a0048b | 3771 | let pat = self.parse_pat()?; |
970d7e83 | 3772 | |
1a4d82fc | 3773 | let mut ty = None; |
9cc50fc6 | 3774 | if self.eat(&token::Colon) { |
54a0048b | 3775 | ty = Some(self.parse_ty_sum()?); |
970d7e83 | 3776 | } |
54a0048b | 3777 | let init = self.parse_initializer()?; |
9346a6ac | 3778 | Ok(P(ast::Local { |
1a4d82fc JJ |
3779 | ty: ty, |
3780 | pat: pat, | |
3781 | init: init, | |
3782 | id: ast::DUMMY_NODE_ID, | |
3783 | span: mk_sp(lo, self.last_span.hi), | |
92a42be0 | 3784 | attrs: attrs, |
9346a6ac | 3785 | })) |
223e47cc LB |
3786 | } |
3787 | ||
1a4d82fc | 3788 | /// Parse a structure field |
5bcae85e SL |
3789 | fn parse_name_and_ty(&mut self, |
3790 | lo: BytePos, | |
3791 | vis: Visibility, | |
3792 | attrs: Vec<Attribute>) | |
3793 | -> PResult<'a, StructField> { | |
54a0048b SL |
3794 | let name = self.parse_ident()?; |
3795 | self.expect(&token::Colon)?; | |
3796 | let ty = self.parse_ty_sum()?; | |
3797 | Ok(StructField { | |
3798 | span: mk_sp(lo, self.last_span.hi), | |
3799 | ident: Some(name), | |
5bcae85e | 3800 | vis: vis, |
1a4d82fc | 3801 | id: ast::DUMMY_NODE_ID, |
970d7e83 LB |
3802 | ty: ty, |
3803 | attrs: attrs, | |
54a0048b | 3804 | }) |
223e47cc LB |
3805 | } |
3806 | ||
c34b1796 AL |
3807 | /// Emit an expected item after attributes error. |
3808 | fn expected_item_err(&self, attrs: &[Attribute]) { | |
3809 | let message = match attrs.last() { | |
1a4d82fc JJ |
3810 | Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => { |
3811 | "expected item after doc comment" | |
3812 | } | |
3813 | _ => "expected item after attributes", | |
c34b1796 AL |
3814 | }; |
3815 | ||
3816 | self.span_err(self.last_span, message); | |
1a4d82fc JJ |
3817 | } |
3818 | ||
5bcae85e SL |
3819 | /// Parse a statement. This stops just before trailing semicolons on everything but items. |
3820 | /// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. | |
7453a54e | 3821 | pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> { |
5bcae85e | 3822 | Ok(self.parse_stmt_(true)) |
7453a54e SL |
3823 | } |
3824 | ||
3825 | // Eat tokens until we can be relatively sure we reached the end of the | |
3826 | // statement. This is something of a best-effort heuristic. | |
3827 | // | |
3828 | // We terminate when we find an unmatched `}` (without consuming it). | |
3829 | fn recover_stmt(&mut self) { | |
3830 | self.recover_stmt_(SemiColonMode::Ignore) | |
3831 | } | |
3832 | // If `break_on_semi` is `Break`, then we will stop consuming tokens after | |
3833 | // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is | |
3834 | // approximate - it can mean we break too early due to macros, but that | |
3835 | // shoud only lead to sub-optimal recovery, not inaccurate parsing). | |
3836 | fn recover_stmt_(&mut self, break_on_semi: SemiColonMode) { | |
3837 | let mut brace_depth = 0; | |
3838 | let mut bracket_depth = 0; | |
3839 | debug!("recover_stmt_ enter loop"); | |
3840 | loop { | |
3841 | debug!("recover_stmt_ loop {:?}", self.token); | |
3842 | match self.token { | |
3843 | token::OpenDelim(token::DelimToken::Brace) => { | |
3844 | brace_depth += 1; | |
3845 | self.bump(); | |
3846 | } | |
3847 | token::OpenDelim(token::DelimToken::Bracket) => { | |
3848 | bracket_depth += 1; | |
3849 | self.bump(); | |
3850 | } | |
3851 | token::CloseDelim(token::DelimToken::Brace) => { | |
3852 | if brace_depth == 0 { | |
3853 | debug!("recover_stmt_ return - close delim {:?}", self.token); | |
3854 | return; | |
3855 | } | |
3856 | brace_depth -= 1; | |
3857 | self.bump(); | |
3858 | } | |
3859 | token::CloseDelim(token::DelimToken::Bracket) => { | |
3860 | bracket_depth -= 1; | |
3861 | if bracket_depth < 0 { | |
3862 | bracket_depth = 0; | |
3863 | } | |
3864 | self.bump(); | |
3865 | } | |
3866 | token::Eof => { | |
3867 | debug!("recover_stmt_ return - Eof"); | |
3868 | return; | |
3869 | } | |
3870 | token::Semi => { | |
3871 | self.bump(); | |
3872 | if break_on_semi == SemiColonMode::Break && | |
3873 | brace_depth == 0 && | |
3874 | bracket_depth == 0 { | |
3875 | debug!("recover_stmt_ return - Semi"); | |
3876 | return; | |
3877 | } | |
3878 | } | |
3879 | _ => { | |
3880 | self.bump() | |
3881 | } | |
3882 | } | |
3883 | } | |
3884 | } | |
3885 | ||
5bcae85e SL |
3886 | fn parse_stmt_(&mut self, macro_expanded: bool) -> Option<Stmt> { |
3887 | self.parse_stmt_without_recovery(macro_expanded).unwrap_or_else(|mut e| { | |
7453a54e SL |
3888 | e.emit(); |
3889 | self.recover_stmt_(SemiColonMode::Break); | |
3890 | None | |
3891 | }) | |
c34b1796 AL |
3892 | } |
3893 | ||
5bcae85e | 3894 | fn parse_stmt_without_recovery(&mut self, macro_expanded: bool) -> PResult<'a, Option<Stmt>> { |
c34b1796 | 3895 | maybe_whole!(Some deref self, NtStmt); |
223e47cc | 3896 | |
54a0048b | 3897 | let attrs = self.parse_outer_attributes()?; |
d9579d0f | 3898 | let lo = self.span.lo; |
c34b1796 | 3899 | |
3157f602 XL |
3900 | Ok(Some(if self.eat_keyword(keywords::Let) { |
3901 | Stmt { | |
3902 | id: ast::DUMMY_NODE_ID, | |
3903 | node: StmtKind::Local(self.parse_local(attrs.into())?), | |
3904 | span: mk_sp(lo, self.last_span.hi), | |
3905 | } | |
1a4d82fc JJ |
3906 | } else if self.token.is_ident() |
3907 | && !self.token.is_any_keyword() | |
3908 | && self.look_ahead(1, |t| *t == token::Not) { | |
3909 | // it's a macro invocation: | |
3910 | ||
223e47cc LB |
3911 | // Potential trouble: if we allow macros with paths instead of |
3912 | // idents, we'd need to look ahead past the whole path here... | |
a7813a04 | 3913 | let pth = self.parse_ident_into_path()?; |
9cc50fc6 | 3914 | self.bump(); |
223e47cc | 3915 | |
1a4d82fc | 3916 | let id = match self.token { |
a7813a04 | 3917 | token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier |
54a0048b | 3918 | _ => self.parse_ident()?, |
1a4d82fc JJ |
3919 | }; |
3920 | ||
3921 | // check that we're pointing at delimiters (need to check | |
3922 | // again after the `if`, because of `parse_ident` | |
3923 | // consuming more tokens). | |
3924 | let delim = match self.token { | |
3925 | token::OpenDelim(delim) => delim, | |
3926 | _ => { | |
3927 | // we only expect an ident if we didn't parse one | |
3928 | // above. | |
a7813a04 | 3929 | let ident_str = if id.name == keywords::Invalid.name() { |
1a4d82fc JJ |
3930 | "identifier, " |
3931 | } else { | |
3932 | "" | |
3933 | }; | |
3934 | let tok_str = self.this_token_to_string(); | |
9346a6ac | 3935 | return Err(self.fatal(&format!("expected {}`(` or `{{`, found `{}`", |
1a4d82fc | 3936 | ident_str, |
9346a6ac | 3937 | tok_str))) |
1a4d82fc | 3938 | }, |
223e47cc LB |
3939 | }; |
3940 | ||
54a0048b | 3941 | let tts = self.parse_unspanned_seq( |
1a4d82fc JJ |
3942 | &token::OpenDelim(delim), |
3943 | &token::CloseDelim(delim), | |
7453a54e | 3944 | SeqSep::none(), |
223e47cc | 3945 | |p| p.parse_token_tree() |
54a0048b | 3946 | )?; |
9346a6ac | 3947 | let hi = self.last_span.hi; |
223e47cc | 3948 | |
1a4d82fc | 3949 | let style = if delim == token::Brace { |
7453a54e | 3950 | MacStmtStyle::Braces |
1a4d82fc | 3951 | } else { |
7453a54e | 3952 | MacStmtStyle::NoBraces |
1a4d82fc JJ |
3953 | }; |
3954 | ||
a7813a04 | 3955 | if id.name == keywords::Invalid.name() { |
3157f602 | 3956 | let mac = spanned(lo, hi, Mac_ { path: pth, tts: tts }); |
5bcae85e SL |
3957 | let node = if delim == token::Brace || |
3958 | self.token == token::Semi || self.token == token::Eof { | |
3959 | StmtKind::Mac(P((mac, style, attrs.into()))) | |
3960 | } | |
3961 | // We used to incorrectly stop parsing macro-expanded statements here. | |
3962 | // If the next token will be an error anyway but could have parsed with the | |
3963 | // earlier behavior, stop parsing here and emit a warning to avoid breakage. | |
3964 | else if macro_expanded && self.token.can_begin_expr() && match self.token { | |
3965 | // These can continue an expression, so we can't stop parsing and warn. | |
3966 | token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) | | |
3967 | token::BinOp(token::Minus) | token::BinOp(token::Star) | | |
3968 | token::BinOp(token::And) | token::BinOp(token::Or) | | |
3969 | token::AndAnd | token::OrOr | | |
3970 | token::DotDot | token::DotDotDot => false, | |
3971 | _ => true, | |
3972 | } { | |
3973 | self.warn_missing_semicolon(); | |
3974 | StmtKind::Mac(P((mac, style, attrs.into()))) | |
3975 | } else { | |
3976 | let e = self.mk_mac_expr(lo, hi, mac.node, ThinVec::new()); | |
3977 | let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; | |
3978 | let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; | |
3979 | StmtKind::Expr(e) | |
3980 | }; | |
3157f602 XL |
3981 | Stmt { |
3982 | id: ast::DUMMY_NODE_ID, | |
3157f602 | 3983 | span: mk_sp(lo, hi), |
5bcae85e | 3984 | node: node, |
3157f602 | 3985 | } |
223e47cc LB |
3986 | } else { |
3987 | // if it has a special ident, it's definitely an item | |
1a4d82fc JJ |
3988 | // |
3989 | // Require a semicolon or braces. | |
7453a54e | 3990 | if style != MacStmtStyle::Braces { |
9cc50fc6 | 3991 | if !self.eat(&token::Semi) { |
1a4d82fc JJ |
3992 | let last_span = self.last_span; |
3993 | self.span_err(last_span, | |
3994 | "macros that expand to items must \ | |
3995 | either be surrounded with braces or \ | |
3996 | followed by a semicolon"); | |
3997 | } | |
3998 | } | |
3157f602 XL |
3999 | Stmt { |
4000 | id: ast::DUMMY_NODE_ID, | |
4001 | span: mk_sp(lo, hi), | |
4002 | node: StmtKind::Item({ | |
223e47cc LB |
4003 | self.mk_item( |
4004 | lo, hi, id /*id is good here*/, | |
3157f602 XL |
4005 | ItemKind::Mac(spanned(lo, hi, Mac_ { path: pth, tts: tts })), |
4006 | Visibility::Inherited, | |
4007 | attrs) | |
4008 | }), | |
4009 | } | |
223e47cc | 4010 | } |
223e47cc | 4011 | } else { |
92a42be0 | 4012 | // FIXME: Bad copy of attrs |
7453a54e | 4013 | let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD; |
54a0048b SL |
4014 | match self.with_res(restrictions, |
4015 | |this| this.parse_item_(attrs.clone(), false, true))? { | |
3157f602 XL |
4016 | Some(i) => Stmt { |
4017 | id: ast::DUMMY_NODE_ID, | |
4018 | span: mk_sp(lo, i.span.hi), | |
4019 | node: StmtKind::Item(i), | |
4020 | }, | |
c34b1796 | 4021 | None => { |
92a42be0 SL |
4022 | let unused_attrs = |attrs: &[_], s: &mut Self| { |
4023 | if attrs.len() > 0 { | |
4024 | s.span_err(s.span, | |
4025 | "expected statement after outer attribute"); | |
4026 | } | |
4027 | }; | |
4028 | ||
c34b1796 AL |
4029 | // Do not attempt to parse an expression if we're done here. |
4030 | if self.token == token::Semi { | |
92a42be0 | 4031 | unused_attrs(&attrs, self); |
9cc50fc6 | 4032 | self.bump(); |
9346a6ac | 4033 | return Ok(None); |
c34b1796 AL |
4034 | } |
4035 | ||
4036 | if self.token == token::CloseDelim(token::Brace) { | |
92a42be0 | 4037 | unused_attrs(&attrs, self); |
9346a6ac | 4038 | return Ok(None); |
1a4d82fc | 4039 | } |
223e47cc | 4040 | |
1a4d82fc | 4041 | // Remainder are line-expr stmts. |
54a0048b | 4042 | let e = self.parse_expr_res( |
3157f602 XL |
4043 | Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?; |
4044 | Stmt { | |
4045 | id: ast::DUMMY_NODE_ID, | |
4046 | span: mk_sp(lo, e.span.hi), | |
4047 | node: StmtKind::Expr(e), | |
4048 | } | |
1a4d82fc JJ |
4049 | } |
4050 | } | |
9346a6ac | 4051 | })) |
223e47cc LB |
4052 | } |
4053 | ||
1a4d82fc JJ |
4054 | /// Is this expression a successfully-parsed statement? |
4055 | fn expr_is_complete(&mut self, e: &Expr) -> bool { | |
d9579d0f | 4056 | self.restrictions.contains(Restrictions::RESTRICTION_STMT_EXPR) && |
1a4d82fc | 4057 | !classify::expr_requires_semi_to_be_stmt(e) |
223e47cc LB |
4058 | } |
4059 | ||
1a4d82fc | 4060 | /// Parse a block. No inner attrs are allowed. |
9cc50fc6 | 4061 | pub fn parse_block(&mut self) -> PResult<'a, P<Block>> { |
1a4d82fc | 4062 | maybe_whole!(no_clone self, NtBlock); |
970d7e83 LB |
4063 | |
4064 | let lo = self.span.lo; | |
1a4d82fc | 4065 | |
9cc50fc6 | 4066 | if !self.eat(&token::OpenDelim(token::Brace)) { |
1a4d82fc JJ |
4067 | let sp = self.span; |
4068 | let tok = self.this_token_to_string(); | |
9346a6ac | 4069 | return Err(self.span_fatal_help(sp, |
85aaf69f | 4070 | &format!("expected `{{`, found `{}`", tok), |
9346a6ac | 4071 | "place this code inside a block")); |
970d7e83 | 4072 | } |
970d7e83 | 4073 | |
7453a54e | 4074 | self.parse_block_tail(lo, BlockCheckMode::Default) |
223e47cc LB |
4075 | } |
4076 | ||
1a4d82fc | 4077 | /// Parse a block. Inner attrs are allowed. |
9cc50fc6 | 4078 | fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Block>)> { |
1a4d82fc | 4079 | maybe_whole!(pair_empty self, NtBlock); |
223e47cc | 4080 | |
223e47cc | 4081 | let lo = self.span.lo; |
54a0048b SL |
4082 | self.expect(&token::OpenDelim(token::Brace))?; |
4083 | Ok((self.parse_inner_attributes()?, | |
4084 | self.parse_block_tail(lo, BlockCheckMode::Default)?)) | |
223e47cc LB |
4085 | } |
4086 | ||
c34b1796 | 4087 | /// Parse the rest of a block expression or function body |
85aaf69f | 4088 | /// Precondition: already parsed the '{'. |
9cc50fc6 | 4089 | fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<Block>> { |
85aaf69f | 4090 | let mut stmts = vec![]; |
223e47cc | 4091 | |
9cc50fc6 | 4092 | while !self.eat(&token::CloseDelim(token::Brace)) { |
5bcae85e SL |
4093 | if let Some(stmt) = self.parse_full_stmt(false)? { |
4094 | stmts.push(stmt); | |
7453a54e SL |
4095 | } else if self.token == token::Eof { |
4096 | break; | |
c34b1796 AL |
4097 | } else { |
4098 | // Found only `;` or `}`. | |
4099 | continue; | |
4100 | }; | |
970d7e83 LB |
4101 | } |
4102 | ||
9346a6ac | 4103 | Ok(P(ast::Block { |
223e47cc | 4104 | stmts: stmts, |
1a4d82fc | 4105 | id: ast::DUMMY_NODE_ID, |
223e47cc | 4106 | rules: s, |
c34b1796 | 4107 | span: mk_sp(lo, self.last_span.hi), |
9346a6ac | 4108 | })) |
223e47cc LB |
4109 | } |
4110 | ||
5bcae85e SL |
4111 | /// Parse a statement, including the trailing semicolon. |
4112 | pub fn parse_full_stmt(&mut self, macro_expanded: bool) -> PResult<'a, Option<Stmt>> { | |
4113 | let mut stmt = match self.parse_stmt_(macro_expanded) { | |
4114 | Some(stmt) => stmt, | |
4115 | None => return Ok(None), | |
4116 | }; | |
4117 | ||
4118 | match stmt.node { | |
4119 | StmtKind::Expr(ref expr) if self.token != token::Eof => { | |
4120 | // expression without semicolon | |
4121 | if classify::expr_requires_semi_to_be_stmt(expr) { | |
4122 | // Just check for errors and recover; do not eat semicolon yet. | |
4123 | if let Err(mut e) = | |
4124 | self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)]) | |
4125 | { | |
4126 | e.emit(); | |
4127 | self.recover_stmt(); | |
4128 | } | |
3157f602 XL |
4129 | } |
4130 | } | |
5bcae85e SL |
4131 | StmtKind::Local(..) => { |
4132 | // We used to incorrectly allow a macro-expanded let statement to lack a semicolon. | |
4133 | if macro_expanded && self.token != token::Semi { | |
4134 | self.warn_missing_semicolon(); | |
4135 | } else { | |
4136 | self.expect_one_of(&[token::Semi], &[])?; | |
3157f602 XL |
4137 | } |
4138 | } | |
5bcae85e | 4139 | _ => {} |
3157f602 | 4140 | } |
3157f602 | 4141 | |
5bcae85e SL |
4142 | if self.eat(&token::Semi) { |
4143 | stmt = stmt.add_trailing_semicolon(); | |
223e47cc | 4144 | } |
223e47cc | 4145 | |
5bcae85e SL |
4146 | stmt.span.hi = self.last_span.hi; |
4147 | Ok(Some(stmt)) | |
4148 | } | |
4149 | ||
4150 | fn warn_missing_semicolon(&self) { | |
4151 | self.diagnostic().struct_span_warn(self.span, { | |
4152 | &format!("expected `;`, found `{}`", self.this_token_to_string()) | |
4153 | }).note({ | |
4154 | "This was erroneously allowed and will become a hard error in a future release" | |
4155 | }).emit(); | |
223e47cc LB |
4156 | } |
4157 | ||
1a4d82fc JJ |
4158 | // Parses a sequence of bounds if a `:` is found, |
4159 | // otherwise returns empty list. | |
4160 | fn parse_colon_then_ty_param_bounds(&mut self, | |
4161 | mode: BoundParsingMode) | |
9cc50fc6 | 4162 | -> PResult<'a, TyParamBounds> |
1a4d82fc | 4163 | { |
9cc50fc6 | 4164 | if !self.eat(&token::Colon) { |
a7813a04 | 4165 | Ok(P::new()) |
1a4d82fc JJ |
4166 | } else { |
4167 | self.parse_ty_param_bounds(mode) | |
223e47cc | 4168 | } |
1a4d82fc | 4169 | } |
223e47cc | 4170 | |
1a4d82fc JJ |
4171 | // matches bounds = ( boundseq )? |
4172 | // where boundseq = ( polybound + boundseq ) | polybound | |
4173 | // and polybound = ( 'for' '<' 'region '>' )? bound | |
4174 | // and bound = 'region | trait_ref | |
4175 | fn parse_ty_param_bounds(&mut self, | |
4176 | mode: BoundParsingMode) | |
9cc50fc6 | 4177 | -> PResult<'a, TyParamBounds> |
1a4d82fc JJ |
4178 | { |
4179 | let mut result = vec!(); | |
223e47cc | 4180 | loop { |
1a4d82fc | 4181 | let question_span = self.span; |
9cc50fc6 | 4182 | let ate_question = self.eat(&token::Question); |
1a4d82fc JJ |
4183 | match self.token { |
4184 | token::Lifetime(lifetime) => { | |
4185 | if ate_question { | |
4186 | self.span_err(question_span, | |
4187 | "`?` may only modify trait bounds, not lifetime bounds"); | |
223e47cc | 4188 | } |
1a4d82fc JJ |
4189 | result.push(RegionTyParamBound(ast::Lifetime { |
4190 | id: ast::DUMMY_NODE_ID, | |
4191 | span: self.span, | |
4192 | name: lifetime.name | |
4193 | })); | |
9cc50fc6 | 4194 | self.bump(); |
223e47cc | 4195 | } |
1a4d82fc | 4196 | token::ModSep | token::Ident(..) => { |
54a0048b | 4197 | let poly_trait_ref = self.parse_poly_trait_ref()?; |
1a4d82fc JJ |
4198 | let modifier = if ate_question { |
4199 | if mode == BoundParsingMode::Modified { | |
4200 | TraitBoundModifier::Maybe | |
4201 | } else { | |
4202 | self.span_err(question_span, | |
4203 | "unexpected `?`"); | |
4204 | TraitBoundModifier::None | |
223e47cc | 4205 | } |
1a4d82fc JJ |
4206 | } else { |
4207 | TraitBoundModifier::None | |
223e47cc | 4208 | }; |
1a4d82fc | 4209 | result.push(TraitTyParamBound(poly_trait_ref, modifier)) |
223e47cc LB |
4210 | } |
4211 | _ => break, | |
4212 | } | |
4213 | ||
9cc50fc6 | 4214 | if !self.eat(&token::BinOp(token::Plus)) { |
970d7e83 | 4215 | break; |
223e47cc LB |
4216 | } |
4217 | } | |
4218 | ||
9cc50fc6 | 4219 | return Ok(P::from_vec(result)); |
223e47cc LB |
4220 | } |
4221 | ||
c34b1796 | 4222 | /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? |
9cc50fc6 | 4223 | fn parse_ty_param(&mut self) -> PResult<'a, TyParam> { |
c34b1796 | 4224 | let span = self.span; |
54a0048b | 4225 | let ident = self.parse_ident()?; |
1a4d82fc | 4226 | |
54a0048b | 4227 | let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified)?; |
1a4d82fc JJ |
4228 | |
4229 | let default = if self.check(&token::Eq) { | |
9cc50fc6 | 4230 | self.bump(); |
54a0048b | 4231 | Some(self.parse_ty_sum()?) |
c34b1796 AL |
4232 | } else { |
4233 | None | |
4234 | }; | |
1a4d82fc | 4235 | |
9346a6ac | 4236 | Ok(TyParam { |
1a4d82fc JJ |
4237 | ident: ident, |
4238 | id: ast::DUMMY_NODE_ID, | |
4239 | bounds: bounds, | |
4240 | default: default, | |
4241 | span: span, | |
9346a6ac | 4242 | }) |
1a4d82fc JJ |
4243 | } |
4244 | ||
4245 | /// Parse a set of optional generic type parameter declarations. Where | |
4246 | /// clauses are not parsed here, and must be added later via | |
4247 | /// `parse_where_clause()`. | |
4248 | /// | |
4249 | /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > ) | |
4250 | /// | ( < lifetimes , typaramseq ( , )? > ) | |
4251 | /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) | |
9cc50fc6 | 4252 | pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { |
d9579d0f AL |
4253 | maybe_whole!(self, NtGenerics); |
4254 | ||
9cc50fc6 | 4255 | if self.eat(&token::Lt) { |
54a0048b | 4256 | let lifetime_defs = self.parse_lifetime_defs()?; |
1a4d82fc | 4257 | let mut seen_default = false; |
54a0048b SL |
4258 | let ty_params = self.parse_seq_to_gt(Some(token::Comma), |p| { |
4259 | p.forbid_lifetime()?; | |
4260 | let ty_param = p.parse_ty_param()?; | |
1a4d82fc JJ |
4261 | if ty_param.default.is_some() { |
4262 | seen_default = true; | |
4263 | } else if seen_default { | |
4264 | let last_span = p.last_span; | |
4265 | p.span_err(last_span, | |
4266 | "type parameters with a default must be trailing"); | |
4267 | } | |
9346a6ac | 4268 | Ok(ty_param) |
54a0048b | 4269 | })?; |
9346a6ac | 4270 | Ok(ast::Generics { |
1a4d82fc JJ |
4271 | lifetimes: lifetime_defs, |
4272 | ty_params: ty_params, | |
4273 | where_clause: WhereClause { | |
4274 | id: ast::DUMMY_NODE_ID, | |
4275 | predicates: Vec::new(), | |
4276 | } | |
9346a6ac | 4277 | }) |
223e47cc | 4278 | } else { |
9cc50fc6 | 4279 | Ok(ast::Generics::default()) |
223e47cc LB |
4280 | } |
4281 | } | |
4282 | ||
9cc50fc6 | 4283 | fn parse_generic_values_after_lt(&mut self) -> PResult<'a, (Vec<ast::Lifetime>, |
9346a6ac | 4284 | Vec<P<Ty>>, |
7453a54e | 4285 | Vec<TypeBinding>)> { |
bd371182 | 4286 | let span_lo = self.span.lo; |
54a0048b | 4287 | let lifetimes = self.parse_lifetimes(token::Comma)?; |
1a4d82fc | 4288 | |
bd371182 AL |
4289 | let missing_comma = !lifetimes.is_empty() && |
4290 | !self.token.is_like_gt() && | |
4291 | self.last_token | |
4292 | .as_ref().map_or(true, | |
4293 | |x| &**x != &token::Comma); | |
4294 | ||
4295 | if missing_comma { | |
4296 | ||
4297 | let msg = format!("expected `,` or `>` after lifetime \ | |
4298 | name, found `{}`", | |
4299 | self.this_token_to_string()); | |
9cc50fc6 | 4300 | let mut err = self.diagnostic().struct_span_err(self.span, &msg); |
bd371182 AL |
4301 | |
4302 | let span_hi = self.span.hi; | |
9cc50fc6 SL |
4303 | let span_hi = match self.parse_ty() { |
4304 | Ok(..) => self.span.hi, | |
4305 | Err(ref mut err) => { | |
4306 | err.cancel(); | |
4307 | span_hi | |
4308 | } | |
bd371182 AL |
4309 | }; |
4310 | ||
4311 | let msg = format!("did you mean a single argument type &'a Type, \ | |
4312 | or did you mean the comma-separated arguments \ | |
4313 | 'a, Type?"); | |
9cc50fc6 | 4314 | err.span_note(mk_sp(span_lo, span_hi), &msg); |
7453a54e | 4315 | return Err(err); |
bd371182 AL |
4316 | } |
4317 | ||
1a4d82fc | 4318 | // First parse types. |
54a0048b | 4319 | let (types, returned) = self.parse_seq_to_gt_or_return( |
1a4d82fc JJ |
4320 | Some(token::Comma), |
4321 | |p| { | |
54a0048b | 4322 | p.forbid_lifetime()?; |
1a4d82fc | 4323 | if p.look_ahead(1, |t| t == &token::Eq) { |
9346a6ac | 4324 | Ok(None) |
1a4d82fc | 4325 | } else { |
54a0048b | 4326 | Ok(Some(p.parse_ty_sum()?)) |
1a4d82fc JJ |
4327 | } |
4328 | } | |
54a0048b | 4329 | )?; |
1a4d82fc JJ |
4330 | |
4331 | // If we found the `>`, don't continue. | |
4332 | if !returned { | |
9346a6ac | 4333 | return Ok((lifetimes, types.into_vec(), Vec::new())); |
1a4d82fc JJ |
4334 | } |
4335 | ||
4336 | // Then parse type bindings. | |
54a0048b | 4337 | let bindings = self.parse_seq_to_gt( |
1a4d82fc JJ |
4338 | Some(token::Comma), |
4339 | |p| { | |
54a0048b | 4340 | p.forbid_lifetime()?; |
1a4d82fc | 4341 | let lo = p.span.lo; |
54a0048b | 4342 | let ident = p.parse_ident()?; |
a7813a04 | 4343 | p.expect(&token::Eq)?; |
54a0048b | 4344 | let ty = p.parse_ty()?; |
e9174d1e | 4345 | let hi = ty.span.hi; |
1a4d82fc | 4346 | let span = mk_sp(lo, hi); |
7453a54e | 4347 | return Ok(TypeBinding{id: ast::DUMMY_NODE_ID, |
1a4d82fc JJ |
4348 | ident: ident, |
4349 | ty: ty, | |
4350 | span: span, | |
7453a54e | 4351 | }); |
1a4d82fc | 4352 | } |
54a0048b | 4353 | )?; |
9346a6ac | 4354 | Ok((lifetimes, types.into_vec(), bindings.into_vec())) |
1a4d82fc JJ |
4355 | } |
4356 | ||
9cc50fc6 | 4357 | fn forbid_lifetime(&mut self) -> PResult<'a, ()> { |
1a4d82fc JJ |
4358 | if self.token.is_lifetime() { |
4359 | let span = self.span; | |
7453a54e SL |
4360 | return Err(self.diagnostic().struct_span_err(span, "lifetime parameters must be \ |
4361 | declared prior to type parameters")) | |
223e47cc | 4362 | } |
9346a6ac | 4363 | Ok(()) |
223e47cc LB |
4364 | } |
4365 | ||
1a4d82fc JJ |
4366 | /// Parses an optional `where` clause and places it in `generics`. |
4367 | /// | |
92a42be0 | 4368 | /// ```ignore |
1a4d82fc JJ |
4369 | /// where T : Trait<U, V> + 'b, 'a : 'b |
4370 | /// ``` | |
9cc50fc6 | 4371 | pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> { |
d9579d0f AL |
4372 | maybe_whole!(self, NtWhereClause); |
4373 | ||
c34b1796 AL |
4374 | let mut where_clause = WhereClause { |
4375 | id: ast::DUMMY_NODE_ID, | |
4376 | predicates: Vec::new(), | |
4377 | }; | |
4378 | ||
9cc50fc6 | 4379 | if !self.eat_keyword(keywords::Where) { |
9346a6ac | 4380 | return Ok(where_clause); |
1a4d82fc JJ |
4381 | } |
4382 | ||
4383 | let mut parsed_something = false; | |
4384 | loop { | |
4385 | let lo = self.span.lo; | |
4386 | match self.token { | |
4387 | token::OpenDelim(token::Brace) => { | |
4388 | break | |
4389 | } | |
4390 | ||
4391 | token::Lifetime(..) => { | |
4392 | let bounded_lifetime = | |
54a0048b | 4393 | self.parse_lifetime()?; |
1a4d82fc | 4394 | |
9cc50fc6 | 4395 | self.eat(&token::Colon); |
1a4d82fc JJ |
4396 | |
4397 | let bounds = | |
54a0048b | 4398 | self.parse_lifetimes(token::BinOp(token::Plus))?; |
1a4d82fc | 4399 | |
d9579d0f | 4400 | let hi = self.last_span.hi; |
1a4d82fc JJ |
4401 | let span = mk_sp(lo, hi); |
4402 | ||
c34b1796 | 4403 | where_clause.predicates.push(ast::WherePredicate::RegionPredicate( |
1a4d82fc JJ |
4404 | ast::WhereRegionPredicate { |
4405 | span: span, | |
4406 | lifetime: bounded_lifetime, | |
4407 | bounds: bounds | |
4408 | } | |
4409 | )); | |
4410 | ||
4411 | parsed_something = true; | |
4412 | } | |
4413 | ||
4414 | _ => { | |
9cc50fc6 | 4415 | let bound_lifetimes = if self.eat_keyword(keywords::For) { |
85aaf69f | 4416 | // Higher ranked constraint. |
54a0048b SL |
4417 | self.expect(&token::Lt)?; |
4418 | let lifetime_defs = self.parse_lifetime_defs()?; | |
4419 | self.expect_gt()?; | |
85aaf69f SL |
4420 | lifetime_defs |
4421 | } else { | |
4422 | vec![] | |
4423 | }; | |
4424 | ||
54a0048b | 4425 | let bounded_ty = self.parse_ty()?; |
1a4d82fc | 4426 | |
9cc50fc6 | 4427 | if self.eat(&token::Colon) { |
54a0048b | 4428 | let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?; |
d9579d0f | 4429 | let hi = self.last_span.hi; |
1a4d82fc JJ |
4430 | let span = mk_sp(lo, hi); |
4431 | ||
9346a6ac | 4432 | if bounds.is_empty() { |
1a4d82fc JJ |
4433 | self.span_err(span, |
4434 | "each predicate in a `where` clause must have \ | |
85aaf69f | 4435 | at least one bound in it"); |
1a4d82fc JJ |
4436 | } |
4437 | ||
c34b1796 | 4438 | where_clause.predicates.push(ast::WherePredicate::BoundPredicate( |
1a4d82fc JJ |
4439 | ast::WhereBoundPredicate { |
4440 | span: span, | |
85aaf69f | 4441 | bound_lifetimes: bound_lifetimes, |
1a4d82fc JJ |
4442 | bounded_ty: bounded_ty, |
4443 | bounds: bounds, | |
4444 | })); | |
4445 | ||
4446 | parsed_something = true; | |
9cc50fc6 | 4447 | } else if self.eat(&token::Eq) { |
92a42be0 | 4448 | // let ty = try!(self.parse_ty()); |
d9579d0f | 4449 | let hi = self.last_span.hi; |
1a4d82fc | 4450 | let span = mk_sp(lo, hi); |
c34b1796 | 4451 | // where_clause.predicates.push( |
1a4d82fc JJ |
4452 | // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { |
4453 | // id: ast::DUMMY_NODE_ID, | |
4454 | // span: span, | |
4455 | // path: panic!("NYI"), //bounded_ty, | |
4456 | // ty: ty, | |
4457 | // })); | |
4458 | // parsed_something = true; | |
4459 | // // FIXME(#18433) | |
4460 | self.span_err(span, | |
4461 | "equality constraints are not yet supported \ | |
4462 | in where clauses (#20041)"); | |
4463 | } else { | |
4464 | let last_span = self.last_span; | |
4465 | self.span_err(last_span, | |
4466 | "unexpected token in `where` clause"); | |
4467 | } | |
4468 | } | |
4469 | }; | |
4470 | ||
9cc50fc6 | 4471 | if !self.eat(&token::Comma) { |
1a4d82fc JJ |
4472 | break |
4473 | } | |
4474 | } | |
4475 | ||
4476 | if !parsed_something { | |
4477 | let last_span = self.last_span; | |
4478 | self.span_err(last_span, | |
4479 | "a `where` clause must have at least one predicate \ | |
4480 | in it"); | |
4481 | } | |
c34b1796 | 4482 | |
9346a6ac | 4483 | Ok(where_clause) |
223e47cc LB |
4484 | } |
4485 | ||
1a4d82fc | 4486 | fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) |
9cc50fc6 | 4487 | -> PResult<'a, (Vec<Arg> , bool)> { |
1a4d82fc | 4488 | let sp = self.span; |
7453a54e SL |
4489 | let mut variadic = false; |
4490 | let args: Vec<Option<Arg>> = | |
54a0048b | 4491 | self.parse_unspanned_seq( |
1a4d82fc JJ |
4492 | &token::OpenDelim(token::Paren), |
4493 | &token::CloseDelim(token::Paren), | |
7453a54e | 4494 | SeqSep::trailing_allowed(token::Comma), |
1a4d82fc JJ |
4495 | |p| { |
4496 | if p.token == token::DotDotDot { | |
9cc50fc6 | 4497 | p.bump(); |
1a4d82fc JJ |
4498 | if allow_variadic { |
4499 | if p.token != token::CloseDelim(token::Paren) { | |
4500 | let span = p.span; | |
7453a54e SL |
4501 | p.span_err(span, |
4502 | "`...` must be last in argument list for variadic function"); | |
1a4d82fc JJ |
4503 | } |
4504 | } else { | |
4505 | let span = p.span; | |
7453a54e SL |
4506 | p.span_err(span, |
4507 | "only foreign functions are allowed to be variadic"); | |
1a4d82fc | 4508 | } |
7453a54e | 4509 | variadic = true; |
9346a6ac | 4510 | Ok(None) |
1a4d82fc | 4511 | } else { |
7453a54e SL |
4512 | match p.parse_arg_general(named_args) { |
4513 | Ok(arg) => Ok(Some(arg)), | |
4514 | Err(mut e) => { | |
4515 | e.emit(); | |
4516 | p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); | |
4517 | Ok(None) | |
4518 | } | |
4519 | } | |
1a4d82fc JJ |
4520 | } |
4521 | } | |
54a0048b | 4522 | )?; |
223e47cc | 4523 | |
7453a54e | 4524 | let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); |
223e47cc | 4525 | |
1a4d82fc JJ |
4526 | if variadic && args.is_empty() { |
4527 | self.span_err(sp, | |
4528 | "variadic function must be declared with at least one named argument"); | |
223e47cc | 4529 | } |
1a4d82fc | 4530 | |
9346a6ac | 4531 | Ok((args, variadic)) |
223e47cc LB |
4532 | } |
4533 | ||
1a4d82fc | 4534 | /// Parse the argument list and result type of a function declaration |
9cc50fc6 | 4535 | pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> { |
1a4d82fc | 4536 | |
54a0048b SL |
4537 | let (args, variadic) = self.parse_fn_args(true, allow_variadic)?; |
4538 | let ret_ty = self.parse_ret_ty()?; | |
1a4d82fc | 4539 | |
9346a6ac | 4540 | Ok(P(FnDecl { |
1a4d82fc JJ |
4541 | inputs: args, |
4542 | output: ret_ty, | |
4543 | variadic: variadic | |
9346a6ac | 4544 | })) |
223e47cc LB |
4545 | } |
4546 | ||
3157f602 XL |
4547 | /// Returns the parsed optional self argument and whether a self shortcut was used. |
4548 | fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> { | |
a7813a04 | 4549 | let expect_ident = |this: &mut Self| match this.token { |
3157f602 XL |
4550 | // Preserve hygienic context. |
4551 | token::Ident(ident) => { this.bump(); codemap::respan(this.last_span, ident) } | |
a7813a04 XL |
4552 | _ => unreachable!() |
4553 | }; | |
223e47cc | 4554 | |
a7813a04 XL |
4555 | // Parse optional self parameter of a method. |
4556 | // Only a limited set of initial token sequences is considered self parameters, anything | |
4557 | // else is parsed as a normal function parameter list, so some lookahead is required. | |
4558 | let eself_lo = self.span.lo; | |
3157f602 | 4559 | let (eself, eself_ident) = match self.token { |
1a4d82fc | 4560 | token::BinOp(token::And) => { |
a7813a04 XL |
4561 | // &self |
4562 | // &mut self | |
4563 | // &'lt self | |
4564 | // &'lt mut self | |
4565 | // ¬_self | |
4566 | if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { | |
4567 | self.bump(); | |
3157f602 | 4568 | (SelfKind::Region(None, Mutability::Immutable), expect_ident(self)) |
a7813a04 XL |
4569 | } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && |
4570 | self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { | |
4571 | self.bump(); | |
4572 | self.bump(); | |
3157f602 | 4573 | (SelfKind::Region(None, Mutability::Mutable), expect_ident(self)) |
a7813a04 XL |
4574 | } else if self.look_ahead(1, |t| t.is_lifetime()) && |
4575 | self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { | |
4576 | self.bump(); | |
4577 | let lt = self.parse_lifetime()?; | |
3157f602 | 4578 | (SelfKind::Region(Some(lt), Mutability::Immutable), expect_ident(self)) |
a7813a04 XL |
4579 | } else if self.look_ahead(1, |t| t.is_lifetime()) && |
4580 | self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) && | |
4581 | self.look_ahead(3, |t| t.is_keyword(keywords::SelfValue)) { | |
4582 | self.bump(); | |
4583 | let lt = self.parse_lifetime()?; | |
4584 | self.bump(); | |
3157f602 | 4585 | (SelfKind::Region(Some(lt), Mutability::Mutable), expect_ident(self)) |
a7813a04 | 4586 | } else { |
3157f602 | 4587 | return Ok(None); |
a7813a04 | 4588 | } |
1a4d82fc | 4589 | } |
1a4d82fc | 4590 | token::BinOp(token::Star) => { |
a7813a04 XL |
4591 | // *self |
4592 | // *const self | |
4593 | // *mut self | |
4594 | // *not_self | |
4595 | // Emit special error for `self` cases. | |
4596 | if self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { | |
4597 | self.bump(); | |
4598 | self.span_err(self.span, "cannot pass `self` by raw pointer"); | |
3157f602 | 4599 | (SelfKind::Value(Mutability::Immutable), expect_ident(self)) |
a7813a04 XL |
4600 | } else if self.look_ahead(1, |t| t.is_mutability()) && |
4601 | self.look_ahead(2, |t| t.is_keyword(keywords::SelfValue)) { | |
9cc50fc6 | 4602 | self.bump(); |
a7813a04 XL |
4603 | self.bump(); |
4604 | self.span_err(self.span, "cannot pass `self` by raw pointer"); | |
3157f602 | 4605 | (SelfKind::Value(Mutability::Immutable), expect_ident(self)) |
a7813a04 | 4606 | } else { |
3157f602 | 4607 | return Ok(None); |
1a4d82fc | 4608 | } |
1a4d82fc JJ |
4609 | } |
4610 | token::Ident(..) => { | |
a7813a04 XL |
4611 | if self.token.is_keyword(keywords::SelfValue) { |
4612 | // self | |
4613 | // self: TYPE | |
4614 | let eself_ident = expect_ident(self); | |
9cc50fc6 | 4615 | if self.eat(&token::Colon) { |
3157f602 XL |
4616 | let ty = self.parse_ty_sum()?; |
4617 | (SelfKind::Explicit(ty, Mutability::Immutable), eself_ident) | |
1a4d82fc | 4618 | } else { |
3157f602 | 4619 | (SelfKind::Value(Mutability::Immutable), eself_ident) |
1a4d82fc | 4620 | } |
a7813a04 | 4621 | } else if self.token.is_keyword(keywords::Mut) && |
85aaf69f | 4622 | self.look_ahead(1, |t| t.is_keyword(keywords::SelfValue)) { |
a7813a04 XL |
4623 | // mut self |
4624 | // mut self: TYPE | |
a7813a04 XL |
4625 | self.bump(); |
4626 | let eself_ident = expect_ident(self); | |
9cc50fc6 | 4627 | if self.eat(&token::Colon) { |
3157f602 XL |
4628 | let ty = self.parse_ty_sum()?; |
4629 | (SelfKind::Explicit(ty, Mutability::Mutable), eself_ident) | |
1a4d82fc | 4630 | } else { |
3157f602 | 4631 | (SelfKind::Value(Mutability::Mutable), eself_ident) |
1a4d82fc | 4632 | } |
1a4d82fc | 4633 | } else { |
3157f602 | 4634 | return Ok(None); |
1a4d82fc JJ |
4635 | } |
4636 | } | |
3157f602 | 4637 | _ => return Ok(None), |
223e47cc | 4638 | }; |
3157f602 XL |
4639 | |
4640 | let eself = codemap::respan(mk_sp(eself_lo, self.last_span.hi), eself); | |
4641 | Ok(Some(Arg::from_self(eself, eself_ident))) | |
4642 | } | |
4643 | ||
4644 | /// Parse the parameter list and result type of a function that may have a `self` parameter. | |
4645 | fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDecl>> | |
4646 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, | |
4647 | { | |
4648 | self.expect(&token::OpenDelim(token::Paren))?; | |
4649 | ||
4650 | // Parse optional self argument | |
4651 | let self_arg = self.parse_self_arg()?; | |
223e47cc | 4652 | |
a7813a04 XL |
4653 | // Parse the rest of the function parameter list. |
4654 | let sep = SeqSep::trailing_allowed(token::Comma); | |
3157f602 XL |
4655 | let fn_inputs = if let Some(self_arg) = self_arg { |
4656 | if self.check(&token::CloseDelim(token::Paren)) { | |
4657 | vec![self_arg] | |
4658 | } else if self.eat(&token::Comma) { | |
4659 | let mut fn_inputs = vec![self_arg]; | |
4660 | fn_inputs.append(&mut self.parse_seq_to_before_end( | |
4661 | &token::CloseDelim(token::Paren), sep, parse_arg_fn) | |
4662 | ); | |
4663 | fn_inputs | |
4664 | } else { | |
4665 | return self.unexpected(); | |
7453a54e | 4666 | } |
3157f602 XL |
4667 | } else { |
4668 | self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn) | |
1a4d82fc JJ |
4669 | }; |
4670 | ||
a7813a04 | 4671 | // Parse closing paren and return type. |
54a0048b | 4672 | self.expect(&token::CloseDelim(token::Paren))?; |
3157f602 | 4673 | Ok(P(FnDecl { |
1a4d82fc | 4674 | inputs: fn_inputs, |
a7813a04 | 4675 | output: self.parse_ret_ty()?, |
1a4d82fc | 4676 | variadic: false |
3157f602 | 4677 | })) |
223e47cc LB |
4678 | } |
4679 | ||
970d7e83 | 4680 | // parse the |arg, arg| header on a lambda |
9cc50fc6 | 4681 | fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> { |
85aaf69f | 4682 | let inputs_captures = { |
9cc50fc6 | 4683 | if self.eat(&token::OrOr) { |
85aaf69f | 4684 | Vec::new() |
223e47cc | 4685 | } else { |
54a0048b SL |
4686 | self.expect(&token::BinOp(token::Or))?; |
4687 | self.parse_obsolete_closure_kind()?; | |
7453a54e | 4688 | let args = self.parse_seq_to_before_end( |
1a4d82fc | 4689 | &token::BinOp(token::Or), |
7453a54e | 4690 | SeqSep::trailing_allowed(token::Comma), |
223e47cc | 4691 | |p| p.parse_fn_block_arg() |
7453a54e | 4692 | ); |
9cc50fc6 | 4693 | self.bump(); |
85aaf69f | 4694 | args |
223e47cc LB |
4695 | } |
4696 | }; | |
54a0048b | 4697 | let output = self.parse_ret_ty()?; |
223e47cc | 4698 | |
9346a6ac | 4699 | Ok(P(FnDecl { |
1a4d82fc | 4700 | inputs: inputs_captures, |
223e47cc | 4701 | output: output, |
1a4d82fc | 4702 | variadic: false |
9346a6ac | 4703 | })) |
1a4d82fc JJ |
4704 | } |
4705 | ||
1a4d82fc | 4706 | /// Parse the name and optional generic types of a function header. |
9cc50fc6 | 4707 | fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> { |
54a0048b SL |
4708 | let id = self.parse_ident()?; |
4709 | let generics = self.parse_generics()?; | |
9346a6ac | 4710 | Ok((id, generics)) |
223e47cc LB |
4711 | } |
4712 | ||
1a4d82fc | 4713 | fn mk_item(&mut self, lo: BytePos, hi: BytePos, ident: Ident, |
7453a54e | 4714 | node: ItemKind, vis: Visibility, |
1a4d82fc JJ |
4715 | attrs: Vec<Attribute>) -> P<Item> { |
4716 | P(Item { | |
4717 | ident: ident, | |
4718 | attrs: attrs, | |
4719 | id: ast::DUMMY_NODE_ID, | |
4720 | node: node, | |
4721 | vis: vis, | |
4722 | span: mk_sp(lo, hi) | |
4723 | }) | |
223e47cc LB |
4724 | } |
4725 | ||
1a4d82fc | 4726 | /// Parse an item-position function declaration. |
62682a34 SL |
4727 | fn parse_item_fn(&mut self, |
4728 | unsafety: Unsafety, | |
4729 | constness: Constness, | |
4730 | abi: abi::Abi) | |
9cc50fc6 | 4731 | -> PResult<'a, ItemInfo> { |
54a0048b SL |
4732 | let (ident, mut generics) = self.parse_fn_header()?; |
4733 | let decl = self.parse_fn_decl(false)?; | |
4734 | generics.where_clause = self.parse_where_clause()?; | |
4735 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | |
7453a54e | 4736 | Ok((ident, ItemKind::Fn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs))) |
62682a34 SL |
4737 | } |
4738 | ||
4739 | /// true if we are looking at `const ID`, false for things like `const fn` etc | |
4740 | pub fn is_const_item(&mut self) -> bool { | |
4741 | self.token.is_keyword(keywords::Const) && | |
b039eaaf SL |
4742 | !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) && |
4743 | !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) | |
62682a34 SL |
4744 | } |
4745 | ||
4746 | /// parses all the "front matter" for a `fn` declaration, up to | |
4747 | /// and including the `fn` keyword: | |
4748 | /// | |
4749 | /// - `const fn` | |
4750 | /// - `unsafe fn` | |
b039eaaf | 4751 | /// - `const unsafe fn` |
62682a34 SL |
4752 | /// - `extern fn` |
4753 | /// - etc | |
9cc50fc6 SL |
4754 | pub fn parse_fn_front_matter(&mut self) |
4755 | -> PResult<'a, (ast::Constness, ast::Unsafety, abi::Abi)> { | |
4756 | let is_const_fn = self.eat_keyword(keywords::Const); | |
54a0048b | 4757 | let unsafety = self.parse_unsafety()?; |
62682a34 | 4758 | let (constness, unsafety, abi) = if is_const_fn { |
7453a54e | 4759 | (Constness::Const, unsafety, Abi::Rust) |
62682a34 | 4760 | } else { |
9cc50fc6 | 4761 | let abi = if self.eat_keyword(keywords::Extern) { |
54a0048b | 4762 | self.parse_opt_abi()?.unwrap_or(Abi::C) |
62682a34 | 4763 | } else { |
7453a54e | 4764 | Abi::Rust |
62682a34 SL |
4765 | }; |
4766 | (Constness::NotConst, unsafety, abi) | |
4767 | }; | |
54a0048b | 4768 | self.expect_keyword(keywords::Fn)?; |
62682a34 | 4769 | Ok((constness, unsafety, abi)) |
223e47cc LB |
4770 | } |
4771 | ||
c34b1796 | 4772 | /// Parse an impl item. |
7453a54e SL |
4773 | pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> { |
4774 | maybe_whole!(no_clone_from_p self, NtImplItem); | |
d9579d0f | 4775 | |
54a0048b | 4776 | let mut attrs = self.parse_outer_attributes()?; |
d9579d0f | 4777 | let lo = self.span.lo; |
a7813a04 | 4778 | let vis = self.parse_visibility(true)?; |
54a0048b | 4779 | let defaultness = self.parse_defaultness()?; |
9cc50fc6 | 4780 | let (name, node) = if self.eat_keyword(keywords::Type) { |
54a0048b SL |
4781 | let name = self.parse_ident()?; |
4782 | self.expect(&token::Eq)?; | |
4783 | let typ = self.parse_ty_sum()?; | |
4784 | self.expect(&token::Semi)?; | |
92a42be0 | 4785 | (name, ast::ImplItemKind::Type(typ)) |
62682a34 | 4786 | } else if self.is_const_item() { |
54a0048b SL |
4787 | self.expect_keyword(keywords::Const)?; |
4788 | let name = self.parse_ident()?; | |
4789 | self.expect(&token::Colon)?; | |
4790 | let typ = self.parse_ty_sum()?; | |
4791 | self.expect(&token::Eq)?; | |
4792 | let expr = self.parse_expr()?; | |
5bcae85e | 4793 | self.expect(&token::Semi)?; |
92a42be0 | 4794 | (name, ast::ImplItemKind::Const(typ, expr)) |
c34b1796 | 4795 | } else { |
54a0048b | 4796 | let (name, inner_attrs, node) = self.parse_impl_method(&vis)?; |
62682a34 | 4797 | attrs.extend(inner_attrs); |
c34b1796 AL |
4798 | (name, node) |
4799 | }; | |
4800 | ||
7453a54e | 4801 | Ok(ImplItem { |
c34b1796 AL |
4802 | id: ast::DUMMY_NODE_ID, |
4803 | span: mk_sp(lo, self.last_span.hi), | |
4804 | ident: name, | |
4805 | vis: vis, | |
54a0048b | 4806 | defaultness: defaultness, |
c34b1796 AL |
4807 | attrs: attrs, |
4808 | node: node | |
7453a54e | 4809 | }) |
1a4d82fc JJ |
4810 | } |
4811 | ||
54a0048b SL |
4812 | fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) { |
4813 | match *visa { | |
4814 | Visibility::Inherited => (), | |
4815 | _ => { | |
9cc50fc6 | 4816 | let is_macro_rules: bool = match self.token { |
a7813a04 | 4817 | token::Ident(sid) => sid.name == intern("macro_rules"), |
9cc50fc6 SL |
4818 | _ => false, |
4819 | }; | |
4820 | if is_macro_rules { | |
4821 | self.diagnostic().struct_span_err(span, "can't qualify macro_rules \ | |
4822 | invocation with `pub`") | |
a7813a04 | 4823 | .help("did you mean #[macro_export]?") |
9cc50fc6 SL |
4824 | .emit(); |
4825 | } else { | |
4826 | self.diagnostic().struct_span_err(span, "can't qualify macro \ | |
4827 | invocation with `pub`") | |
a7813a04 XL |
4828 | .help("try adjusting the macro to put `pub` \ |
4829 | inside the invocation") | |
9cc50fc6 SL |
4830 | .emit(); |
4831 | } | |
85aaf69f | 4832 | } |
85aaf69f SL |
4833 | } |
4834 | } | |
4835 | ||
c34b1796 | 4836 | /// Parse a method or a macro invocation in a trait impl. |
54a0048b | 4837 | fn parse_impl_method(&mut self, vis: &Visibility) |
9cc50fc6 | 4838 | -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> { |
1a4d82fc | 4839 | // code copied from parse_macro_use_or_failure... abstraction! |
c34b1796 AL |
4840 | if !self.token.is_any_keyword() |
4841 | && self.look_ahead(1, |t| *t == token::Not) | |
4842 | && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) | |
4843 | || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { | |
4844 | // method macro. | |
85aaf69f | 4845 | |
c34b1796 | 4846 | let last_span = self.last_span; |
54a0048b | 4847 | self.complain_if_pub_macro(&vis, last_span); |
c34b1796 | 4848 | |
92a42be0 | 4849 | let lo = self.span.lo; |
a7813a04 | 4850 | let pth = self.parse_ident_into_path()?; |
54a0048b | 4851 | self.expect(&token::Not)?; |
c34b1796 AL |
4852 | |
4853 | // eat a matched-delimiter token tree: | |
54a0048b SL |
4854 | let delim = self.expect_open_delim()?; |
4855 | let tts = self.parse_seq_to_end(&token::CloseDelim(delim), | |
4856 | SeqSep::none(), | |
4857 | |p| p.parse_token_tree())?; | |
3157f602 | 4858 | let m_ = Mac_ { path: pth, tts: tts }; |
c34b1796 | 4859 | let m: ast::Mac = codemap::Spanned { node: m_, |
3157f602 XL |
4860 | span: mk_sp(lo, |
4861 | self.last_span.hi) }; | |
c34b1796 | 4862 | if delim != token::Brace { |
54a0048b | 4863 | self.expect(&token::Semi)? |
1a4d82fc | 4864 | } |
a7813a04 | 4865 | Ok((keywords::Invalid.ident(), vec![], ast::ImplItemKind::Macro(m))) |
c34b1796 | 4866 | } else { |
54a0048b SL |
4867 | let (constness, unsafety, abi) = self.parse_fn_front_matter()?; |
4868 | let ident = self.parse_ident()?; | |
4869 | let mut generics = self.parse_generics()?; | |
3157f602 | 4870 | let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; |
54a0048b SL |
4871 | generics.where_clause = self.parse_where_clause()?; |
4872 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | |
92a42be0 | 4873 | Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig { |
c34b1796 AL |
4874 | generics: generics, |
4875 | abi: abi, | |
c34b1796 | 4876 | unsafety: unsafety, |
62682a34 | 4877 | constness: constness, |
c34b1796 | 4878 | decl: decl |
9346a6ac | 4879 | }, body))) |
c34b1796 | 4880 | } |
223e47cc LB |
4881 | } |
4882 | ||
1a4d82fc | 4883 | /// Parse trait Foo { ... } |
9cc50fc6 | 4884 | fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { |
54a0048b SL |
4885 | let ident = self.parse_ident()?; |
4886 | let mut tps = self.parse_generics()?; | |
1a4d82fc JJ |
4887 | |
4888 | // Parse supertrait bounds. | |
54a0048b | 4889 | let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare)?; |
223e47cc | 4890 | |
54a0048b | 4891 | tps.where_clause = self.parse_where_clause()?; |
223e47cc | 4892 | |
54a0048b | 4893 | let meths = self.parse_trait_items()?; |
7453a54e | 4894 | Ok((ident, ItemKind::Trait(unsafety, tps, bounds, meths), None)) |
223e47cc LB |
4895 | } |
4896 | ||
c34b1796 | 4897 | /// Parses items implementations variants |
1a4d82fc | 4898 | /// impl<T> Foo { ... } |
c34b1796 AL |
4899 | /// impl<T> ToString for &'static T { ... } |
4900 | /// impl Send for .. {} | |
9cc50fc6 | 4901 | fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> { |
c34b1796 AL |
4902 | let impl_span = self.span; |
4903 | ||
1a4d82fc | 4904 | // First, parse type parameters if necessary. |
54a0048b | 4905 | let mut generics = self.parse_generics()?; |
223e47cc LB |
4906 | |
4907 | // Special case: if the next identifier that follows is '(', don't | |
4908 | // allow this to be parsed as a trait. | |
1a4d82fc JJ |
4909 | let could_be_trait = self.token != token::OpenDelim(token::Paren); |
4910 | ||
4911 | let neg_span = self.span; | |
9cc50fc6 | 4912 | let polarity = if self.eat(&token::Not) { |
1a4d82fc JJ |
4913 | ast::ImplPolarity::Negative |
4914 | } else { | |
4915 | ast::ImplPolarity::Positive | |
4916 | }; | |
223e47cc LB |
4917 | |
4918 | // Parse the trait. | |
54a0048b | 4919 | let mut ty = self.parse_ty_sum()?; |
223e47cc LB |
4920 | |
4921 | // Parse traits, if necessary. | |
9cc50fc6 | 4922 | let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { |
223e47cc | 4923 | // New-style trait. Reinterpret the type as a trait. |
c34b1796 | 4924 | match ty.node { |
7453a54e | 4925 | TyKind::Path(None, ref path) => { |
1a4d82fc JJ |
4926 | Some(TraitRef { |
4927 | path: (*path).clone(), | |
c34b1796 | 4928 | ref_id: ty.id, |
223e47cc LB |
4929 | }) |
4930 | } | |
4931 | _ => { | |
970d7e83 | 4932 | self.span_err(ty.span, "not a trait"); |
223e47cc LB |
4933 | None |
4934 | } | |
c34b1796 | 4935 | } |
223e47cc | 4936 | } else { |
1a4d82fc JJ |
4937 | match polarity { |
4938 | ast::ImplPolarity::Negative => { | |
4939 | // This is a negated type implementation | |
4940 | // `impl !MyType {}`, which is not allowed. | |
4941 | self.span_err(neg_span, "inherent implementation can't be negated"); | |
4942 | }, | |
4943 | _ => {} | |
4944 | } | |
223e47cc LB |
4945 | None |
4946 | }; | |
4947 | ||
9cc50fc6 | 4948 | if opt_trait.is_some() && self.eat(&token::DotDot) { |
c34b1796 AL |
4949 | if generics.is_parameterized() { |
4950 | self.span_err(impl_span, "default trait implementations are not \ | |
62682a34 | 4951 | allowed to have generics"); |
c34b1796 | 4952 | } |
223e47cc | 4953 | |
54a0048b SL |
4954 | self.expect(&token::OpenDelim(token::Brace))?; |
4955 | self.expect(&token::CloseDelim(token::Brace))?; | |
a7813a04 | 4956 | Ok((keywords::Invalid.ident(), |
7453a54e | 4957 | ItemKind::DefaultImpl(unsafety, opt_trait.unwrap()), None)) |
c34b1796 AL |
4958 | } else { |
4959 | if opt_trait.is_some() { | |
54a0048b | 4960 | ty = self.parse_ty_sum()?; |
c34b1796 | 4961 | } |
54a0048b | 4962 | generics.where_clause = self.parse_where_clause()?; |
223e47cc | 4963 | |
54a0048b SL |
4964 | self.expect(&token::OpenDelim(token::Brace))?; |
4965 | let attrs = self.parse_inner_attributes()?; | |
c34b1796 AL |
4966 | |
4967 | let mut impl_items = vec![]; | |
9cc50fc6 | 4968 | while !self.eat(&token::CloseDelim(token::Brace)) { |
54a0048b | 4969 | impl_items.push(self.parse_impl_item()?); |
c34b1796 AL |
4970 | } |
4971 | ||
a7813a04 | 4972 | Ok((keywords::Invalid.ident(), |
7453a54e | 4973 | ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items), |
9346a6ac | 4974 | Some(attrs))) |
c34b1796 | 4975 | } |
1a4d82fc JJ |
4976 | } |
4977 | ||
85aaf69f | 4978 | /// Parse a::B<String,i32> |
9cc50fc6 | 4979 | fn parse_trait_ref(&mut self) -> PResult<'a, TraitRef> { |
9346a6ac | 4980 | Ok(ast::TraitRef { |
a7813a04 | 4981 | path: self.parse_path(PathStyle::Type)?, |
1a4d82fc | 4982 | ref_id: ast::DUMMY_NODE_ID, |
9346a6ac | 4983 | }) |
223e47cc LB |
4984 | } |
4985 | ||
9cc50fc6 SL |
4986 | fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<ast::LifetimeDef>> { |
4987 | if self.eat_keyword(keywords::For) { | |
54a0048b SL |
4988 | self.expect(&token::Lt)?; |
4989 | let lifetime_defs = self.parse_lifetime_defs()?; | |
4990 | self.expect_gt()?; | |
9346a6ac | 4991 | Ok(lifetime_defs) |
1a4d82fc | 4992 | } else { |
9346a6ac | 4993 | Ok(Vec::new()) |
223e47cc LB |
4994 | } |
4995 | } | |
4996 | ||
85aaf69f | 4997 | /// Parse for<'l> a::B<String,i32> |
9cc50fc6 | 4998 | fn parse_poly_trait_ref(&mut self) -> PResult<'a, PolyTraitRef> { |
85aaf69f | 4999 | let lo = self.span.lo; |
54a0048b | 5000 | let lifetime_defs = self.parse_late_bound_lifetime_defs()?; |
1a4d82fc | 5001 | |
9346a6ac | 5002 | Ok(ast::PolyTraitRef { |
1a4d82fc | 5003 | bound_lifetimes: lifetime_defs, |
54a0048b | 5004 | trait_ref: self.parse_trait_ref()?, |
85aaf69f | 5005 | span: mk_sp(lo, self.last_span.hi), |
9346a6ac | 5006 | }) |
223e47cc LB |
5007 | } |
5008 | ||
1a4d82fc | 5009 | /// Parse struct Foo { ... } |
9cc50fc6 | 5010 | fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { |
54a0048b SL |
5011 | let class_name = self.parse_ident()?; |
5012 | let mut generics = self.parse_generics()?; | |
1a4d82fc | 5013 | |
1a4d82fc JJ |
5014 | // There is a special case worth noting here, as reported in issue #17904. |
5015 | // If we are parsing a tuple struct it is the case that the where clause | |
5016 | // should follow the field list. Like so: | |
5017 | // | |
5018 | // struct Foo<T>(T) where T: Copy; | |
5019 | // | |
5020 | // If we are parsing a normal record-style struct it is the case | |
5021 | // that the where clause comes before the body, and after the generics. | |
5022 | // So if we look ahead and see a brace or a where-clause we begin | |
5023 | // parsing a record style struct. | |
5024 | // | |
5025 | // Otherwise if we look ahead and see a paren we parse a tuple-style | |
5026 | // struct. | |
5027 | ||
b039eaaf | 5028 | let vdata = if self.token.is_keyword(keywords::Where) { |
54a0048b | 5029 | generics.where_clause = self.parse_where_clause()?; |
9cc50fc6 | 5030 | if self.eat(&token::Semi) { |
1a4d82fc | 5031 | // If we see a: `struct Foo<T> where T: Copy;` style decl. |
b039eaaf | 5032 | VariantData::Unit(ast::DUMMY_NODE_ID) |
1a4d82fc JJ |
5033 | } else { |
5034 | // If we see: `struct Foo<T> where T: Copy { ... }` | |
54a0048b | 5035 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) |
223e47cc | 5036 | } |
1a4d82fc | 5037 | // No `where` so: `struct Foo<T>;` |
9cc50fc6 | 5038 | } else if self.eat(&token::Semi) { |
b039eaaf | 5039 | VariantData::Unit(ast::DUMMY_NODE_ID) |
1a4d82fc JJ |
5040 | // Record-style struct definition |
5041 | } else if self.token == token::OpenDelim(token::Brace) { | |
54a0048b | 5042 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) |
1a4d82fc | 5043 | // Tuple-style struct definition with optional where-clause. |
e9174d1e | 5044 | } else if self.token == token::OpenDelim(token::Paren) { |
54a0048b SL |
5045 | let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); |
5046 | generics.where_clause = self.parse_where_clause()?; | |
5047 | self.expect(&token::Semi)?; | |
92a42be0 | 5048 | body |
e9174d1e SL |
5049 | } else { |
5050 | let token_str = self.this_token_to_string(); | |
5051 | return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \ | |
5052 | name, found `{}`", token_str))) | |
1a4d82fc | 5053 | }; |
223e47cc | 5054 | |
7453a54e | 5055 | Ok((class_name, ItemKind::Struct(vdata, generics), None)) |
223e47cc LB |
5056 | } |
5057 | ||
54a0048b | 5058 | pub fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> { |
1a4d82fc | 5059 | let mut fields = Vec::new(); |
9cc50fc6 | 5060 | if self.eat(&token::OpenDelim(token::Brace)) { |
1a4d82fc | 5061 | while self.token != token::CloseDelim(token::Brace) { |
54a0048b | 5062 | fields.push(self.parse_struct_decl_field()?); |
1a4d82fc JJ |
5063 | } |
5064 | ||
9cc50fc6 | 5065 | self.bump(); |
1a4d82fc JJ |
5066 | } else { |
5067 | let token_str = self.this_token_to_string(); | |
e9174d1e SL |
5068 | return Err(self.fatal(&format!("expected `where`, or `{{` after struct \ |
5069 | name, found `{}`", | |
9346a6ac | 5070 | token_str))); |
1a4d82fc JJ |
5071 | } |
5072 | ||
9346a6ac | 5073 | Ok(fields) |
1a4d82fc JJ |
5074 | } |
5075 | ||
54a0048b | 5076 | pub fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> { |
1a4d82fc | 5077 | // This is the case where we find `struct Foo<T>(T) where T: Copy;` |
e9174d1e | 5078 | // Unit like structs are handled in parse_item_struct function |
54a0048b | 5079 | let fields = self.parse_unspanned_seq( |
e9174d1e SL |
5080 | &token::OpenDelim(token::Paren), |
5081 | &token::CloseDelim(token::Paren), | |
7453a54e | 5082 | SeqSep::trailing_allowed(token::Comma), |
e9174d1e | 5083 | |p| { |
54a0048b | 5084 | let attrs = p.parse_outer_attributes()?; |
e9174d1e | 5085 | let lo = p.span.lo; |
a7813a04 XL |
5086 | let mut vis = p.parse_visibility(false)?; |
5087 | let ty_is_interpolated = | |
5088 | p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated()); | |
5089 | let mut ty = p.parse_ty_sum()?; | |
5090 | ||
5091 | // Handle `pub(path) type`, in which `vis` will be `pub` and `ty` will be `(path)`. | |
5092 | if vis == Visibility::Public && !ty_is_interpolated && | |
5093 | p.token != token::Comma && p.token != token::CloseDelim(token::Paren) { | |
5094 | ty = if let TyKind::Paren(ref path_ty) = ty.node { | |
5095 | if let TyKind::Path(None, ref path) = path_ty.node { | |
5096 | vis = Visibility::Restricted { path: P(path.clone()), id: path_ty.id }; | |
5097 | Some(p.parse_ty_sum()?) | |
5098 | } else { | |
5099 | None | |
5100 | } | |
5101 | } else { | |
5102 | None | |
5103 | }.unwrap_or(ty); | |
5104 | } | |
54a0048b SL |
5105 | Ok(StructField { |
5106 | span: mk_sp(lo, p.span.hi), | |
5107 | vis: vis, | |
5108 | ident: None, | |
e9174d1e | 5109 | id: ast::DUMMY_NODE_ID, |
54a0048b | 5110 | ty: ty, |
e9174d1e | 5111 | attrs: attrs, |
54a0048b SL |
5112 | }) |
5113 | })?; | |
223e47cc | 5114 | |
e9174d1e | 5115 | Ok(fields) |
1a4d82fc | 5116 | } |
223e47cc | 5117 | |
1a4d82fc JJ |
5118 | /// Parse a structure field declaration |
5119 | pub fn parse_single_struct_field(&mut self, | |
5bcae85e | 5120 | lo: BytePos, |
1a4d82fc JJ |
5121 | vis: Visibility, |
5122 | attrs: Vec<Attribute> ) | |
9cc50fc6 | 5123 | -> PResult<'a, StructField> { |
5bcae85e | 5124 | let a_var = self.parse_name_and_ty(lo, vis, attrs)?; |
1a4d82fc JJ |
5125 | match self.token { |
5126 | token::Comma => { | |
9cc50fc6 | 5127 | self.bump(); |
223e47cc | 5128 | } |
1a4d82fc | 5129 | token::CloseDelim(token::Brace) => {} |
223e47cc | 5130 | _ => { |
1a4d82fc JJ |
5131 | let span = self.span; |
5132 | let token_str = self.this_token_to_string(); | |
9346a6ac | 5133 | return Err(self.span_fatal_help(span, |
1a4d82fc | 5134 | &format!("expected `,`, or `}}`, found `{}`", |
85aaf69f | 5135 | token_str), |
9346a6ac | 5136 | "struct fields should be separated by commas")) |
223e47cc LB |
5137 | } |
5138 | } | |
9346a6ac | 5139 | Ok(a_var) |
223e47cc LB |
5140 | } |
5141 | ||
1a4d82fc | 5142 | /// Parse an element of a struct definition |
54a0048b | 5143 | fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { |
54a0048b | 5144 | let attrs = self.parse_outer_attributes()?; |
5bcae85e | 5145 | let lo = self.span.lo; |
a7813a04 | 5146 | let vis = self.parse_visibility(true)?; |
5bcae85e | 5147 | self.parse_single_struct_field(lo, vis, attrs) |
223e47cc LB |
5148 | } |
5149 | ||
a7813a04 XL |
5150 | // If `allow_path` is false, just parse the `pub` in `pub(path)` (but still parse `pub(crate)`) |
5151 | fn parse_visibility(&mut self, allow_path: bool) -> PResult<'a, Visibility> { | |
5152 | let pub_crate = |this: &mut Self| { | |
5153 | let span = this.last_span; | |
5154 | this.expect(&token::CloseDelim(token::Paren))?; | |
5155 | Ok(Visibility::Crate(span)) | |
5156 | }; | |
5157 | ||
5158 | if !self.eat_keyword(keywords::Pub) { | |
5159 | Ok(Visibility::Inherited) | |
5160 | } else if !allow_path { | |
5161 | // Look ahead to avoid eating the `(` in `pub(path)` while still parsing `pub(crate)` | |
5162 | if self.token == token::OpenDelim(token::Paren) && | |
5163 | self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) { | |
5164 | self.bump(); self.bump(); | |
5165 | pub_crate(self) | |
5166 | } else { | |
5167 | Ok(Visibility::Public) | |
5168 | } | |
5169 | } else if !self.eat(&token::OpenDelim(token::Paren)) { | |
5170 | Ok(Visibility::Public) | |
5171 | } else if self.eat_keyword(keywords::Crate) { | |
5172 | pub_crate(self) | |
5173 | } else { | |
5174 | let path = self.parse_path(PathStyle::Mod)?; | |
5175 | self.expect(&token::CloseDelim(token::Paren))?; | |
5176 | Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID }) | |
5177 | } | |
223e47cc LB |
5178 | } |
5179 | ||
54a0048b SL |
5180 | /// Parse defaultness: DEFAULT or nothing |
5181 | fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> { | |
a7813a04 | 5182 | if self.eat_contextual_keyword(keywords::Default.ident()) { |
54a0048b SL |
5183 | Ok(Defaultness::Default) |
5184 | } else { | |
5185 | Ok(Defaultness::Final) | |
5186 | } | |
5187 | } | |
5188 | ||
c34b1796 | 5189 | /// Given a termination token, parse all of the items in a module |
9cc50fc6 | 5190 | fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> PResult<'a, Mod> { |
85aaf69f | 5191 | let mut items = vec![]; |
54a0048b | 5192 | while let Some(item) = self.parse_item()? { |
c34b1796 | 5193 | items.push(item); |
85aaf69f | 5194 | } |
223e47cc | 5195 | |
9cc50fc6 | 5196 | if !self.eat(term) { |
c34b1796 | 5197 | let token_str = self.this_token_to_string(); |
9346a6ac | 5198 | return Err(self.fatal(&format!("expected item, found `{}`", token_str))); |
223e47cc LB |
5199 | } |
5200 | ||
3157f602 | 5201 | let hi = if self.span == syntax_pos::DUMMY_SP { |
c1a9b12d SL |
5202 | inner_lo |
5203 | } else { | |
b039eaaf | 5204 | self.last_span.hi |
c1a9b12d SL |
5205 | }; |
5206 | ||
9346a6ac | 5207 | Ok(ast::Mod { |
c1a9b12d | 5208 | inner: mk_sp(inner_lo, hi), |
1a4d82fc | 5209 | items: items |
9346a6ac | 5210 | }) |
223e47cc LB |
5211 | } |
5212 | ||
9cc50fc6 | 5213 | fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> { |
54a0048b SL |
5214 | let id = self.parse_ident()?; |
5215 | self.expect(&token::Colon)?; | |
5216 | let ty = self.parse_ty_sum()?; | |
5217 | self.expect(&token::Eq)?; | |
5218 | let e = self.parse_expr()?; | |
5bcae85e | 5219 | self.expect(&token::Semi)?; |
1a4d82fc | 5220 | let item = match m { |
7453a54e SL |
5221 | Some(m) => ItemKind::Static(ty, m, e), |
5222 | None => ItemKind::Const(ty, e), | |
1a4d82fc | 5223 | }; |
9346a6ac | 5224 | Ok((id, item, None)) |
223e47cc LB |
5225 | } |
5226 | ||
1a4d82fc | 5227 | /// Parse a `mod <foo> { ... }` or `mod <foo>;` item |
9cc50fc6 | 5228 | fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { |
5bcae85e SL |
5229 | let outer_attrs = ::config::StripUnconfigured { |
5230 | config: &self.cfg, | |
5231 | sess: self.sess, | |
5232 | should_test: false, // irrelevant | |
5233 | features: None, // don't perform gated feature checking | |
5234 | }.process_cfg_attrs(outer_attrs.to_owned()); | |
5235 | ||
1a4d82fc | 5236 | let id_span = self.span; |
54a0048b | 5237 | let id = self.parse_ident()?; |
1a4d82fc | 5238 | if self.check(&token::Semi) { |
9cc50fc6 | 5239 | self.bump(); |
223e47cc | 5240 | // This mod is in an external file. Let's go get it! |
5bcae85e | 5241 | let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?; |
9346a6ac | 5242 | Ok((id, m, Some(attrs))) |
223e47cc | 5243 | } else { |
5bcae85e | 5244 | self.push_mod_path(id, &outer_attrs); |
54a0048b | 5245 | self.expect(&token::OpenDelim(token::Brace))?; |
1a4d82fc | 5246 | let mod_inner_lo = self.span.lo; |
54a0048b SL |
5247 | let attrs = self.parse_inner_attributes()?; |
5248 | let m = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; | |
223e47cc | 5249 | self.pop_mod_path(); |
7453a54e | 5250 | Ok((id, ItemKind::Mod(m), Some(attrs))) |
223e47cc LB |
5251 | } |
5252 | } | |
5253 | ||
1a4d82fc JJ |
5254 | fn push_mod_path(&mut self, id: Ident, attrs: &[Attribute]) { |
5255 | let default_path = self.id_to_interned_str(id); | |
c1a9b12d | 5256 | let file_path = match ::attr::first_attr_value_str_by_name(attrs, "path") { |
970d7e83 | 5257 | Some(d) => d, |
1a4d82fc | 5258 | None => default_path, |
223e47cc LB |
5259 | }; |
5260 | self.mod_path_stack.push(file_path) | |
5261 | } | |
5262 | ||
1a4d82fc JJ |
5263 | fn pop_mod_path(&mut self) { |
5264 | self.mod_path_stack.pop().unwrap(); | |
5265 | } | |
5266 | ||
c1a9b12d SL |
5267 | pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> { |
5268 | ::attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d)) | |
5269 | } | |
5270 | ||
5271 | /// Returns either a path to a module, or . | |
5272 | pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath | |
5273 | { | |
5274 | let mod_name = id.to_string(); | |
5275 | let default_path_str = format!("{}.rs", mod_name); | |
5276 | let secondary_path_str = format!("{}/mod.rs", mod_name); | |
5277 | let default_path = dir_path.join(&default_path_str); | |
5278 | let secondary_path = dir_path.join(&secondary_path_str); | |
5279 | let default_exists = codemap.file_exists(&default_path); | |
5280 | let secondary_exists = codemap.file_exists(&secondary_path); | |
5281 | ||
5282 | let result = match (default_exists, secondary_exists) { | |
5283 | (true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }), | |
5284 | (false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }), | |
5285 | (false, false) => Err(ModulePathError { | |
5286 | err_msg: format!("file not found for module `{}`", mod_name), | |
5287 | help_msg: format!("name the file either {} or {} inside the directory {:?}", | |
5288 | default_path_str, | |
5289 | secondary_path_str, | |
5290 | dir_path.display()), | |
5291 | }), | |
5292 | (true, true) => Err(ModulePathError { | |
5293 | err_msg: format!("file for module `{}` found at both {} and {}", | |
5294 | mod_name, | |
5295 | default_path_str, | |
5296 | secondary_path_str), | |
5297 | help_msg: "delete or rename one of them to remove the ambiguity".to_owned(), | |
5298 | }), | |
5299 | }; | |
5300 | ||
5301 | ModulePath { | |
5302 | name: mod_name, | |
5303 | path_exists: default_exists || secondary_exists, | |
5304 | result: result, | |
5305 | } | |
5306 | } | |
5307 | ||
5308 | fn submod_path(&mut self, | |
5309 | id: ast::Ident, | |
5310 | outer_attrs: &[ast::Attribute], | |
9cc50fc6 | 5311 | id_sp: Span) -> PResult<'a, ModulePathSuccess> { |
54a0048b | 5312 | let mut prefix = PathBuf::from(self.filename.as_ref().unwrap()); |
1a4d82fc | 5313 | prefix.pop(); |
c34b1796 AL |
5314 | let mut dir_path = prefix; |
5315 | for part in &self.mod_path_stack { | |
5316 | dir_path.push(&**part); | |
5317 | } | |
223e47cc | 5318 | |
c1a9b12d SL |
5319 | if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &dir_path) { |
5320 | return Ok(ModulePathSuccess { path: p, owns_directory: true }); | |
5321 | } | |
5322 | ||
5323 | let paths = Parser::default_submod_path(id, &dir_path, self.sess.codemap()); | |
5324 | ||
7453a54e SL |
5325 | if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) { |
5326 | let msg = | |
5327 | "Cannot declare a non-inline module inside a block unless it has a path attribute"; | |
5328 | let mut err = self.diagnostic().struct_span_err(id_sp, msg); | |
5329 | if paths.path_exists { | |
5330 | let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", | |
5331 | paths.name); | |
5332 | err.span_note(id_sp, &msg); | |
5333 | } | |
5334 | return Err(err); | |
5335 | } else if !self.owns_directory { | |
9cc50fc6 SL |
5336 | let mut err = self.diagnostic().struct_span_err(id_sp, |
5337 | "cannot declare a new module at this location"); | |
c1a9b12d SL |
5338 | let this_module = match self.mod_path_stack.last() { |
5339 | Some(name) => name.to_string(), | |
5340 | None => self.root_module_name.as_ref().unwrap().clone(), | |
5341 | }; | |
9cc50fc6 SL |
5342 | err.span_note(id_sp, |
5343 | &format!("maybe move this module `{0}` to its own directory \ | |
c1a9b12d SL |
5344 | via `{0}/mod.rs`", |
5345 | this_module)); | |
5346 | if paths.path_exists { | |
9cc50fc6 SL |
5347 | err.span_note(id_sp, |
5348 | &format!("... or maybe `use` the module `{}` instead \ | |
5349 | of possibly redeclaring it", | |
5350 | paths.name)); | |
223e47cc | 5351 | } |
7453a54e | 5352 | return Err(err); |
c1a9b12d SL |
5353 | } |
5354 | ||
5355 | match paths.result { | |
5356 | Ok(succ) => Ok(succ), | |
5357 | Err(err) => Err(self.span_fatal_help(id_sp, &err.err_msg, &err.help_msg)), | |
5358 | } | |
5359 | } | |
5360 | ||
5361 | /// Read a module from a source file. | |
5362 | fn eval_src_mod(&mut self, | |
5363 | id: ast::Ident, | |
5364 | outer_attrs: &[ast::Attribute], | |
5365 | id_sp: Span) | |
7453a54e | 5366 | -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> { |
54a0048b SL |
5367 | let ModulePathSuccess { path, owns_directory } = self.submod_path(id, |
5368 | outer_attrs, | |
5369 | id_sp)?; | |
223e47cc | 5370 | |
c1a9b12d SL |
5371 | self.eval_src_mod_from_path(path, |
5372 | owns_directory, | |
5373 | id.to_string(), | |
5374 | id_sp) | |
1a4d82fc JJ |
5375 | } |
5376 | ||
5377 | fn eval_src_mod_from_path(&mut self, | |
c34b1796 | 5378 | path: PathBuf, |
1a4d82fc JJ |
5379 | owns_directory: bool, |
5380 | name: String, | |
7453a54e | 5381 | id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> { |
1a4d82fc | 5382 | let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); |
3157f602 XL |
5383 | if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { |
5384 | let mut err = String::from("circular modules: "); | |
5385 | let len = included_mod_stack.len(); | |
5386 | for p in &included_mod_stack[i.. len] { | |
5387 | err.push_str(&p.to_string_lossy()); | |
5388 | err.push_str(" -> "); | |
223e47cc | 5389 | } |
3157f602 XL |
5390 | err.push_str(&path.to_string_lossy()); |
5391 | return Err(self.span_fatal(id_sp, &err[..])); | |
1a4d82fc JJ |
5392 | } |
5393 | included_mod_stack.push(path.clone()); | |
5394 | drop(included_mod_stack); | |
5395 | ||
c1a9b12d SL |
5396 | let mut p0 = new_sub_parser_from_file(self.sess, |
5397 | self.cfg.clone(), | |
5398 | &path, | |
5399 | owns_directory, | |
5400 | Some(name), | |
5401 | id_sp); | |
1a4d82fc | 5402 | let mod_inner_lo = p0.span.lo; |
54a0048b SL |
5403 | let mod_attrs = p0.parse_inner_attributes()?; |
5404 | let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; | |
1a4d82fc | 5405 | self.sess.included_mod_stack.borrow_mut().pop(); |
7453a54e | 5406 | Ok((ast::ItemKind::Mod(m0), mod_attrs)) |
223e47cc LB |
5407 | } |
5408 | ||
1a4d82fc | 5409 | /// Parse a function declaration from a foreign module |
b039eaaf | 5410 | fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: BytePos, |
7453a54e | 5411 | attrs: Vec<Attribute>) -> PResult<'a, ForeignItem> { |
54a0048b | 5412 | self.expect_keyword(keywords::Fn)?; |
1a4d82fc | 5413 | |
54a0048b SL |
5414 | let (ident, mut generics) = self.parse_fn_header()?; |
5415 | let decl = self.parse_fn_decl(true)?; | |
5416 | generics.where_clause = self.parse_where_clause()?; | |
970d7e83 | 5417 | let hi = self.span.hi; |
54a0048b | 5418 | self.expect(&token::Semi)?; |
7453a54e | 5419 | Ok(ast::ForeignItem { |
1a4d82fc JJ |
5420 | ident: ident, |
5421 | attrs: attrs, | |
7453a54e | 5422 | node: ForeignItemKind::Fn(decl, generics), |
1a4d82fc JJ |
5423 | id: ast::DUMMY_NODE_ID, |
5424 | span: mk_sp(lo, hi), | |
5425 | vis: vis | |
7453a54e | 5426 | }) |
1a4d82fc JJ |
5427 | } |
5428 | ||
5429 | /// Parse a static item from a foreign module | |
b039eaaf | 5430 | fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: BytePos, |
7453a54e | 5431 | attrs: Vec<Attribute>) -> PResult<'a, ForeignItem> { |
54a0048b | 5432 | self.expect_keyword(keywords::Static)?; |
9cc50fc6 | 5433 | let mutbl = self.eat_keyword(keywords::Mut); |
223e47cc | 5434 | |
54a0048b SL |
5435 | let ident = self.parse_ident()?; |
5436 | self.expect(&token::Colon)?; | |
5437 | let ty = self.parse_ty_sum()?; | |
223e47cc | 5438 | let hi = self.span.hi; |
54a0048b | 5439 | self.expect(&token::Semi)?; |
7453a54e | 5440 | Ok(ForeignItem { |
1a4d82fc JJ |
5441 | ident: ident, |
5442 | attrs: attrs, | |
7453a54e | 5443 | node: ForeignItemKind::Static(ty, mutbl), |
1a4d82fc JJ |
5444 | id: ast::DUMMY_NODE_ID, |
5445 | span: mk_sp(lo, hi), | |
5446 | vis: vis | |
7453a54e | 5447 | }) |
223e47cc LB |
5448 | } |
5449 | ||
1a4d82fc JJ |
5450 | /// Parse extern crate links |
5451 | /// | |
c34b1796 | 5452 | /// # Examples |
1a4d82fc | 5453 | /// |
c34b1796 AL |
5454 | /// extern crate foo; |
5455 | /// extern crate bar as foo; | |
1a4d82fc | 5456 | fn parse_item_extern_crate(&mut self, |
c34b1796 AL |
5457 | lo: BytePos, |
5458 | visibility: Visibility, | |
5459 | attrs: Vec<Attribute>) | |
9cc50fc6 | 5460 | -> PResult<'a, P<Item>> { |
223e47cc | 5461 | |
54a0048b SL |
5462 | let crate_name = self.parse_ident()?; |
5463 | let (maybe_path, ident) = if let Some(ident) = self.parse_rename()? { | |
e9174d1e | 5464 | (Some(crate_name.name), ident) |
c34b1796 AL |
5465 | } else { |
5466 | (None, crate_name) | |
223e47cc | 5467 | }; |
54a0048b | 5468 | self.expect(&token::Semi)?; |
223e47cc | 5469 | |
85aaf69f | 5470 | let last_span = self.last_span; |
9346a6ac | 5471 | Ok(self.mk_item(lo, |
e9174d1e SL |
5472 | last_span.hi, |
5473 | ident, | |
7453a54e | 5474 | ItemKind::ExternCrate(maybe_path), |
e9174d1e SL |
5475 | visibility, |
5476 | attrs)) | |
1a4d82fc | 5477 | } |
970d7e83 | 5478 | |
1a4d82fc JJ |
5479 | /// Parse `extern` for foreign ABIs |
5480 | /// modules. | |
5481 | /// | |
5482 | /// `extern` is expected to have been | |
5483 | /// consumed before calling this method | |
5484 | /// | |
5485 | /// # Examples: | |
5486 | /// | |
5487 | /// extern "C" {} | |
5488 | /// extern {} | |
5489 | fn parse_item_foreign_mod(&mut self, | |
5490 | lo: BytePos, | |
5491 | opt_abi: Option<abi::Abi>, | |
5492 | visibility: Visibility, | |
c34b1796 | 5493 | mut attrs: Vec<Attribute>) |
9cc50fc6 | 5494 | -> PResult<'a, P<Item>> { |
54a0048b | 5495 | self.expect(&token::OpenDelim(token::Brace))?; |
223e47cc | 5496 | |
7453a54e | 5497 | let abi = opt_abi.unwrap_or(Abi::C); |
223e47cc | 5498 | |
54a0048b | 5499 | attrs.extend(self.parse_inner_attributes()?); |
c34b1796 AL |
5500 | |
5501 | let mut foreign_items = vec![]; | |
54a0048b | 5502 | while let Some(item) = self.parse_foreign_item()? { |
c34b1796 AL |
5503 | foreign_items.push(item); |
5504 | } | |
54a0048b | 5505 | self.expect(&token::CloseDelim(token::Brace))?; |
223e47cc | 5506 | |
1a4d82fc | 5507 | let last_span = self.last_span; |
c34b1796 AL |
5508 | let m = ast::ForeignMod { |
5509 | abi: abi, | |
5510 | items: foreign_items | |
5511 | }; | |
9346a6ac | 5512 | Ok(self.mk_item(lo, |
85aaf69f | 5513 | last_span.hi, |
a7813a04 | 5514 | keywords::Invalid.ident(), |
7453a54e | 5515 | ItemKind::ForeignMod(m), |
85aaf69f | 5516 | visibility, |
9346a6ac | 5517 | attrs)) |
223e47cc LB |
5518 | } |
5519 | ||
1a4d82fc | 5520 | /// Parse type Foo = Bar; |
9cc50fc6 | 5521 | fn parse_item_type(&mut self) -> PResult<'a, ItemInfo> { |
54a0048b SL |
5522 | let ident = self.parse_ident()?; |
5523 | let mut tps = self.parse_generics()?; | |
5524 | tps.where_clause = self.parse_where_clause()?; | |
5525 | self.expect(&token::Eq)?; | |
5526 | let ty = self.parse_ty_sum()?; | |
5527 | self.expect(&token::Semi)?; | |
7453a54e | 5528 | Ok((ident, ItemKind::Ty(ty, tps), None)) |
223e47cc LB |
5529 | } |
5530 | ||
1a4d82fc | 5531 | /// Parse the part of an "enum" decl following the '{' |
9cc50fc6 | 5532 | fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> { |
1a4d82fc | 5533 | let mut variants = Vec::new(); |
970d7e83 | 5534 | let mut all_nullary = true; |
1a4d82fc JJ |
5535 | let mut any_disr = None; |
5536 | while self.token != token::CloseDelim(token::Brace) { | |
54a0048b | 5537 | let variant_attrs = self.parse_outer_attributes()?; |
223e47cc LB |
5538 | let vlo = self.span.lo; |
5539 | ||
b039eaaf | 5540 | let struct_def; |
970d7e83 | 5541 | let mut disr_expr = None; |
54a0048b | 5542 | let ident = self.parse_ident()?; |
92a42be0 | 5543 | if self.check(&token::OpenDelim(token::Brace)) { |
223e47cc LB |
5544 | // Parse a struct variant. |
5545 | all_nullary = false; | |
54a0048b | 5546 | struct_def = VariantData::Struct(self.parse_record_struct_body()?, |
92a42be0 | 5547 | ast::DUMMY_NODE_ID); |
1a4d82fc | 5548 | } else if self.check(&token::OpenDelim(token::Paren)) { |
223e47cc | 5549 | all_nullary = false; |
54a0048b | 5550 | struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?, |
92a42be0 | 5551 | ast::DUMMY_NODE_ID); |
9cc50fc6 | 5552 | } else if self.eat(&token::Eq) { |
54a0048b | 5553 | disr_expr = Some(self.parse_expr()?); |
1a4d82fc | 5554 | any_disr = disr_expr.as_ref().map(|expr| expr.span); |
92a42be0 | 5555 | struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); |
223e47cc | 5556 | } else { |
92a42be0 | 5557 | struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); |
223e47cc | 5558 | } |
223e47cc | 5559 | |
1a4d82fc | 5560 | let vr = ast::Variant_ { |
223e47cc LB |
5561 | name: ident, |
5562 | attrs: variant_attrs, | |
b039eaaf | 5563 | data: struct_def, |
223e47cc | 5564 | disr_expr: disr_expr, |
223e47cc | 5565 | }; |
7453a54e | 5566 | variants.push(spanned(vlo, self.last_span.hi, vr)); |
223e47cc | 5567 | |
9cc50fc6 | 5568 | if !self.eat(&token::Comma) { break; } |
223e47cc | 5569 | } |
54a0048b | 5570 | self.expect(&token::CloseDelim(token::Brace))?; |
1a4d82fc JJ |
5571 | match any_disr { |
5572 | Some(disr_span) if !all_nullary => | |
5573 | self.span_err(disr_span, | |
5574 | "discriminator values can only be used with a c-like enum"), | |
5575 | _ => () | |
223e47cc LB |
5576 | } |
5577 | ||
9346a6ac | 5578 | Ok(ast::EnumDef { variants: variants }) |
223e47cc LB |
5579 | } |
5580 | ||
1a4d82fc | 5581 | /// Parse an "enum" declaration |
9cc50fc6 | 5582 | fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { |
54a0048b SL |
5583 | let id = self.parse_ident()?; |
5584 | let mut generics = self.parse_generics()?; | |
5585 | generics.where_clause = self.parse_where_clause()?; | |
5586 | self.expect(&token::OpenDelim(token::Brace))?; | |
223e47cc | 5587 | |
54a0048b | 5588 | let enum_definition = self.parse_enum_def(&generics)?; |
7453a54e | 5589 | Ok((id, ItemKind::Enum(enum_definition, generics), None)) |
223e47cc LB |
5590 | } |
5591 | ||
1a4d82fc JJ |
5592 | /// Parses a string as an ABI spec on an extern type or module. Consumes |
5593 | /// the `extern` keyword, if one is found. | |
9cc50fc6 | 5594 | fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> { |
1a4d82fc JJ |
5595 | match self.token { |
5596 | token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => { | |
5597 | let sp = self.span; | |
5598 | self.expect_no_suffix(sp, "ABI spec", suf); | |
9cc50fc6 | 5599 | self.bump(); |
c1a9b12d | 5600 | match abi::lookup(&s.as_str()) { |
9346a6ac | 5601 | Some(abi) => Ok(Some(abi)), |
1a4d82fc JJ |
5602 | None => { |
5603 | let last_span = self.last_span; | |
5604 | self.span_err( | |
5605 | last_span, | |
c1a9b12d | 5606 | &format!("invalid ABI: expected one of [{}], \ |
1a4d82fc | 5607 | found `{}`", |
c1a9b12d SL |
5608 | abi::all_names().join(", "), |
5609 | s)); | |
9346a6ac | 5610 | Ok(None) |
223e47cc LB |
5611 | } |
5612 | } | |
223e47cc LB |
5613 | } |
5614 | ||
9346a6ac | 5615 | _ => Ok(None), |
223e47cc LB |
5616 | } |
5617 | } | |
5618 | ||
c34b1796 | 5619 | /// Parse one of the items allowed by the flags. |
1a4d82fc JJ |
5620 | /// NB: this function no longer parses the items inside an |
5621 | /// extern crate. | |
85aaf69f | 5622 | fn parse_item_(&mut self, attrs: Vec<Attribute>, |
9cc50fc6 | 5623 | macros_allowed: bool, attributes_allowed: bool) -> PResult<'a, Option<P<Item>>> { |
1a4d82fc JJ |
5624 | let nt_item = match self.token { |
5625 | token::Interpolated(token::NtItem(ref item)) => { | |
5626 | Some((**item).clone()) | |
5627 | } | |
5628 | _ => None | |
5629 | }; | |
3157f602 XL |
5630 | if let Some(mut item) = nt_item { |
5631 | self.bump(); | |
5632 | let mut attrs = attrs; | |
5633 | mem::swap(&mut item.attrs, &mut attrs); | |
5634 | item.attrs.extend(attrs); | |
5635 | return Ok(Some(P(item))); | |
1a4d82fc JJ |
5636 | } |
5637 | ||
223e47cc LB |
5638 | let lo = self.span.lo; |
5639 | ||
a7813a04 | 5640 | let visibility = self.parse_visibility(true)?; |
970d7e83 | 5641 | |
9cc50fc6 | 5642 | if self.eat_keyword(keywords::Use) { |
85aaf69f | 5643 | // USE ITEM |
54a0048b SL |
5644 | let item_ = ItemKind::Use(self.parse_view_path()?); |
5645 | self.expect(&token::Semi)?; | |
85aaf69f SL |
5646 | |
5647 | let last_span = self.last_span; | |
5648 | let item = self.mk_item(lo, | |
5649 | last_span.hi, | |
a7813a04 | 5650 | keywords::Invalid.ident(), |
85aaf69f SL |
5651 | item_, |
5652 | visibility, | |
5653 | attrs); | |
9346a6ac | 5654 | return Ok(Some(item)); |
223e47cc | 5655 | } |
1a4d82fc | 5656 | |
9cc50fc6 SL |
5657 | if self.eat_keyword(keywords::Extern) { |
5658 | if self.eat_keyword(keywords::Crate) { | |
54a0048b | 5659 | return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?)); |
1a4d82fc JJ |
5660 | } |
5661 | ||
54a0048b | 5662 | let opt_abi = self.parse_opt_abi()?; |
223e47cc | 5663 | |
9cc50fc6 | 5664 | if self.eat_keyword(keywords::Fn) { |
970d7e83 | 5665 | // EXTERN FUNCTION ITEM |
7453a54e | 5666 | let abi = opt_abi.unwrap_or(Abi::C); |
970d7e83 | 5667 | let (ident, item_, extra_attrs) = |
54a0048b | 5668 | self.parse_item_fn(Unsafety::Normal, Constness::NotConst, abi)?; |
1a4d82fc JJ |
5669 | let last_span = self.last_span; |
5670 | let item = self.mk_item(lo, | |
5671 | last_span.hi, | |
5672 | ident, | |
5673 | item_, | |
5674 | visibility, | |
5675 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5676 | return Ok(Some(item)); |
1a4d82fc | 5677 | } else if self.check(&token::OpenDelim(token::Brace)) { |
54a0048b | 5678 | return Ok(Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)?)); |
970d7e83 | 5679 | } |
1a4d82fc | 5680 | |
54a0048b | 5681 | self.unexpected()?; |
1a4d82fc JJ |
5682 | } |
5683 | ||
9cc50fc6 | 5684 | if self.eat_keyword(keywords::Static) { |
1a4d82fc | 5685 | // STATIC ITEM |
7453a54e SL |
5686 | let m = if self.eat_keyword(keywords::Mut) { |
5687 | Mutability::Mutable | |
5688 | } else { | |
5689 | Mutability::Immutable | |
5690 | }; | |
54a0048b | 5691 | let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?; |
1a4d82fc JJ |
5692 | let last_span = self.last_span; |
5693 | let item = self.mk_item(lo, | |
5694 | last_span.hi, | |
5695 | ident, | |
5696 | item_, | |
5697 | visibility, | |
5698 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5699 | return Ok(Some(item)); |
1a4d82fc | 5700 | } |
9cc50fc6 | 5701 | if self.eat_keyword(keywords::Const) { |
b039eaaf SL |
5702 | if self.check_keyword(keywords::Fn) |
5703 | || (self.check_keyword(keywords::Unsafe) | |
5704 | && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) { | |
62682a34 | 5705 | // CONST FUNCTION ITEM |
9cc50fc6 | 5706 | let unsafety = if self.eat_keyword(keywords::Unsafe) { |
b039eaaf SL |
5707 | Unsafety::Unsafe |
5708 | } else { | |
5709 | Unsafety::Normal | |
5710 | }; | |
9cc50fc6 | 5711 | self.bump(); |
62682a34 | 5712 | let (ident, item_, extra_attrs) = |
54a0048b | 5713 | self.parse_item_fn(unsafety, Constness::Const, Abi::Rust)?; |
62682a34 SL |
5714 | let last_span = self.last_span; |
5715 | let item = self.mk_item(lo, | |
5716 | last_span.hi, | |
5717 | ident, | |
5718 | item_, | |
5719 | visibility, | |
5720 | maybe_append(attrs, extra_attrs)); | |
5721 | return Ok(Some(item)); | |
5722 | } | |
5723 | ||
1a4d82fc | 5724 | // CONST ITEM |
9cc50fc6 | 5725 | if self.eat_keyword(keywords::Mut) { |
1a4d82fc | 5726 | let last_span = self.last_span; |
9cc50fc6 | 5727 | self.diagnostic().struct_span_err(last_span, "const globals cannot be mutable") |
a7813a04 | 5728 | .help("did you mean to declare a static?") |
9cc50fc6 | 5729 | .emit(); |
1a4d82fc | 5730 | } |
54a0048b | 5731 | let (ident, item_, extra_attrs) = self.parse_item_const(None)?; |
1a4d82fc JJ |
5732 | let last_span = self.last_span; |
5733 | let item = self.mk_item(lo, | |
5734 | last_span.hi, | |
5735 | ident, | |
5736 | item_, | |
5737 | visibility, | |
5738 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5739 | return Ok(Some(item)); |
1a4d82fc | 5740 | } |
85aaf69f SL |
5741 | if self.check_keyword(keywords::Unsafe) && |
5742 | self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) | |
1a4d82fc JJ |
5743 | { |
5744 | // UNSAFE TRAIT ITEM | |
54a0048b SL |
5745 | self.expect_keyword(keywords::Unsafe)?; |
5746 | self.expect_keyword(keywords::Trait)?; | |
223e47cc | 5747 | let (ident, item_, extra_attrs) = |
54a0048b | 5748 | self.parse_item_trait(ast::Unsafety::Unsafe)?; |
1a4d82fc JJ |
5749 | let last_span = self.last_span; |
5750 | let item = self.mk_item(lo, | |
5751 | last_span.hi, | |
5752 | ident, | |
5753 | item_, | |
5754 | visibility, | |
5755 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5756 | return Ok(Some(item)); |
1a4d82fc | 5757 | } |
85aaf69f SL |
5758 | if self.check_keyword(keywords::Unsafe) && |
5759 | self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) | |
1a4d82fc JJ |
5760 | { |
5761 | // IMPL ITEM | |
54a0048b SL |
5762 | self.expect_keyword(keywords::Unsafe)?; |
5763 | self.expect_keyword(keywords::Impl)?; | |
5764 | let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe)?; | |
1a4d82fc JJ |
5765 | let last_span = self.last_span; |
5766 | let item = self.mk_item(lo, | |
5767 | last_span.hi, | |
5768 | ident, | |
5769 | item_, | |
5770 | visibility, | |
5771 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5772 | return Ok(Some(item)); |
1a4d82fc | 5773 | } |
85aaf69f | 5774 | if self.check_keyword(keywords::Fn) { |
1a4d82fc | 5775 | // FUNCTION ITEM |
9cc50fc6 | 5776 | self.bump(); |
223e47cc | 5777 | let (ident, item_, extra_attrs) = |
54a0048b | 5778 | self.parse_item_fn(Unsafety::Normal, Constness::NotConst, Abi::Rust)?; |
1a4d82fc JJ |
5779 | let last_span = self.last_span; |
5780 | let item = self.mk_item(lo, | |
5781 | last_span.hi, | |
5782 | ident, | |
5783 | item_, | |
5784 | visibility, | |
5785 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5786 | return Ok(Some(item)); |
1a4d82fc | 5787 | } |
85aaf69f SL |
5788 | if self.check_keyword(keywords::Unsafe) |
5789 | && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { | |
970d7e83 | 5790 | // UNSAFE FUNCTION ITEM |
9cc50fc6 SL |
5791 | self.bump(); |
5792 | let abi = if self.eat_keyword(keywords::Extern) { | |
54a0048b | 5793 | self.parse_opt_abi()?.unwrap_or(Abi::C) |
1a4d82fc | 5794 | } else { |
7453a54e | 5795 | Abi::Rust |
1a4d82fc | 5796 | }; |
54a0048b | 5797 | self.expect_keyword(keywords::Fn)?; |
223e47cc | 5798 | let (ident, item_, extra_attrs) = |
54a0048b | 5799 | self.parse_item_fn(Unsafety::Unsafe, Constness::NotConst, abi)?; |
1a4d82fc JJ |
5800 | let last_span = self.last_span; |
5801 | let item = self.mk_item(lo, | |
5802 | last_span.hi, | |
5803 | ident, | |
5804 | item_, | |
5805 | visibility, | |
5806 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5807 | return Ok(Some(item)); |
223e47cc | 5808 | } |
9cc50fc6 | 5809 | if self.eat_keyword(keywords::Mod) { |
223e47cc | 5810 | // MODULE ITEM |
970d7e83 | 5811 | let (ident, item_, extra_attrs) = |
54a0048b | 5812 | self.parse_item_mod(&attrs[..])?; |
1a4d82fc JJ |
5813 | let last_span = self.last_span; |
5814 | let item = self.mk_item(lo, | |
5815 | last_span.hi, | |
5816 | ident, | |
5817 | item_, | |
5818 | visibility, | |
5819 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5820 | return Ok(Some(item)); |
223e47cc | 5821 | } |
9cc50fc6 | 5822 | if self.eat_keyword(keywords::Type) { |
223e47cc | 5823 | // TYPE ITEM |
54a0048b | 5824 | let (ident, item_, extra_attrs) = self.parse_item_type()?; |
1a4d82fc JJ |
5825 | let last_span = self.last_span; |
5826 | let item = self.mk_item(lo, | |
5827 | last_span.hi, | |
5828 | ident, | |
5829 | item_, | |
5830 | visibility, | |
5831 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5832 | return Ok(Some(item)); |
223e47cc | 5833 | } |
9cc50fc6 | 5834 | if self.eat_keyword(keywords::Enum) { |
223e47cc | 5835 | // ENUM ITEM |
54a0048b | 5836 | let (ident, item_, extra_attrs) = self.parse_item_enum()?; |
1a4d82fc JJ |
5837 | let last_span = self.last_span; |
5838 | let item = self.mk_item(lo, | |
5839 | last_span.hi, | |
5840 | ident, | |
5841 | item_, | |
5842 | visibility, | |
5843 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5844 | return Ok(Some(item)); |
223e47cc | 5845 | } |
9cc50fc6 | 5846 | if self.eat_keyword(keywords::Trait) { |
223e47cc | 5847 | // TRAIT ITEM |
1a4d82fc | 5848 | let (ident, item_, extra_attrs) = |
54a0048b | 5849 | self.parse_item_trait(ast::Unsafety::Normal)?; |
1a4d82fc JJ |
5850 | let last_span = self.last_span; |
5851 | let item = self.mk_item(lo, | |
5852 | last_span.hi, | |
5853 | ident, | |
5854 | item_, | |
5855 | visibility, | |
5856 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5857 | return Ok(Some(item)); |
223e47cc | 5858 | } |
9cc50fc6 | 5859 | if self.eat_keyword(keywords::Impl) { |
223e47cc | 5860 | // IMPL ITEM |
54a0048b | 5861 | let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal)?; |
1a4d82fc JJ |
5862 | let last_span = self.last_span; |
5863 | let item = self.mk_item(lo, | |
5864 | last_span.hi, | |
5865 | ident, | |
5866 | item_, | |
5867 | visibility, | |
5868 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5869 | return Ok(Some(item)); |
223e47cc | 5870 | } |
9cc50fc6 | 5871 | if self.eat_keyword(keywords::Struct) { |
223e47cc | 5872 | // STRUCT ITEM |
54a0048b | 5873 | let (ident, item_, extra_attrs) = self.parse_item_struct()?; |
1a4d82fc JJ |
5874 | let last_span = self.last_span; |
5875 | let item = self.mk_item(lo, | |
5876 | last_span.hi, | |
5877 | ident, | |
5878 | item_, | |
5879 | visibility, | |
5880 | maybe_append(attrs, extra_attrs)); | |
9346a6ac | 5881 | return Ok(Some(item)); |
223e47cc | 5882 | } |
92a42be0 | 5883 | self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility) |
970d7e83 LB |
5884 | } |
5885 | ||
c34b1796 | 5886 | /// Parse a foreign item. |
7453a54e | 5887 | fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> { |
54a0048b | 5888 | let attrs = self.parse_outer_attributes()?; |
d9579d0f | 5889 | let lo = self.span.lo; |
a7813a04 | 5890 | let visibility = self.parse_visibility(true)?; |
970d7e83 | 5891 | |
85aaf69f | 5892 | if self.check_keyword(keywords::Static) { |
1a4d82fc | 5893 | // FOREIGN STATIC ITEM |
54a0048b | 5894 | return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?)); |
970d7e83 | 5895 | } |
a7813a04 | 5896 | if self.check_keyword(keywords::Fn) { |
970d7e83 | 5897 | // FOREIGN FUNCTION ITEM |
54a0048b | 5898 | return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?)); |
223e47cc | 5899 | } |
85aaf69f SL |
5900 | |
5901 | // FIXME #5668: this will occur for a macro invocation: | |
54a0048b | 5902 | match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? { |
c34b1796 | 5903 | Some(item) => { |
9346a6ac | 5904 | return Err(self.span_fatal(item.span, "macros cannot expand to foreign items")); |
c34b1796 | 5905 | } |
9346a6ac | 5906 | None => Ok(None) |
c34b1796 | 5907 | } |
970d7e83 LB |
5908 | } |
5909 | ||
1a4d82fc | 5910 | /// This is the fall-through for parsing items. |
970d7e83 | 5911 | fn parse_macro_use_or_failure( |
1a4d82fc JJ |
5912 | &mut self, |
5913 | attrs: Vec<Attribute> , | |
970d7e83 | 5914 | macros_allowed: bool, |
92a42be0 | 5915 | attributes_allowed: bool, |
1a4d82fc JJ |
5916 | lo: BytePos, |
5917 | visibility: Visibility | |
9cc50fc6 | 5918 | ) -> PResult<'a, Option<P<Item>>> { |
1a4d82fc JJ |
5919 | if macros_allowed && !self.token.is_any_keyword() |
5920 | && self.look_ahead(1, |t| *t == token::Not) | |
a7813a04 | 5921 | && (self.look_ahead(2, |t| t.is_ident()) |
1a4d82fc JJ |
5922 | || self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) |
5923 | || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { | |
223e47cc | 5924 | // MACRO INVOCATION ITEM |
223e47cc | 5925 | |
85aaf69f | 5926 | let last_span = self.last_span; |
54a0048b | 5927 | self.complain_if_pub_macro(&visibility, last_span); |
85aaf69f | 5928 | |
92a42be0 SL |
5929 | let mac_lo = self.span.lo; |
5930 | ||
223e47cc | 5931 | // item macro. |
a7813a04 | 5932 | let pth = self.parse_ident_into_path()?; |
54a0048b | 5933 | self.expect(&token::Not)?; |
223e47cc LB |
5934 | |
5935 | // a 'special' identifier (like what `macro_rules!` uses) | |
5936 | // is optional. We should eventually unify invoc syntax | |
5937 | // and remove this. | |
a7813a04 | 5938 | let id = if self.token.is_ident() { |
54a0048b | 5939 | self.parse_ident()? |
223e47cc | 5940 | } else { |
a7813a04 | 5941 | keywords::Invalid.ident() // no special identifier |
223e47cc LB |
5942 | }; |
5943 | // eat a matched-delimiter token tree: | |
54a0048b SL |
5944 | let delim = self.expect_open_delim()?; |
5945 | let tts = self.parse_seq_to_end(&token::CloseDelim(delim), | |
5946 | SeqSep::none(), | |
5947 | |p| p.parse_token_tree())?; | |
223e47cc | 5948 | // single-variant-enum... : |
3157f602 | 5949 | let m = Mac_ { path: pth, tts: tts }; |
1a4d82fc | 5950 | let m: ast::Mac = codemap::Spanned { node: m, |
3157f602 XL |
5951 | span: mk_sp(mac_lo, |
5952 | self.last_span.hi) }; | |
1a4d82fc JJ |
5953 | |
5954 | if delim != token::Brace { | |
9cc50fc6 | 5955 | if !self.eat(&token::Semi) { |
1a4d82fc JJ |
5956 | let last_span = self.last_span; |
5957 | self.span_err(last_span, | |
5958 | "macros that expand to items must either \ | |
5959 | be surrounded with braces or followed by \ | |
5960 | a semicolon"); | |
5961 | } | |
5962 | } | |
5963 | ||
7453a54e | 5964 | let item_ = ItemKind::Mac(m); |
1a4d82fc JJ |
5965 | let last_span = self.last_span; |
5966 | let item = self.mk_item(lo, | |
5967 | last_span.hi, | |
5968 | id, | |
5969 | item_, | |
5970 | visibility, | |
5971 | attrs); | |
9346a6ac | 5972 | return Ok(Some(item)); |
223e47cc LB |
5973 | } |
5974 | ||
5975 | // FAILURE TO PARSE ITEM | |
1a4d82fc | 5976 | match visibility { |
7453a54e | 5977 | Visibility::Inherited => {} |
54a0048b | 5978 | _ => { |
1a4d82fc | 5979 | let last_span = self.last_span; |
9346a6ac | 5980 | return Err(self.span_fatal(last_span, "unmatched visibility `pub`")); |
970d7e83 | 5981 | } |
223e47cc | 5982 | } |
223e47cc | 5983 | |
92a42be0 | 5984 | if !attributes_allowed && !attrs.is_empty() { |
c34b1796 AL |
5985 | self.expected_item_err(&attrs); |
5986 | } | |
9346a6ac | 5987 | Ok(None) |
1a4d82fc JJ |
5988 | } |
5989 | ||
9cc50fc6 | 5990 | pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> { |
54a0048b | 5991 | let attrs = self.parse_outer_attributes()?; |
92a42be0 | 5992 | self.parse_item_(attrs, true, false) |
223e47cc LB |
5993 | } |
5994 | ||
a7813a04 XL |
5995 | fn parse_path_list_items(&mut self) -> PResult<'a, Vec<ast::PathListItem>> { |
5996 | self.parse_unspanned_seq(&token::OpenDelim(token::Brace), | |
5997 | &token::CloseDelim(token::Brace), | |
5998 | SeqSep::trailing_allowed(token::Comma), |this| { | |
5999 | let lo = this.span.lo; | |
6000 | let node = if this.eat_keyword(keywords::SelfValue) { | |
6001 | let rename = this.parse_rename()?; | |
6002 | ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename } | |
6003 | } else { | |
6004 | let ident = this.parse_ident()?; | |
6005 | let rename = this.parse_rename()?; | |
6006 | ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID } | |
6007 | }; | |
6008 | let hi = this.last_span.hi; | |
6009 | Ok(spanned(lo, hi, node)) | |
6010 | }) | |
6011 | } | |
9346a6ac | 6012 | |
a7813a04 XL |
6013 | /// `::{` or `::*` |
6014 | fn is_import_coupler(&mut self) -> bool { | |
6015 | self.check(&token::ModSep) && | |
6016 | self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) || | |
6017 | *t == token::BinOp(token::Star)) | |
6018 | } | |
6019 | ||
6020 | /// Matches ViewPath: | |
6021 | /// MOD_SEP? non_global_path | |
6022 | /// MOD_SEP? non_global_path as IDENT | |
6023 | /// MOD_SEP? non_global_path MOD_SEP STAR | |
6024 | /// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE | |
6025 | /// MOD_SEP? LBRACE item_seq RBRACE | |
9cc50fc6 | 6026 | fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> { |
223e47cc | 6027 | let lo = self.span.lo; |
a7813a04 XL |
6028 | if self.check(&token::OpenDelim(token::Brace)) || self.is_import_coupler() { |
6029 | // `{foo, bar}` or `::{foo, bar}` | |
6030 | let prefix = ast::Path { | |
6031 | global: self.eat(&token::ModSep), | |
6032 | segments: Vec::new(), | |
1a4d82fc | 6033 | span: mk_sp(lo, self.span.hi), |
1a4d82fc | 6034 | }; |
a7813a04 XL |
6035 | let items = self.parse_path_list_items()?; |
6036 | Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items)))) | |
6037 | } else { | |
6038 | let prefix = self.parse_path(PathStyle::Mod)?; | |
6039 | if self.is_import_coupler() { | |
6040 | // `foo::bar::{a, b}` or `foo::bar::*` | |
9cc50fc6 | 6041 | self.bump(); |
a7813a04 | 6042 | if self.check(&token::BinOp(token::Star)) { |
9cc50fc6 | 6043 | self.bump(); |
a7813a04 XL |
6044 | Ok(P(spanned(lo, self.span.hi, ViewPathGlob(prefix)))) |
6045 | } else { | |
6046 | let items = self.parse_path_list_items()?; | |
6047 | Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items)))) | |
223e47cc | 6048 | } |
a7813a04 XL |
6049 | } else { |
6050 | // `foo::bar` or `foo::bar as baz` | |
6051 | let rename = self.parse_rename()?. | |
6052 | unwrap_or(prefix.segments.last().unwrap().identifier); | |
6053 | Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename, prefix)))) | |
223e47cc | 6054 | } |
223e47cc | 6055 | } |
e9174d1e SL |
6056 | } |
6057 | ||
9cc50fc6 SL |
6058 | fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { |
6059 | if self.eat_keyword(keywords::As) { | |
e9174d1e SL |
6060 | self.parse_ident().map(Some) |
6061 | } else { | |
6062 | Ok(None) | |
1a4d82fc | 6063 | } |
970d7e83 LB |
6064 | } |
6065 | ||
1a4d82fc JJ |
6066 | /// Parses a source module as a crate. This is the main |
6067 | /// entry point for the parser. | |
9cc50fc6 | 6068 | pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { |
223e47cc | 6069 | let lo = self.span.lo; |
9346a6ac | 6070 | Ok(ast::Crate { |
54a0048b SL |
6071 | attrs: self.parse_inner_attributes()?, |
6072 | module: self.parse_mod_items(&token::Eof, lo)?, | |
1a4d82fc JJ |
6073 | config: self.cfg.clone(), |
6074 | span: mk_sp(lo, self.span.lo), | |
6075 | exported_macros: Vec::new(), | |
9346a6ac | 6076 | }) |
223e47cc LB |
6077 | } |
6078 | ||
1a4d82fc | 6079 | pub fn parse_optional_str(&mut self) |
9cc50fc6 SL |
6080 | -> Option<(InternedString, |
6081 | ast::StrStyle, | |
6082 | Option<ast::Name>)> { | |
1a4d82fc JJ |
6083 | let ret = match self.token { |
6084 | token::Literal(token::Str_(s), suf) => { | |
7453a54e SL |
6085 | let s = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)); |
6086 | (s, ast::StrStyle::Cooked, suf) | |
1a4d82fc JJ |
6087 | } |
6088 | token::Literal(token::StrRaw(s, n), suf) => { | |
7453a54e SL |
6089 | let s = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)); |
6090 | (s, ast::StrStyle::Raw(n), suf) | |
1a4d82fc | 6091 | } |
9cc50fc6 | 6092 | _ => return None |
1a4d82fc | 6093 | }; |
9cc50fc6 SL |
6094 | self.bump(); |
6095 | Some(ret) | |
1a4d82fc JJ |
6096 | } |
6097 | ||
9cc50fc6 SL |
6098 | pub fn parse_str(&mut self) -> PResult<'a, (InternedString, StrStyle)> { |
6099 | match self.parse_optional_str() { | |
1a4d82fc JJ |
6100 | Some((s, style, suf)) => { |
6101 | let sp = self.last_span; | |
e9174d1e | 6102 | self.expect_no_suffix(sp, "string literal", suf); |
9346a6ac | 6103 | Ok((s, style)) |
970d7e83 | 6104 | } |
9346a6ac | 6105 | _ => Err(self.fatal("expected string literal")) |
223e47cc LB |
6106 | } |
6107 | } | |
6108 | } |