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.
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.
13 use codemap
::{spanned, Spanned, mk_sp, Span}
;
14 use parse
::common
::SeqSep
;
17 use parse
::parser
::{Parser, TokenType}
;
21 /// Parse attributes that appear before an item
22 pub fn parse_outer_attributes(&mut self) -> PResult
<'a
, Vec
<ast
::Attribute
>> {
23 let mut attrs
: Vec
<ast
::Attribute
> = Vec
::new();
25 debug
!("parse_outer_attributes: self.token={:?}", self.token
);
28 attrs
.push(self.parse_attribute(false)?
);
30 token
::DocComment(s
) => {
31 let attr
= ::attr
::mk_sugared_doc_attr(
33 self.id_to_interned_str(ast
::Ident
::with_empty_ctxt(s
)),
37 if attr
.node
.style
!= ast
::AttrStyle
::Outer
{
38 let mut err
= self.fatal("expected outer doc comment");
39 err
.note("inner doc comments like this (starting with \
40 `//!` or `/*!`) can only appear before items");
52 /// Matches `attribute = # ! [ meta_item ]`
54 /// If permit_inner is true, then a leading `!` indicates an inner
56 pub fn parse_attribute(&mut self, permit_inner
: bool
) -> PResult
<'a
, ast
::Attribute
> {
57 debug
!("parse_attributes: permit_inner={:?} self.token={:?}",
60 let (span
, value
, mut style
) = match self.token
{
62 let lo
= self.span
.lo
;
66 self.expected_tokens
.push(TokenType
::Token(token
::Not
));
68 let style
= if self.token
== token
::Not
{
73 .struct_span_err(span
,
74 "an inner attribute is not permitted in this context")
75 .help("place inner attribute at the top of the module or \
84 self.expect(&token
::OpenDelim(token
::Bracket
))?
;
85 let meta_item
= self.parse_meta_item()?
;
86 let hi
= self.span
.hi
;
87 self.expect(&token
::CloseDelim(token
::Bracket
))?
;
89 (mk_sp(lo
, hi
), meta_item
, style
)
92 let token_str
= self.this_token_to_string();
93 return Err(self.fatal(&format
!("expected `#`, found `{}`", token_str
)));
97 if permit_inner
&& self.token
== token
::Semi
{
100 "this inner attribute syntax is deprecated. The new syntax is \
101 `#![foo]`, with a bang and no semicolon");
102 style
= ast
::AttrStyle
::Inner
;
107 node
: ast
::Attribute_
{
108 id
: attr
::mk_attr_id(),
111 is_sugared_doc
: false,
116 /// Parse attributes that appear after the opening of an item. These should
117 /// be preceded by an exclamation mark, but we accept and warn about one
118 /// terminated by a semicolon.
120 /// matches inner_attrs*
121 pub fn parse_inner_attributes(&mut self) -> PResult
<'a
, Vec
<ast
::Attribute
>> {
122 let mut attrs
: Vec
<ast
::Attribute
> = vec
![];
126 // Don't even try to parse if it's not an inner attribute.
127 if !self.look_ahead(1, |t
| t
== &token
::Not
) {
131 let attr
= self.parse_attribute(true)?
;
132 assert
!(attr
.node
.style
== ast
::AttrStyle
::Inner
);
135 token
::DocComment(s
) => {
136 // we need to get the position of this token before we bump.
137 let Span { lo, hi, .. }
= self.span
;
138 let str = self.id_to_interned_str(ast
::Ident
::with_empty_ctxt(s
));
139 let attr
= attr
::mk_sugared_doc_attr(attr
::mk_attr_id(), str, lo
, hi
);
140 if attr
.node
.style
== ast
::AttrStyle
::Inner
{
153 /// matches meta_item = IDENT
156 pub fn parse_meta_item(&mut self) -> PResult
<'a
, P
<ast
::MetaItem
>> {
157 let nt_meta
= match self.token
{
158 token
::Interpolated(token
::NtMeta(ref e
)) => Some(e
.clone()),
170 let lo
= self.span
.lo
;
171 let ident
= self.parse_ident()?
;
172 let name
= self.id_to_interned_str(ident
);
176 let lit
= self.parse_lit()?
;
177 // FIXME #623 Non-string meta items are not serialized correctly;
178 // just forbid them for now
180 ast
::LitKind
::Str(..) => {}
182 self.span_err(lit
.span
,
183 "non-string literals are not allowed in meta-items");
186 let hi
= self.span
.hi
;
187 Ok(P(spanned(lo
, hi
, ast
::MetaItemKind
::NameValue(name
, lit
))))
189 token
::OpenDelim(token
::Paren
) => {
190 let inner_items
= self.parse_meta_seq()?
;
191 let hi
= self.span
.hi
;
192 Ok(P(spanned(lo
, hi
, ast
::MetaItemKind
::List(name
, inner_items
))))
195 let hi
= self.last_span
.hi
;
196 Ok(P(spanned(lo
, hi
, ast
::MetaItemKind
::Word(name
))))
201 /// matches meta_seq = ( COMMASEP(meta_item) )
202 fn parse_meta_seq(&mut self) -> PResult
<'a
, Vec
<P
<ast
::MetaItem
>>> {
203 self.parse_unspanned_seq(&token
::OpenDelim(token
::Paren
),
204 &token
::CloseDelim(token
::Paren
),
205 SeqSep
::trailing_allowed(token
::Comma
),
206 |p
: &mut Parser
<'a
>| p
.parse_meta_item())