about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-08-14 14:22:52 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-08-14 14:24:00 -0700
commit138dc3048af36f0a20f857542c357fe8df563013 (patch)
tree6066f6da929d6223ae4bec956a191c681bd3a7ba /src/libsyntax/parse
parent350668579a4f3037fa4314fa03bcb97461896d4a (diff)
downloadrust-138dc3048af36f0a20f857542c357fe8df563013.tar.gz
rust-138dc3048af36f0a20f857542c357fe8df563013.zip
libsyntax: Parse "extern mod foo;"
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs137
1 files changed, 100 insertions, 37 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ae899a91bfa..dd6e9f85312 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -111,6 +111,12 @@ enum item_or_view_item {
     iovi_view_item(@view_item)
 }
 
+enum view_item_parse_mode {
+    VIEW_ITEMS_AND_ITEMS_ALLOWED,
+    VIEW_ITEMS_ALLOWED,
+    IMPORTS_AND_ITEMS_ALLOWED
+}
+
 /* The expr situation is not as complex as I thought it would be.
 The important thing is to make sure that lookahead doesn't balk
 at INTERPOLATED tokens */
@@ -2054,7 +2060,7 @@ class parser {
 
             let item_attrs = vec::append(first_item_attrs, item_attrs);
 
-            match self.parse_item_or_view_item(item_attrs) {
+            match self.parse_item_or_view_item(item_attrs, true) {
               iovi_item(i) => {
                 let mut hi = i.span.hi;
                 let decl = @spanned(lo, hi, decl_item(i));
@@ -2141,8 +2147,17 @@ class parser {
                          +first_item_attrs: ~[attribute]) -> blk {
         let mut stmts = ~[];
         let mut expr = none;
-        let {attrs_remaining, view_items} =
-            self.parse_view(first_item_attrs, true);
+
+        let {attrs_remaining, view_items, items: items} =
+            self.parse_items_and_view_items(first_item_attrs,
+                                            IMPORTS_AND_ITEMS_ALLOWED);
+
+        for items.each |item| {
+            let decl = @spanned(item.span.lo, item.span.hi, decl_item(item));
+            push(stmts, @spanned(item.span.lo, item.span.hi,
+                                 stmt_decl(decl, self.get_id())));
+        }
+
         let mut initial_attrs = attrs_remaining;
 
         if self.token == token::RBRACE && !vec::is_empty(initial_attrs) {
@@ -2709,9 +2724,11 @@ class parser {
     fn parse_mod_items(term: token::token,
                        +first_item_attrs: ~[attribute]) -> _mod {
         // Shouldn't be any view items since we've already parsed an item attr
-        let {attrs_remaining, view_items} =
-            self.parse_view(first_item_attrs, false);
-        let mut items: ~[@item] = ~[];
+        let {attrs_remaining, view_items, items: starting_items} =
+            self.parse_items_and_view_items(first_item_attrs,
+                                            VIEW_ITEMS_AND_ITEMS_ALLOWED);
+        let mut items: ~[@item] = move starting_items;
+
         let mut first = true;
         while self.token != term {
             let mut attrs = self.parse_outer_attributes();
@@ -2721,7 +2738,7 @@ class parser {
             }
             debug!("parse_mod_items: parse_item_or_view_item(attrs=%?)",
                    attrs);
-            match self.parse_item_or_view_item(attrs) {
+            match self.parse_item_or_view_item(attrs, true) {
               iovi_item(item) => vec::push(items, item),
               iovi_view_item(view_item) => {
                 self.span_fatal(view_item.span, ~"view items must be \
@@ -2797,8 +2814,10 @@ class parser {
     fn parse_foreign_mod_items(+first_item_attrs: ~[attribute]) ->
         foreign_mod {
         // Shouldn't be any view items since we've already parsed an item attr
-        let {attrs_remaining, view_items} =
-            self.parse_view(first_item_attrs, false);
+        let {attrs_remaining, view_items, items: _} =
+            self.parse_items_and_view_items(first_item_attrs,
+                                            VIEW_ITEMS_ALLOWED);
+
         let mut items: ~[@foreign_item] = ~[];
         let mut initial_attrs = attrs_remaining;
         while self.token != token::RBRACE {
@@ -2813,7 +2832,8 @@ class parser {
 
     fn parse_item_foreign_mod(lo: uint,
                               visibility: visibility,
-                              attrs: ~[attribute])
+                              attrs: ~[attribute],
+                              items_allowed: bool)
                            -> item_or_view_item {
         if self.is_keyword(~"mod") {
             self.expect_keyword(~"mod");
@@ -2823,7 +2843,7 @@ class parser {
         let ident = self.parse_ident();
 
         // extern mod { ... }
-        if self.eat(token::LBRACE) {
+        if items_allowed && self.eat(token::LBRACE) {
             let extra_attrs = self.parse_inner_attrs_and_next();
             let m = self.parse_foreign_mod_items(extra_attrs.next);
             self.expect(token::RBRACE);
@@ -2836,6 +2856,7 @@ class parser {
 
         // extern mod foo;
         let metadata = self.parse_optional_meta();
+        self.expect(token::SEMI);
         return iovi_view_item(@{
             node: view_item_use(ident, metadata, self.get_id()),
             attrs: attrs,
@@ -3033,7 +3054,8 @@ class parser {
         }
     }
 
-    fn parse_item_or_view_item(+attrs: ~[attribute]) -> item_or_view_item {
+    fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool)
+                            -> item_or_view_item {
         maybe_whole!{iovi self,nt_item};
         let lo = self.span.lo;
 
@@ -3046,25 +3068,26 @@ class parser {
             visibility = inherited;
         }
 
-        if self.eat_keyword(~"const") {
+        if items_allowed && self.eat_keyword(~"const") {
             let (ident, item_, extra_attrs) = self.parse_item_const();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.is_keyword(~"fn") &&
+        } else if items_allowed &&
+            self.is_keyword(~"fn") &&
             !self.fn_expr_lookahead(self.look_ahead(1u)) {
             self.bump();
             let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn);
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"pure") {
+        } else if items_allowed && self.eat_keyword(~"pure") {
             self.expect_keyword(~"fn");
             let (ident, item_, extra_attrs) = self.parse_item_fn(pure_fn);
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.is_keyword(~"unsafe")
+        } else if items_allowed && self.is_keyword(~"unsafe")
             && self.look_ahead(1u) != token::LBRACE {
             self.bump();
             self.expect_keyword(~"fn");
@@ -3073,8 +3096,7 @@ class parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         } else if self.eat_keyword(~"extern") {
-            // XXX: "extern mod foo;" syntax as a "use" replacement.
-            if self.eat_keyword(~"fn") {
+            if items_allowed && self.eat_keyword(~"fn") {
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(extern_fn);
                 return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
@@ -3082,45 +3104,49 @@ class parser {
                                               maybe_append(attrs,
                                                            extra_attrs)));
             }
-            return self.parse_item_foreign_mod(lo, visibility, attrs);
-        } else if self.eat_keyword(~"mod") || self.eat_keyword(~"module") {
+            return self.parse_item_foreign_mod(lo, visibility, attrs,
+                                               items_allowed);
+        } else if items_allowed && (self.eat_keyword(~"mod") ||
+                                    self.eat_keyword(~"module")) {
             let (ident, item_, extra_attrs) = self.parse_item_mod();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"type") {
+        } else if items_allowed && self.eat_keyword(~"type") {
             let (ident, item_, extra_attrs) = self.parse_item_type();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"enum") {
+        } else if items_allowed && self.eat_keyword(~"enum") {
             let (ident, item_, extra_attrs) = self.parse_item_enum();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"iface") {
+        } else if items_allowed && self.eat_keyword(~"iface") {
             self.warn(~"`iface` is deprecated; use `trait`");
             let (ident, item_, extra_attrs) = self.parse_item_trait();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"trait") {
+        } else if items_allowed && self.eat_keyword(~"trait") {
             let (ident, item_, extra_attrs) = self.parse_item_trait();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"impl") {
+        } else if items_allowed && self.eat_keyword(~"impl") {
             let (ident, item_, extra_attrs) = self.parse_item_impl();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
-        } else if self.eat_keyword(~"class") || self.eat_keyword(~"struct") {
+        } else if items_allowed &&
+                (self.eat_keyword(~"class") || self.eat_keyword(~"struct")) {
             let (ident, item_, extra_attrs) = self.parse_item_class();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         } else if self.eat_keyword(~"use") {
             let view_item = self.parse_use();
+            self.expect(token::SEMI);
             return iovi_view_item(@{
                 node: view_item,
                 attrs: attrs,
@@ -3129,6 +3155,7 @@ class parser {
             });
         } else if self.eat_keyword(~"import") {
             let view_paths = self.parse_view_paths();
+            self.expect(token::SEMI);
             return iovi_view_item(@{
                 node: view_item_import(view_paths),
                 attrs: attrs,
@@ -3137,15 +3164,16 @@ class parser {
             });
         } else if self.eat_keyword(~"export") {
             let view_paths = self.parse_view_paths();
+            self.expect(token::SEMI);
             return iovi_view_item(@{
                 node: view_item_export(view_paths),
                 attrs: attrs,
                 vis: visibility,
                 span: mk_sp(lo, self.last_span.hi)
             });
-        } else if !self.is_any_keyword(copy self.token)
+        } else if items_allowed && (!self.is_any_keyword(copy self.token)
                 && self.look_ahead(1) == token::NOT
-                && is_plain_ident(self.look_ahead(2)) {
+                && is_plain_ident(self.look_ahead(2))) {
             // item macro.
             let pth = self.parse_path_without_tps();
             self.expect(token::NOT);
@@ -3173,7 +3201,7 @@ class parser {
     }
 
     fn parse_item(+attrs: ~[attribute]) -> option<@ast::item> {
-        match self.parse_item_or_view_item(attrs) {
+        match self.parse_item_or_view_item(attrs, true) {
             iovi_none =>
                 none,
             iovi_view_item(_) =>
@@ -3296,18 +3324,53 @@ class parser {
           vis: vis, span: mk_sp(lo, self.last_span.hi)}
     }
 
-    fn parse_view(+first_item_attrs: ~[attribute],
-                  only_imports: bool) -> {attrs_remaining: ~[attribute],
-                                          view_items: ~[@view_item]} {
+    fn parse_items_and_view_items(+first_item_attrs: ~[attribute],
+                                  mode: view_item_parse_mode)
+                               -> {attrs_remaining: ~[attribute],
+                                   view_items: ~[@view_item],
+                                   items: ~[@item]} {
         let mut attrs = vec::append(first_item_attrs,
                                     self.parse_outer_attributes());
-        let mut items = ~[];
-        while if only_imports { self.is_keyword(~"import") }
-        else { self.is_view_item() } {
-            vec::push(items, self.parse_view_item(attrs));
+
+        let items_allowed;
+        match mode {
+            VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED =>
+                items_allowed = true,
+            VIEW_ITEMS_ALLOWED =>
+                items_allowed = false
+        }
+
+        let (view_items, items) = (dvec(), dvec());
+        loop {
+            match self.parse_item_or_view_item(attrs, items_allowed) {
+                iovi_none =>
+                    break,
+                iovi_view_item(view_item) => {
+                    match mode {
+                        VIEW_ITEMS_AND_ITEMS_ALLOWED |
+                        VIEW_ITEMS_ALLOWED => {}
+                        IMPORTS_AND_ITEMS_ALLOWED =>
+                            match view_item.node {
+                                view_item_import(_) => {}
+                                view_item_export(_) | view_item_use(*) =>
+                                    self.fatal(~"exports and \"extern mod\" \
+                                                 declarations are not \
+                                                 allowed here")
+                            }
+                    }
+                    view_items.push(view_item);
+                }
+                iovi_item(item) => {
+                    assert items_allowed;
+                    items.push(item)
+                }
+            }
             attrs = self.parse_outer_attributes();
         }
-        {attrs_remaining: attrs, view_items: items}
+
+        {attrs_remaining: attrs,
+         view_items: vec::from_mut(dvec::unwrap(view_items)),
+         items: vec::from_mut(dvec::unwrap(items))}
     }
 
     // Parses a source module as a crate