attr.rs 6.7 KB
Newer Older
P
Patrick Walton 已提交
1 2 3
use either::{Either, Left, Right};
use ast_util::spanned;
use common::*; //resolve bug?
4 5

export attr_or_ext;
6
export parser_attr;
7 8 9

// A type to distingush between the parsing of item attributes or syntax
// extensions, which both begin with token.POUND
B
Brian Anderson 已提交
10
type attr_or_ext = Option<Either<~[ast::attribute], @ast::expr>>;
11

12 13 14 15 16
trait parser_attr {
    fn parse_outer_attrs_or_ext(first_item_attrs: ~[ast::attribute])
        -> attr_or_ext;
    fn parse_outer_attributes() -> ~[ast::attribute];
    fn parse_attribute(style: ast::attr_style) -> ast::attribute;
17
    fn parse_attribute_naked(style: ast::attr_style, lo: CharPos) ->
18 19 20
        ast::attribute;
    fn parse_inner_attrs_and_next() ->
        {inner: ~[ast::attribute], next: ~[ast::attribute]};
21 22 23
    fn parse_meta_item() -> @ast::meta_item;
    fn parse_meta_seq() -> ~[@ast::meta_item];
    fn parse_optional_meta() -> ~[@ast::meta_item];
24 25
}

26
impl Parser: parser_attr {
27

28
    fn parse_outer_attrs_or_ext(first_item_attrs: ~[ast::attribute])
29 30 31
        -> attr_or_ext
    {
        let expect_item_next = vec::is_not_empty(first_item_attrs);
32
        match self.token {
B
Brian Anderson 已提交
33
          token::POUND => {
34 35 36 37 38
            let lo = self.span.lo;
            if self.look_ahead(1u) == token::LBRACKET {
                self.bump();
                let first_attr =
                    self.parse_attribute_naked(ast::attr_outer, lo);
B
Brian Anderson 已提交
39
                return Some(Left(vec::append(~[first_attr],
E
Eric Holk 已提交
40
                                          self.parse_outer_attributes())));
41 42
            } else if !(self.look_ahead(1u) == token::LT
                        || self.look_ahead(1u) == token::LBRACKET
P
Paul Stansifer 已提交
43
                        || self.look_ahead(1u) == token::POUND
44 45
                        || expect_item_next) {
                self.bump();
B
Brian Anderson 已提交
46 47
                return Some(Right(self.parse_syntax_ext_naked(lo)));
            } else { return None; }
48
        }
B
Brian Anderson 已提交
49
        token::DOC_COMMENT(_) => {
B
Brian Anderson 已提交
50
          return Some(Left(self.parse_outer_attributes()));
51
        }
B
Brian Anderson 已提交
52
        _ => return None
53
      }
54
    }
55

56
    // Parse attributes that appear before an item
57 58
    fn parse_outer_attributes() -> ~[ast::attribute] {
        let mut attrs: ~[ast::attribute] = ~[];
59
        loop {
60
            match copy self.token {
B
Brian Anderson 已提交
61
              token::POUND => {
62 63 64
                if self.look_ahead(1u) != token::LBRACKET {
                    break;
                }
65
                attrs += ~[self.parse_attribute(ast::attr_outer)];
66
              }
B
Brian Anderson 已提交
67
              token::DOC_COMMENT(s) => {
68
                let attr = ::attr::mk_sugared_doc_attr(
P
Paul Stansifer 已提交
69
                        *self.id_to_str(s), self.span.lo, self.span.hi);
70
                if attr.node.style != ast::attr_outer {
71
                  self.fatal(~"expected outer comment");
72
                }
73
                attrs += ~[attr];
74 75
                self.bump();
              }
B
Brian Anderson 已提交
76
              _ => break
77
            }
78
        }
B
Brian Anderson 已提交
79
        return attrs;
80 81
    }

82 83 84
    fn parse_attribute(style: ast::attr_style) -> ast::attribute {
        let lo = self.span.lo;
        self.expect(token::POUND);
B
Brian Anderson 已提交
85
        return self.parse_attribute_naked(style, lo);
86
    }
87

88
    fn parse_attribute_naked(style: ast::attr_style, lo: CharPos) ->
89 90 91 92 93
        ast::attribute {
        self.expect(token::LBRACKET);
        let meta_item = self.parse_meta_item();
        self.expect(token::RBRACKET);
        let mut hi = self.span.hi;
94
        return spanned(lo, hi, {style: style, value: *meta_item,
95
                             is_sugared_doc: false});
96
    }
97

98 99 100 101 102 103 104
    // 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() ->
105 106 107
        {inner: ~[ast::attribute], next: ~[ast::attribute]} {
        let mut inner_attrs: ~[ast::attribute] = ~[];
        let mut next_outer_attrs: ~[ast::attribute] = ~[];
108
        loop {
109
            match copy self.token {
B
Brian Anderson 已提交
110
              token::POUND => {
111 112 113 114 115 116 117
                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();
118
                    inner_attrs += ~[attr];
119 120 121 122 123 124
                } else {
                    // It's not really an inner attribute
                    let outer_attr =
                        spanned(attr.span.lo, attr.span.hi,
                            {style: ast::attr_outer, value: attr.node.value,
                             is_sugared_doc: false});
125
                    next_outer_attrs += ~[outer_attr];
126 127 128
                    break;
                }
              }
B
Brian Anderson 已提交
129
              token::DOC_COMMENT(s) => {
130
                let attr = ::attr::mk_sugared_doc_attr(
P
Paul Stansifer 已提交
131
                        *self.id_to_str(s), self.span.lo, self.span.hi);
132
                self.bump();
133
                if attr.node.style == ast::attr_inner {
134
                  inner_attrs += ~[attr];
135
                } else {
136
                  next_outer_attrs += ~[attr];
137 138 139
                  break;
                }
              }
B
Brian Anderson 已提交
140
              _ => break
141
            }
142
        }
B
Brian Anderson 已提交
143
        return {inner: inner_attrs, next: next_outer_attrs};
144 145
    }

146
    fn parse_meta_item() -> @ast::meta_item {
147
        let lo = self.span.lo;
P
Paul Stansifer 已提交
148
        let name = *self.id_to_str(self.parse_ident());
149
        match self.token {
B
Brian Anderson 已提交
150
          token::EQ => {
151 152 153
            self.bump();
            let lit = self.parse_lit();
            let mut hi = self.span.hi;
154
            return @spanned(lo, hi, ast::meta_name_value(name, lit));
155
          }
B
Brian Anderson 已提交
156
          token::LPAREN => {
157 158
            let inner_items = self.parse_meta_seq();
            let mut hi = self.span.hi;
159
            return @spanned(lo, hi, ast::meta_list(name, inner_items));
160
          }
B
Brian Anderson 已提交
161
          _ => {
162
            let mut hi = self.span.hi;
163
            return @spanned(lo, hi, ast::meta_word(name));
164
          }
165 166 167
        }
    }

168
    fn parse_meta_seq() -> ~[@ast::meta_item] {
B
Brian Anderson 已提交
169
        return self.parse_seq(token::LPAREN, token::RPAREN,
170
                           seq_sep_trailing_disallowed(token::COMMA),
B
Brian Anderson 已提交
171
                           |p| p.parse_meta_item()).node;
172 173
    }

174
    fn parse_optional_meta() -> ~[@ast::meta_item] {
175
        match self.token {
B
Brian Anderson 已提交
176 177 178
          token::LPAREN => return self.parse_meta_seq(),
          _ => return ~[]
        }
179
    }
180 181
}

182 183 184 185 186 187 188 189 190
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//