]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/parse/attr.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / libsyntax / parse / attr.rs
CommitLineData
223e47cc
LB
1// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
1a4d82fc 11use attr;
223e47cc 12use ast;
cc61c64b 13use codemap::respan;
94b46f34 14use parse::{SeqSep, PResult};
cc61c64b
XL
15use parse::token::{self, Nonterminal};
16use parse::parser::{Parser, TokenType, PathStyle};
17use tokenstream::TokenStream;
223e47cc 18
5bcae85e
SL
19#[derive(PartialEq, Eq, Debug)]
20enum InnerAttributeParsePolicy<'a> {
21 Permitted,
22 NotPermitted { reason: &'a str },
23}
24
25const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &'static str = "an inner attribute is not \
26 permitted in this context";
27
92a42be0 28impl<'a> Parser<'a> {
1a4d82fc 29 /// Parse attributes that appear before an item
94b46f34 30 crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
1a4d82fc 31 let mut attrs: Vec<ast::Attribute> = Vec::new();
5bcae85e 32 let mut just_parsed_doc_comment = false;
223e47cc 33 loop {
7453a54e 34 debug!("parse_outer_attributes: self.token={:?}", self.token);
1a4d82fc 35 match self.token {
7453a54e 36 token::Pound => {
5bcae85e
SL
37 let inner_error_reason = if just_parsed_doc_comment {
38 "an inner attribute is not permitted following an outer doc comment"
39 } else if !attrs.is_empty() {
40 "an inner attribute is not permitted following an outer attribute"
41 } else {
42 DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
43 };
44 let inner_parse_policy =
45 InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason };
46 attrs.push(self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?);
47 just_parsed_doc_comment = false;
7453a54e
SL
48 }
49 token::DocComment(s) => {
cc61c64b 50 let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.span);
476ff2be 51 if attr.style != ast::AttrStyle::Outer {
a7813a04
XL
52 let mut err = self.fatal("expected outer doc comment");
53 err.note("inner doc comments like this (starting with \
54 `//!` or `/*!`) can only appear before items");
55 return Err(err);
7453a54e
SL
56 }
57 attrs.push(attr);
58 self.bump();
5bcae85e 59 just_parsed_doc_comment = true;
223e47cc 60 }
7453a54e 61 _ => break,
223e47cc
LB
62 }
63 }
7cac9316 64 Ok(attrs)
223e47cc
LB
65 }
66
1a4d82fc
JJ
67 /// Matches `attribute = # ! [ meta_item ]`
68 ///
69 /// If permit_inner is true, then a leading `!` indicates an inner
70 /// attribute
9cc50fc6 71 pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
5bcae85e 72 debug!("parse_attribute: permit_inner={:?} self.token={:?}",
7453a54e
SL
73 permit_inner,
74 self.token);
5bcae85e
SL
75 let inner_parse_policy = if permit_inner {
76 InnerAttributeParsePolicy::Permitted
77 } else {
78 InnerAttributeParsePolicy::NotPermitted
79 { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG }
80 };
81 self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
82 }
83
84 /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy`
85 /// that prescribes how to handle inner attributes.
86 fn parse_attribute_with_inner_parse_policy(&mut self,
87 inner_parse_policy: InnerAttributeParsePolicy)
88 -> PResult<'a, ast::Attribute> {
89 debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
90 inner_parse_policy,
91 self.token);
0531ce1d 92 let (span, path, tokens, style) = match self.token {
1a4d82fc 93 token::Pound => {
cc61c64b 94 let lo = self.span;
9cc50fc6 95 self.bump();
1a4d82fc 96
5bcae85e 97 if inner_parse_policy == InnerAttributeParsePolicy::Permitted {
7453a54e
SL
98 self.expected_tokens.push(TokenType::Token(token::Not));
99 }
85aaf69f 100 let style = if self.token == token::Not {
9cc50fc6 101 self.bump();
5bcae85e
SL
102 if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy
103 {
1a4d82fc 104 let span = self.span;
7453a54e 105 self.diagnostic()
5bcae85e 106 .struct_span_err(span, reason)
abe05a73
XL
107 .note("inner attributes, like `#![no_std]`, annotate the item \
108 enclosing them, and are usually found at the beginning of \
109 source files. Outer attributes, like `#[test]`, annotate the \
110 item following them.")
7453a54e 111 .emit()
1a4d82fc 112 }
b039eaaf 113 ast::AttrStyle::Inner
1a4d82fc 114 } else {
b039eaaf 115 ast::AttrStyle::Outer
1a4d82fc
JJ
116 };
117
54a0048b 118 self.expect(&token::OpenDelim(token::Bracket))?;
cc61c64b 119 let (path, tokens) = self.parse_path_and_tokens()?;
54a0048b 120 self.expect(&token::CloseDelim(token::Bracket))?;
cc61c64b 121 let hi = self.prev_span;
1a4d82fc 122
cc61c64b 123 (lo.to(hi), path, tokens, style)
1a4d82fc
JJ
124 }
125 _ => {
126 let token_str = self.this_token_to_string();
92a42be0 127 return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
1a4d82fc
JJ
128 }
129 };
130
476ff2be
SL
131 Ok(ast::Attribute {
132 id: attr::mk_attr_id(),
3b2f2976
XL
133 style,
134 path,
135 tokens,
476ff2be 136 is_sugared_doc: false,
3b2f2976 137 span,
92a42be0 138 })
223e47cc
LB
139 }
140
94b46f34 141 crate fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
cc61c64b 142 let meta = match self.token {
041b39d2 143 token::Interpolated(ref nt) => match nt.0 {
cc61c64b
XL
144 Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
145 _ => None,
146 },
147 _ => None,
148 };
149 Ok(if let Some(meta) = meta {
150 self.bump();
83c7162d 151 (meta.ident, meta.node.tokens(meta.span))
cc61c64b
XL
152 } else {
153 (self.parse_path(PathStyle::Mod)?, self.parse_tokens())
154 })
155 }
156
1a4d82fc
JJ
157 /// Parse attributes that appear after the opening of an item. These should
158 /// be preceded by an exclamation mark, but we accept and warn about one
c34b1796 159 /// terminated by a semicolon.
1a4d82fc 160
c34b1796 161 /// matches inner_attrs*
94b46f34 162 crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
c34b1796 163 let mut attrs: Vec<ast::Attribute> = vec![];
223e47cc 164 loop {
c34b1796 165 match self.token {
1a4d82fc 166 token::Pound => {
c34b1796
AL
167 // Don't even try to parse if it's not an inner attribute.
168 if !self.look_ahead(1, |t| t == &token::Not) {
169 break;
170 }
171
54a0048b 172 let attr = self.parse_attribute(true)?;
7cac9316 173 assert_eq!(attr.style, ast::AttrStyle::Inner);
c34b1796 174 attrs.push(attr);
223e47cc 175 }
1a4d82fc
JJ
176 token::DocComment(s) => {
177 // we need to get the position of this token before we bump.
cc61c64b 178 let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, self.span);
476ff2be 179 if attr.style == ast::AttrStyle::Inner {
c34b1796 180 attrs.push(attr);
9cc50fc6 181 self.bump();
c34b1796
AL
182 } else {
183 break;
184 }
223e47cc 185 }
7453a54e 186 _ => break,
223e47cc
LB
187 }
188 }
92a42be0 189 Ok(attrs)
223e47cc
LB
190 }
191
9e0c209e
SL
192 fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
193 let lit = self.parse_lit()?;
194 debug!("Checking if {:?} is unusuffixed.", lit);
195
196 if !lit.node.is_unsuffixed() {
197 let msg = "suffixed literals are not allowed in attributes";
198 self.diagnostic().struct_span_err(lit.span, msg)
199 .help("instead of using a suffixed literal \
200 (1u8, 1.0f32, etc.), use an unsuffixed version \
201 (1, 1.0, etc.).")
202 .emit()
203 }
204
205 Ok(lit)
206 }
207
208 /// Per RFC#1559, matches the following grammar:
209 ///
210 /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
211 /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
476ff2be 212 pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
1a4d82fc 213 let nt_meta = match self.token {
041b39d2 214 token::Interpolated(ref nt) => match nt.0 {
c30ab7b3
SL
215 token::NtMeta(ref e) => Some(e.clone()),
216 _ => None,
217 },
7453a54e 218 _ => None,
1a4d82fc
JJ
219 };
220
3157f602
XL
221 if let Some(meta) = nt_meta {
222 self.bump();
223 return Ok(meta);
1a4d82fc
JJ
224 }
225
cc61c64b 226 let lo = self.span;
83c7162d 227 let ident = self.parse_path(PathStyle::Mod)?;
cc61c64b 228 let node = self.parse_meta_item_kind()?;
83c7162d
XL
229 let span = lo.to(self.prev_span);
230 Ok(ast::MetaItem { ident, node, span })
cc61c64b
XL
231 }
232
94b46f34 233 crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
cc61c64b 234 Ok(if self.eat(&token::Eq) {
476ff2be 235 ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?)
3b2f2976 236 } else if self.eat(&token::OpenDelim(token::Paren)) {
476ff2be
SL
237 ast::MetaItemKind::List(self.parse_meta_seq()?)
238 } else {
239 ast::MetaItemKind::Word
cc61c64b 240 })
223e47cc
LB
241 }
242
9e0c209e
SL
243 /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
244 fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
cc61c64b 245 let lo = self.span;
9e0c209e
SL
246
247 match self.parse_unsuffixed_lit() {
248 Ok(lit) => {
cc61c64b 249 return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::Literal(lit)))
9e0c209e
SL
250 }
251 Err(ref mut err) => self.diagnostic().cancel(err)
252 }
253
254 match self.parse_meta_item() {
255 Ok(mi) => {
cc61c64b 256 return Ok(respan(lo.to(self.prev_span), ast::NestedMetaItemKind::MetaItem(mi)))
9e0c209e
SL
257 }
258 Err(ref mut err) => self.diagnostic().cancel(err)
259 }
260
261 let found = self.this_token_to_string();
262 let msg = format!("expected unsuffixed literal or identifier, found {}", found);
cc61c64b 263 Err(self.diagnostic().struct_span_err(lo, &msg))
9e0c209e
SL
264 }
265
266 /// matches meta_seq = ( COMMASEP(meta_item_inner) )
267 fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
3b2f2976
XL
268 self.parse_seq_to_end(&token::CloseDelim(token::Paren),
269 SeqSep::trailing_allowed(token::Comma),
270 |p: &mut Parser<'a>| p.parse_meta_item_inner())
223e47cc
LB
271 }
272}