about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-05-08 23:01:38 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2012-05-08 23:14:24 +0200
commit96a159a6eaea213c2b9b9582a133a718bc967eac (patch)
tree875241bab9ff115d255578026c1437fcf392af77
parent5c0577f233ee79c85c6890977f8f73ffe8a21233 (diff)
downloadrust-96a159a6eaea213c2b9b9582a133a718bc967eac.tar.gz
rust-96a159a6eaea213c2b9b9582a133a718bc967eac.zip
Support visibility modifiers and attributes on view items
Issue #1893
Tangentially, issue #2357
-rw-r--r--src/librustsyntax/ast.rs3
-rw-r--r--src/librustsyntax/fold.rs2
-rw-r--r--src/librustsyntax/parse/attr.rs2
-rw-r--r--src/librustsyntax/parse/common.rs14
-rw-r--r--src/librustsyntax/parse/parser.rs97
-rw-r--r--src/rustc/front/core_inject.rs10
-rw-r--r--src/test/compile-fail/ext-after-attrib.rs2
-rw-r--r--src/test/run-pass/attr-before-view-item.rs (renamed from src/test/compile-fail/attr-before-view-item.rs)0
-rw-r--r--src/test/run-pass/attr-before-view-item2.rs (renamed from src/test/compile-fail/attr-before-view-item2.rs)0
9 files changed, 61 insertions, 69 deletions
diff --git a/src/librustsyntax/ast.rs b/src/librustsyntax/ast.rs
index cf338ad02c2..210244eca91 100644
--- a/src/librustsyntax/ast.rs
+++ b/src/librustsyntax/ast.rs
@@ -612,7 +612,8 @@ enum view_path_ {
 }
 
 #[auto_serialize]
-type view_item = spanned<view_item_>;
+type view_item = {node: view_item_, attrs: [attribute],
+                  vis: visibility, span: span};
 
 #[auto_serialize]
 enum view_item_ {
diff --git a/src/librustsyntax/fold.rs b/src/librustsyntax/fold.rs
index f538cc52651..ebc65c9db38 100644
--- a/src/librustsyntax/fold.rs
+++ b/src/librustsyntax/fold.rs
@@ -679,6 +679,8 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
     fn f_view_item(afp: ast_fold_precursor, f: ast_fold, &&x: @view_item) ->
        @view_item {
         ret @{node: afp.fold_view_item(x.node, f),
+              attrs: vec::map(x.attrs, {|a| fold_attribute_(a, f)}),
+              vis: x.vis,
               span: afp.new_span(x.span)};
     }
     fn f_native_item(afp: ast_fold_precursor, f: ast_fold, &&x: @native_item)
diff --git a/src/librustsyntax/parse/attr.rs b/src/librustsyntax/parse/attr.rs
index 969aa03d902..e8d73915577 100644
--- a/src/librustsyntax/parse/attr.rs
+++ b/src/librustsyntax/parse/attr.rs
@@ -39,7 +39,7 @@ fn parse_outer_attrs_or_ext(
 // Parse attributes that appear before an item
 fn parse_outer_attributes(p: parser) -> [ast::attribute] {
     let mut attrs: [ast::attribute] = [];
-    while p.token == token::POUND {
+    while p.token == token::POUND && p.look_ahead(1u) == token::LBRACKET {
         attrs += [parse_attribute(p, ast::attr_outer)];
     }
     ret attrs;
diff --git a/src/librustsyntax/parse/common.rs b/src/librustsyntax/parse/common.rs
index 8bf388f3d40..b50c2b7e7f3 100644
--- a/src/librustsyntax/parse/common.rs
+++ b/src/librustsyntax/parse/common.rs
@@ -58,12 +58,16 @@ fn require_keyword(p: parser, word: str) {
     }
 }
 
-fn is_keyword(p: parser, word: str) -> bool {
+fn token_is_keyword(p: parser, word: str, tok: token::token) -> bool {
     require_keyword(p, word);
-    ret alt p.token {
-          token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
-          _ { false }
-        };
+    alt tok {
+      token::IDENT(sid, false) { str::eq(word, p.get_str(sid)) }
+      _ { false }
+    }
+}
+
+fn is_keyword(p: parser, word: str) -> bool {
+    token_is_keyword(p, word, p.token)
 }
 
 fn eat_keyword(p: parser, word: str) -> bool {
diff --git a/src/librustsyntax/parse/parser.rs b/src/librustsyntax/parse/parser.rs
index 1bfc6b2c6c2..7b1b9823a1f 100644
--- a/src/librustsyntax/parse/parser.rs
+++ b/src/librustsyntax/parse/parser.rs
@@ -1606,8 +1606,8 @@ fn parse_block_tail_(p: parser, lo: uint, s: blk_check_mode,
                      +first_item_attrs: [attribute]) -> blk {
     let mut stmts = [];
     let mut expr = none;
-    let view_items = maybe_parse_view_import_only(p, first_item_attrs);
-    let mut initial_attrs = first_item_attrs;
+    let {attrs_remaining, view_items} = parse_view(p, first_item_attrs, true);
+    let mut initial_attrs = attrs_remaining;
 
     if p.token == token::RBRACE && !vec::is_empty(initial_attrs) {
         p.fatal("expected item");
@@ -2036,12 +2036,13 @@ fn parse_visibility(p: parser, def: visibility) -> visibility {
 fn parse_mod_items(p: parser, term: token::token,
                    +first_item_attrs: [attribute]) -> _mod {
     // Shouldn't be any view items since we've already parsed an item attr
-    let view_items = maybe_parse_view(p, first_item_attrs);
+    let {attrs_remaining, view_items} =
+        parse_view(p, first_item_attrs, false);
     let mut items: [@item] = [];
     let mut first = true;
     while p.token != term {
         let mut attrs = parse_outer_attributes(p);
-        if first { attrs = first_item_attrs + attrs; first = false; }
+        if first { attrs = attrs_remaining + attrs; first = false; }
         #debug["parse_mod_items: parse_item(attrs=%?)", attrs];
         let vis = parse_visibility(p, private);
         alt parse_item(p, attrs, vis) {
@@ -2054,7 +2055,7 @@ fn parse_mod_items(p: parser, term: token::token,
         #debug["parse_mod_items: attrs=%?", attrs];
     }
 
-    if first && first_item_attrs.len() > 0u {
+    if first && attrs_remaining.len() > 0u {
         // We parsed attributes for the first item but didn't find the item
         p.fatal("expected item");
     }
@@ -2113,12 +2114,10 @@ fn parse_native_item(p: parser, +attrs: [attribute]) ->
 fn parse_native_mod_items(p: parser, +first_item_attrs: [attribute]) ->
    native_mod {
     // Shouldn't be any view items since we've already parsed an item attr
-    let view_items =
-        if vec::len(first_item_attrs) == 0u {
-            parse_native_view(p)
-        } else { [] };
+    let {attrs_remaining, view_items} =
+        parse_view(p, first_item_attrs, false);
     let mut items: [@native_item] = [];
-    let mut initial_attrs = first_item_attrs;
+    let mut initial_attrs = attrs_remaining;
     while p.token != token::RBRACE {
         let attrs = initial_attrs + parse_outer_attributes(p);
         initial_attrs = [];
@@ -2378,58 +2377,38 @@ fn parse_view_paths(p: parser) -> [@view_path] {
     ret vp;
 }
 
-fn parse_view_item(p: parser) -> @view_item {
-    let lo = p.span.lo;
-    let the_item =
-        if eat_keyword(p, "use") {
-            parse_use(p)
-        } else if eat_keyword(p, "import") {
-            view_item_import(parse_view_paths(p))
-        } else if eat_keyword(p, "export") {
-            view_item_export(parse_view_paths(p))
-        } else {
-            fail
-    };
-    let mut hi = p.span.lo;
-    expect(p, token::SEMI);
-    ret @spanned(lo, hi, the_item);
-}
-
 fn is_view_item(p: parser) -> bool {
-    is_keyword(p, "use") || is_keyword(p, "import") || is_keyword(p, "export")
-}
-
-fn maybe_parse_view(
-    p: parser,
-    first_item_attrs: [attribute]) -> [@view_item] {
-
-    maybe_parse_view_while(p, first_item_attrs, is_view_item)
-}
-
-fn maybe_parse_view_import_only(
-    p: parser,
-    first_item_attrs: [attribute]) -> [@view_item] {
-
-    maybe_parse_view_while(p, first_item_attrs, bind is_keyword(_, "import"))
+    let tok = if !is_keyword(p, "pub") && !is_keyword(p, "priv") { p.token }
+              else { p.look_ahead(1u) };
+    token_is_keyword(p, "use", tok) || token_is_keyword(p, "import", tok) ||
+        token_is_keyword(p, "export", tok)
+}
+
+fn parse_view_item(p: parser, +attrs: [attribute]) -> @view_item {
+    let lo = p.span.lo, vis = parse_visibility(p, private);
+    let node = if eat_keyword(p, "use") {
+        parse_use(p)
+    } else if eat_keyword(p, "import") {
+        view_item_import(parse_view_paths(p))
+    } else if eat_keyword(p, "export") {
+        view_item_export(parse_view_paths(p))
+    } else { fail; };
+    expect(p, token::SEMI);
+    @{node: node, attrs: attrs,
+      vis: vis, span: mk_sp(lo, p.last_span.hi)}
 }
 
-fn maybe_parse_view_while(
-    p: parser,
-    first_item_attrs: [attribute],
-    f: fn@(parser) -> bool) -> [@view_item] {
-
-    if vec::len(first_item_attrs) == 0u {
-        let mut items = [];
-        while f(p) { items += [parse_view_item(p)]; }
-        ret items;
-    } else {
-        // Shouldn't be any view items since we've already parsed an item attr
-        ret [];
+fn parse_view(p: parser, +first_item_attrs: [attribute],
+              only_imports: bool) -> {attrs_remaining: [attribute],
+                                      view_items: [@view_item]} {
+    let mut attrs = first_item_attrs + parse_outer_attributes(p);
+    let mut items = [];
+    while if only_imports { is_keyword(p, "import") }
+          else { is_view_item(p) } {
+        items += [parse_view_item(p, attrs)];
+        attrs = parse_outer_attributes(p);
     }
-}
-
-fn parse_native_view(p: parser) -> [@view_item] {
-    maybe_parse_view_while(p, [], is_view_item)
+    {attrs_remaining: attrs, view_items: items}
 }
 
 // Parses a source module as a crate
@@ -2494,7 +2473,7 @@ fn parse_crate_directive(p: parser, first_outer_attr: [attribute]) ->
           _ { unexpected(p); }
         }
     } else if is_view_item(p) {
-        let vi = parse_view_item(p);
+        let vi = parse_view_item(p, outer_attrs);
         ret spanned(lo, vi.span.hi, cdir_view_item(vi));
     } else { ret p.fatal("expected crate directive"); }
 }
diff --git a/src/rustc/front/core_inject.rs b/src/rustc/front/core_inject.rs
index 79c78e2fcc4..590a371da07 100644
--- a/src/rustc/front/core_inject.rs
+++ b/src/rustc/front/core_inject.rs
@@ -30,10 +30,16 @@ fn inject_libcore_ref(sess: session,
     let n1 = sess.next_node_id();
     let n2 = sess.next_node_id();
 
-    let vi1 = spanned(ast::view_item_use("core", [], n1));
+    let vi1 = @{node: ast::view_item_use("core", [], n1),
+                attrs: [],
+                vis: ast::public,
+                span: dummy_sp()};
     let vp = spanned(ast::view_path_glob(ident_to_path(dummy_sp(), "core"),
                                          n2));
-    let vi2 = spanned(ast::view_item_import([vp]));
+    let vi2 = @{node: ast::view_item_import([vp]),
+                attrs: [],
+                vis: ast::public,
+                span: dummy_sp()};
 
     let vis = [vi1, vi2] + crate.node.module.view_items;
 
diff --git a/src/test/compile-fail/ext-after-attrib.rs b/src/test/compile-fail/ext-after-attrib.rs
index 1eea33bc2e9..42d93b82208 100644
--- a/src/test/compile-fail/ext-after-attrib.rs
+++ b/src/test/compile-fail/ext-after-attrib.rs
@@ -1,4 +1,4 @@
-// error-pattern:expecting '[' but found 'fmt'
+// error-pattern:expected item but found '#'
 
 // Don't know how to deal with a syntax extension appearing after an
 // item attribute. Probably could use a better error message.
diff --git a/src/test/compile-fail/attr-before-view-item.rs b/src/test/run-pass/attr-before-view-item.rs
index 60788d65b82..60788d65b82 100644
--- a/src/test/compile-fail/attr-before-view-item.rs
+++ b/src/test/run-pass/attr-before-view-item.rs
diff --git a/src/test/compile-fail/attr-before-view-item2.rs b/src/test/run-pass/attr-before-view-item2.rs
index 539f028d611..539f028d611 100644
--- a/src/test/compile-fail/attr-before-view-item2.rs
+++ b/src/test/run-pass/attr-before-view-item2.rs