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::*; //resolve bug?
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={:?}",
29 attrs.push(try!(self.parse_attribute(false)));
31 token::DocComment(s) => {
32 let attr = ::attr::mk_sugared_doc_attr(
34 self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)),
38 if attr.node.style != ast::AttrStyle::Outer {
39 return Err(self.fatal("expected outer comment"));
50 /// Matches `attribute = # ! [ meta_item ]`
52 /// If permit_inner is true, then a leading `!` indicates an inner
54 pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
55 debug!("parse_attributes: permit_inner={:?} self.token={:?}",
56 permit_inner, self.token);
57 let (span, value, mut style) = match self.token {
59 let lo = self.span.lo;
62 if permit_inner { self.expected_tokens.push(TokenType::Token(token::Not)); }
63 let style = if self.token == token::Not {
67 self.diagnostic().struct_span_err(span,
68 "an inner attribute is not permitted in \
71 "place inner attribute at the top of \
80 try!(self.expect(&token::OpenDelim(token::Bracket)));
81 let meta_item = try!(self.parse_meta_item());
82 let hi = self.span.hi;
83 try!(self.expect(&token::CloseDelim(token::Bracket)));
85 (mk_sp(lo, hi), meta_item, style)
88 let token_str = self.this_token_to_string();
89 return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
93 if permit_inner && self.token == token::Semi {
95 self.span_warn(span, "this inner attribute syntax is deprecated. \
96 The new syntax is `#![foo]`, with a bang and no semicolon");
97 style = ast::AttrStyle::Inner;
102 node: ast::Attribute_ {
103 id: attr::mk_attr_id(),
106 is_sugared_doc: false
111 /// Parse attributes that appear after the opening of an item. These should
112 /// be preceded by an exclamation mark, but we accept and warn about one
113 /// terminated by a semicolon.
115 /// matches inner_attrs*
116 pub fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
117 let mut attrs: Vec<ast::Attribute> = vec![];
121 // Don't even try to parse if it's not an inner attribute.
122 if !self.look_ahead(1, |t| t == &token::Not) {
126 let attr = try!(self.parse_attribute(true));
127 assert!(attr.node.style == ast::AttrStyle::Inner);
130 token::DocComment(s) => {
131 // we need to get the position of this token before we bump.
132 let Span { lo, hi, .. } = self.span;
133 let str = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s));
134 let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
135 if attr.node.style == ast::AttrStyle::Inner {
148 /// matches meta_item = IDENT
151 pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
152 let nt_meta = match self.token {
153 token::Interpolated(token::NtMeta(ref e)) => {
167 let lo = self.span.lo;
168 let ident = try!(self.parse_ident());
169 let name = self.id_to_interned_str(ident);
173 let lit = try!(self.parse_lit());
174 // FIXME #623 Non-string meta items are not serialized correctly;
175 // just forbid them for now
177 ast::LitStr(..) => {}
181 "non-string literals are not allowed in meta-items");
184 let hi = self.span.hi;
185 Ok(P(spanned(lo, hi, ast::MetaNameValue(name, lit))))
187 token::OpenDelim(token::Paren) => {
188 let inner_items = try!(self.parse_meta_seq());
189 let hi = self.span.hi;
190 Ok(P(spanned(lo, hi, ast::MetaList(name, inner_items))))
193 let hi = self.last_span.hi;
194 Ok(P(spanned(lo, hi, ast::MetaWord(name))))
199 /// matches meta_seq = ( COMMASEP(meta_item) )
200 fn parse_meta_seq(&mut self) -> PResult<'a, Vec<P<ast::MetaItem>>> {
201 self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
202 &token::CloseDelim(token::Paren),
203 seq_sep_trailing_allowed(token::Comma),
204 |p: &mut Parser<'a>| p.parse_meta_item())