attr.rs 6.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11 12
use core::prelude::*;

13
use ast;
P
Patrick Walton 已提交
14
use ast_util::spanned;
15
use codemap::BytePos;
16
use parse::common::*; //resolve bug?
17 18 19
use parse::token;

use core::either::{Either, Left, Right};
20

21
export parser_attr;
22

23 24 25
trait parser_attr {
    fn parse_outer_attributes() -> ~[ast::attribute];
    fn parse_attribute(style: ast::attr_style) -> ast::attribute;
26
    fn parse_attribute_naked(style: ast::attr_style, lo: BytePos) ->
27 28 29
        ast::attribute;
    fn parse_inner_attrs_and_next() ->
        {inner: ~[ast::attribute], next: ~[ast::attribute]};
30 31 32
    fn parse_meta_item() -> @ast::meta_item;
    fn parse_meta_seq() -> ~[@ast::meta_item];
    fn parse_optional_meta() -> ~[@ast::meta_item];
33 34
}

35
impl Parser: parser_attr {
36 37

    // Parse attributes that appear before an item
38 39
    fn parse_outer_attributes() -> ~[ast::attribute] {
        let mut attrs: ~[ast::attribute] = ~[];
40
        loop {
41
            match copy self.token {
B
Brian Anderson 已提交
42
              token::POUND => {
43 44 45
                if self.look_ahead(1u) != token::LBRACKET {
                    break;
                }
46
                attrs += ~[self.parse_attribute(ast::attr_outer)];
47
              }
B
Brian Anderson 已提交
48
              token::DOC_COMMENT(s) => {
49
                let attr = ::attr::mk_sugared_doc_attr(
P
Paul Stansifer 已提交
50
                        *self.id_to_str(s), self.span.lo, self.span.hi);
51
                if attr.node.style != ast::attr_outer {
52
                  self.fatal(~"expected outer comment");
53
                }
54
                attrs += ~[attr];
55 56
                self.bump();
              }
B
Brian Anderson 已提交
57
              _ => break
58
            }
59
        }
B
Brian Anderson 已提交
60
        return attrs;
61 62
    }

63 64 65
    fn parse_attribute(style: ast::attr_style) -> ast::attribute {
        let lo = self.span.lo;
        self.expect(token::POUND);
B
Brian Anderson 已提交
66
        return self.parse_attribute_naked(style, lo);
67
    }
68

69
    fn parse_attribute_naked(style: ast::attr_style, lo: BytePos) ->
70 71 72 73 74
        ast::attribute {
        self.expect(token::LBRACKET);
        let meta_item = self.parse_meta_item();
        self.expect(token::RBRACKET);
        let mut hi = self.span.hi;
75 76 77
        return spanned(lo, hi, ast::attribute_ { style: style,
                                                 value: *meta_item,
                                                 is_sugared_doc: false });
78
    }
79

80 81 82 83 84 85 86
    // Parse attributes that appear after the opening of an item, each
    // terminated by a semicolon. In addition to a vector of inner attributes,
    // this function also returns a vector that may contain the first outer
    // attribute of the next item (since we can't know whether the attribute
    // is an inner attribute of the containing item or an outer attribute of
    // the first contained item until we see the semi).
    fn parse_inner_attrs_and_next() ->
87 88 89
        {inner: ~[ast::attribute], next: ~[ast::attribute]} {
        let mut inner_attrs: ~[ast::attribute] = ~[];
        let mut next_outer_attrs: ~[ast::attribute] = ~[];
90
        loop {
91
            match copy self.token {
B
Brian Anderson 已提交
92
              token::POUND => {
93 94 95 96 97 98 99
                if self.look_ahead(1u) != token::LBRACKET {
                    // This is an extension
                    break;
                }
                let attr = self.parse_attribute(ast::attr_inner);
                if self.token == token::SEMI {
                    self.bump();
100
                    inner_attrs += ~[attr];
101 102 103 104
                } else {
                    // It's not really an inner attribute
                    let outer_attr =
                        spanned(attr.span.lo, attr.span.hi,
105 106 107
                            ast::attribute_ { style: ast::attr_outer,
                                              value: attr.node.value,
                                              is_sugared_doc: false });
108
                    next_outer_attrs += ~[outer_attr];
109 110 111
                    break;
                }
              }
B
Brian Anderson 已提交
112
              token::DOC_COMMENT(s) => {
113
                let attr = ::attr::mk_sugared_doc_attr(
P
Paul Stansifer 已提交
114
                        *self.id_to_str(s), self.span.lo, self.span.hi);
115
                self.bump();
116
                if attr.node.style == ast::attr_inner {
117
                  inner_attrs += ~[attr];
118
                } else {
119
                  next_outer_attrs += ~[attr];
120 121 122
                  break;
                }
              }
B
Brian Anderson 已提交
123
              _ => break
124
            }
125
        }
B
Brian Anderson 已提交
126
        return {inner: inner_attrs, next: next_outer_attrs};
127 128
    }

129
    fn parse_meta_item() -> @ast::meta_item {
130
        let lo = self.span.lo;
P
Paul Stansifer 已提交
131
        let name = *self.id_to_str(self.parse_ident());
132
        match self.token {
B
Brian Anderson 已提交
133
          token::EQ => {
134 135 136
            self.bump();
            let lit = self.parse_lit();
            let mut hi = self.span.hi;
137
            return @spanned(lo, hi, ast::meta_name_value(name, lit));
138
          }
B
Brian Anderson 已提交
139
          token::LPAREN => {
140 141
            let inner_items = self.parse_meta_seq();
            let mut hi = self.span.hi;
142
            return @spanned(lo, hi, ast::meta_list(name, inner_items));
143
          }
B
Brian Anderson 已提交
144
          _ => {
145
            let mut hi = self.span.hi;
146
            return @spanned(lo, hi, ast::meta_word(name));
147
          }
148 149 150
        }
    }

151
    fn parse_meta_seq() -> ~[@ast::meta_item] {
B
Brian Anderson 已提交
152
        return self.parse_seq(token::LPAREN, token::RPAREN,
153
                           seq_sep_trailing_disallowed(token::COMMA),
B
Brian Anderson 已提交
154
                           |p| p.parse_meta_item()).node;
155 156
    }

157
    fn parse_optional_meta() -> ~[@ast::meta_item] {
158
        match self.token {
B
Brian Anderson 已提交
159 160 161
          token::LPAREN => return self.parse_meta_seq(),
          _ => return ~[]
        }
162
    }
163 164
}

165 166 167 168 169 170 171 172 173
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//