about summary refs log tree commit diff
path: root/src/comp/syntax
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-02-17 23:05:20 -0800
committerGraydon Hoare <graydon@mozilla.com>2012-02-17 23:05:20 -0800
commitef6f6285893ca2546d740771b4c8046bfa68f668 (patch)
tree78c00965b1b06d7920ab4a64097bbf9c8b635b78 /src/comp/syntax
parent6f708968549b346611e8172b02612f3c32ca4feb (diff)
downloadrust-ef6f6285893ca2546d740771b4c8046bfa68f668.tar.gz
rust-ef6f6285893ca2546d740771b4c8046bfa68f668.zip
Refactor view_path to parse (but not yet process) export globs, unify code paths.
Diffstat (limited to 'src/comp/syntax')
-rw-r--r--src/comp/syntax/ast.rs32
-rw-r--r--src/comp/syntax/ast_util.rs63
-rw-r--r--src/comp/syntax/parse/parser.rs183
-rw-r--r--src/comp/syntax/print/pprust.rs89
4 files changed, 164 insertions, 203 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
index 3a365e58bbd..a76b6f9919f 100644
--- a/src/comp/syntax/ast.rs
+++ b/src/comp/syntax/ast.rs
@@ -441,26 +441,36 @@ type variant_ = {name: ident, attrs: [attribute], args: [variant_arg],
 
 type variant = spanned<variant_>;
 
-type view_item = spanned<view_item_>;
 
 // FIXME: May want to just use path here, which would allow things like
 // 'import ::foo'
 type simple_path = [ident];
 
-type import_ident_ = {name: ident, id: node_id};
+type path_list_ident_ = {name: ident, id: node_id};
+type path_list_ident = spanned<path_list_ident_>;
+
+type view_path = spanned<view_path_>;
+enum view_path_ {
+
+    // quux = foo::bar::baz
+    //
+    // or just
+    //
+    // foo::bar::baz  (with 'baz =' implicitly on the left)
+    view_path_simple(ident, @simple_path, node_id),
 
-type import_ident = spanned<import_ident_>;
+    // foo::bar::*
+    view_path_glob(@simple_path, node_id),
 
+    // foo::bar::{a,b,c}
+    view_path_list(@simple_path, [path_list_ident], node_id)
+}
+
+type view_item = spanned<view_item_>;
 enum view_item_ {
     view_item_use(ident, [@meta_item], node_id),
-    view_item_import(ident, @simple_path, node_id),
-    view_item_import_glob(@simple_path, node_id),
-    view_item_import_from(@simple_path, [import_ident], node_id),
-    view_item_export([ident], node_id),
-    // export foo::{}
-    view_item_export_enum_none(ident, node_id),
-    // export foo::{bar, baz, blat}
-    view_item_export_enum_some(ident, [import_ident], node_id)
+    view_item_import([@view_path]),
+    view_item_export([@view_path])
 }
 
 // Meta-data associated with an item
diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs
index cd508aae90b..09242f40c42 100644
--- a/src/comp/syntax/ast_util.rs
+++ b/src/comp/syntax/ast_util.rs
@@ -116,56 +116,63 @@ fn float_ty_to_str(t: float_ty) -> str {
 }
 
 fn is_exported(i: ident, m: _mod) -> bool {
-    let nonlocal = true;
+    let local = false;
     let parent_enum : option<ident> = none;
     for it: @item in m.items {
-        if it.ident == i { nonlocal = false; }
+        if it.ident == i { local = true; }
         alt it.node {
           item_enum(variants, _) {
             for v: variant in variants {
                 if v.node.name == i {
-                   nonlocal = false;
+                   local = true;
                    parent_enum = some(it.ident);
                 }
             }
           }
           _ { }
         }
-        if !nonlocal { break; }
+        if local { break; }
     }
-    let count = 0u;
+    let has_explicit_exports = false;
     for vi: @view_item in m.view_items {
         alt vi.node {
-          view_item_export(ids, _) {
-              // If any of ids is a enum, we want to consider
-              // all the variants to be exported
-            for id in ids {
-                if str::eq(i, id) { ret true; }
-                alt parent_enum {
-                    some(parent_enum_id) {
-                        if str::eq(id, parent_enum_id) { ret true; }
+          view_item_export(vps) {
+            has_explicit_exports = true;
+            for vp in vps {
+                alt vp.node {
+                  ast::view_path_simple(id, _, _) {
+                    if id == i { ret true; }
+                    alt parent_enum {
+                      some(parent_enum_id) {
+                        if id == parent_enum_id { ret true; }
+                      }
+                      _ {}
                     }
-                    _ { }
-                 }
+                  }
+
+                  ast::view_path_list(path, ids, _) {
+                    if vec::len(*path) == 1u {
+                        if i == path[0] { ret true; }
+                        for id in ids {
+                            if id.node.name == i { ret true; }
+                        }
+                    } else {
+                        fail "export of path-qualified list";
+                    }
+                  }
+
+                  // FIXME: glob-exports aren't supported yet.
+                  _ {}
+                }
             }
-            count += 1u;
-          }
-          view_item_export_enum_none(id, _) {
-              if str::eq(i, id) { ret true; }
-              count += 1u;
-          }
-          view_item_export_enum_some(id, ids, _) {
-              if str::eq(i, id) { ret true; }
-              for id in ids { if str::eq(i, id.node.name) { ret true; } }
-              count += 1u;
           }
-          _ {/* fall through */ }
+          _ {}
         }
     }
     // If there are no declared exports then
     // everything not imported is exported
-    // even if it's nonlocal (since it's explicit)
-    ret count == 0u && !nonlocal;
+    // even if it's local (since it's explicit)
+    ret !has_explicit_exports && local;
 }
 
 pure fn is_call_expr(e: @expr) -> bool {
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 1e21dff0b34..eb34fb4b89d 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -202,7 +202,7 @@ fn parse_ident(p: parser) -> ast::ident {
     }
 }
 
-fn parse_import_ident(p: parser) -> ast::import_ident {
+fn parse_path_list_ident(p: parser) -> ast::path_list_ident {
     let lo = p.span.lo;
     let ident = parse_ident(p);
     let hi = p.span.hi;
@@ -2421,139 +2421,80 @@ fn parse_use(p: parser) -> ast::view_item_ {
     ret ast::view_item_use(ident, metadata, p.get_id());
 }
 
-fn parse_rest_import_name(p: parser, first: ast::ident,
-                          def_ident: option<ast::ident>) ->
-   ast::view_item_ {
-    let identifiers: [ast::ident] = [first];
-    let glob: bool = false;
-    let from_idents = option::none::<[ast::import_ident]>;
-    while true {
-        alt p.token {
-          token::SEMI { break; }
-          token::MOD_SEP {
-            if glob { p.fatal("cannot path into a glob"); }
-            if option::is_some(from_idents) {
-                p.fatal("cannot path into import list");
-            }
+fn parse_view_path(p: parser) -> @ast::view_path {
+    let lo = p.span.lo;
+    let first_ident = parse_ident(p);
+    let path = [first_ident];
+    #debug("parsed view_path: %s", first_ident);
+    alt p.token {
+      token::EQ {
+        // x = foo::bar
+        p.bump();
+        path = [parse_ident(p)];
+        while p.token == token::MOD_SEP {
             p.bump();
-          }
-          _ { p.fatal("expecting '::' or ';'"); }
+            let id = parse_ident(p);
+            path += [id];
         }
-        alt p.token {
-          token::IDENT(_, _) { identifiers += [parse_ident(p)]; }
-
-
-
-
+        let hi = p.span.hi;
+        ret @spanned(lo, hi,
+                     ast::view_path_simple(first_ident,
+                                           @path, p.get_id()));
+      }
 
-          //the lexer can't tell the different kinds of stars apart ) :
-          token::BINOP(token::STAR) {
-            glob = true;
+      token::MOD_SEP {
+        // foo::bar or foo::{a,b,c} or foo::*
+        while p.token == token::MOD_SEP {
             p.bump();
-          }
 
+            alt p.token {
 
+              token::IDENT(i, _) {
+                p.bump();
+                path += [p.get_str(i)];
+              }
 
+              // foo::bar::{a,b,c}
+              token::LBRACE {
+                let idents =
+                    parse_seq(token::LBRACE, token::RBRACE,
+                              seq_sep(token::COMMA),
+                              parse_path_list_ident, p).node;
+                let hi = p.span.hi;
+                ret @spanned(lo, hi,
+                             ast::view_path_list(@path, idents,
+                                                 p.get_id()));
+              }
 
+              // foo::bar::*
+              token::BINOP(token::STAR) {
+                p.bump();
+                let hi = p.span.hi;
+                ret @spanned(lo, hi,
+                             ast::view_path_glob(@path,
+                                                 p.get_id()));
+              }
 
-          token::LBRACE {
-            let from_idents_ =
-                parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
-                          parse_import_ident, p).node;
-            if vec::is_empty(from_idents_) {
-                p.fatal("at least one import is required");
+              _ { break; }
             }
-            from_idents = some(from_idents_);
-          }
-
-
-
-
-
-          _ {
-            p.fatal("expecting an identifier, or '*'");
-          }
-        }
-    }
-    alt def_ident {
-      some(i) {
-        if glob { p.fatal("globbed imports can't be renamed"); }
-        if option::is_some(from_idents) {
-            p.fatal("can't rename import list");
-        }
-        ret ast::view_item_import(i, @identifiers, p.get_id());
-      }
-      _ {
-        if glob {
-            ret ast::view_item_import_glob(@identifiers, p.get_id());
-        } else if option::is_some(from_idents) {
-            ret ast::view_item_import_from(@identifiers,
-                                           option::get(from_idents),
-                                           p.get_id());
-        } else {
-            let len = vec::len(identifiers);
-            ret ast::view_item_import(identifiers[len - 1u], @identifiers,
-                                      p.get_id());
         }
       }
+      _ { }
     }
+    let hi = p.span.hi;
+    let last = path[vec::len(path) - 1u];
+    ret @spanned(lo, hi,
+                 ast::view_path_simple(last, @path,
+                                       p.get_id()));
 }
 
-fn parse_full_import_name(p: parser, def_ident: ast::ident) ->
-   ast::view_item_ {
-    alt p.token {
-      token::IDENT(i, _) {
+fn parse_view_paths(p: parser) -> [@ast::view_path] {
+    let vp = [parse_view_path(p)];
+    while p.token == token::COMMA {
         p.bump();
-        ret parse_rest_import_name(p, p.get_str(i), some(def_ident));
-      }
-      _ { p.fatal("expecting an identifier"); }
-    }
-}
-
-fn parse_import(p: parser) -> ast::view_item_ {
-    alt p.token {
-      token::IDENT(i, _) {
-        p.bump();
-        alt p.token {
-          token::EQ {
-            p.bump();
-            ret parse_full_import_name(p, p.get_str(i));
-          }
-          _ { ret parse_rest_import_name(p, p.get_str(i), none); }
-        }
-      }
-      _ { p.fatal("expecting an identifier"); }
-    }
-}
-
-fn parse_enum_export(p:parser, tyname:ast::ident) -> ast::view_item_ {
-    let enumnames:[ast::import_ident] =
-        parse_seq(token::LBRACE, token::RBRACE,
-             seq_sep(token::COMMA), {|p| parse_import_ident(p) }, p).node;
-    let id = p.get_id();
-    if vec::is_empty(enumnames) {
-       ret ast::view_item_export_enum_none(tyname, id);
-    }
-    else {
-       ret ast::view_item_export_enum_some(tyname, enumnames, id);
-    }
-}
-
-fn parse_export(p: parser) -> ast::view_item_ {
-    let first = parse_ident(p);
-    alt p.token {
-       token::MOD_SEP {
-           p.bump();
-           ret parse_enum_export(p, first);
-       }
-       t {
-           if t == token::COMMA { p.bump(); }
-           let ids =
-               parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
-                                       parse_ident, p);
-           ret ast::view_item_export(vec::concat([[first], ids]), p.get_id());
-       }
+        vp += [parse_view_path(p)];
     }
+    ret vp;
 }
 
 fn parse_view_item(p: parser) -> @ast::view_item {
@@ -2562,8 +2503,12 @@ fn parse_view_item(p: parser) -> @ast::view_item {
         if eat_word(p, "use") {
             parse_use(p)
         } else if eat_word(p, "import") {
-            parse_import(p)
-        } else if eat_word(p, "export") { parse_export(p) } else { fail };
+            ast::view_item_import(parse_view_paths(p))
+        } else if eat_word(p, "export") {
+            ast::view_item_export(parse_view_paths(p))
+        } else {
+            fail
+    };
     let hi = p.span.lo;
     expect(p, token::SEMI);
     ret @spanned(lo, hi, the_item);
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index 343b4500a3d..3d0e8a579dc 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -1333,6 +1333,44 @@ fn print_meta_item(s: ps, &&item: @ast::meta_item) {
     end(s);
 }
 
+fn print_simple_path(s: ps, path: ast::simple_path) {
+    let first = true;
+    for id in path {
+        if first { first = false; } else { word(s.s, "::"); }
+        word(s.s, id);
+    }
+}
+
+fn print_view_path(s: ps, &&vp: @ast::view_path) {
+    alt vp.node {
+      ast::view_path_simple(ident, path, _) {
+        if path[vec::len(*path)-1u] != ident {
+            word_space(s, ident);
+            word_space(s, "=");
+        }
+        print_simple_path(s, *path);
+      }
+
+      ast::view_path_glob(path, _) {
+        print_simple_path(s, *path);
+        word(s.s, "::*");
+      }
+
+      ast::view_path_list(path, idents, _) {
+        print_simple_path(s, *path);
+        word(s.s, "::{");
+        commasep(s, inconsistent, idents) {|s, w|
+            word(s.s, w.node.name)
+        }
+        word(s.s, "}");
+      }
+    }
+}
+
+fn print_view_paths(s: ps, vps: [@ast::view_path]) {
+    commasep(s, inconsistent, vps, print_view_path);
+}
+
 fn print_view_item(s: ps, item: @ast::view_item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
@@ -1346,59 +1384,20 @@ fn print_view_item(s: ps, item: @ast::view_item) {
             pclose(s);
         }
       }
-      ast::view_item_import(id, ids, _) {
-        head(s, "import");
-        if !str::eq(id, ids[vec::len(*ids) - 1u]) {
-            word_space(s, id);
-            word_space(s, "=");
-        }
-        let first = true;
-        for elt: ast::ident in *ids {
-            if first { first = false; } else { word(s.s, "::"); }
-            word(s.s, elt);
-        }
-      }
-      ast::view_item_import_from(mod_path, idents, _) {
-        head(s, "import");
-        for elt: ast::ident in *mod_path { word(s.s, elt); word(s.s, "::"); }
-        word(s.s, "{");
-        commasep(s, inconsistent, idents,
-                 fn@(s: ps, w: ast::import_ident) { word(s.s, w.node.name) });
-        word(s.s, "}");
-      }
-      ast::view_item_import_glob(ids, _) {
+
+      ast::view_item_import(vps) {
         head(s, "import");
-        let first = true;
-        for elt: ast::ident in *ids {
-            if first { first = false; } else { word(s.s, "::"); }
-            word(s.s, elt);
-        }
-        word(s.s, "::*");
+        print_view_paths(s, vps);
       }
-      ast::view_item_export(ids, _) {
+
+      ast::view_item_export(vps) {
         head(s, "export");
-        commasep(s, inconsistent, ids,
-                 fn@(s: ps, &&w: ast::ident) { word(s.s, w) });
-      }
-      ast::view_item_export_enum_none(id, _) {
-          head(s, "export");
-          word(s.s, id);
-          word(s.s, "::{}");
-      }
-      ast::view_item_export_enum_some(id, ids, _) {
-          head(s, "export");
-          word(s.s, id);
-          word(s.s, "::{");
-          commasep(s, inconsistent, ids, fn@(s:ps, &&w: ast::import_ident) {
-                  word(s.s, w.node.name) });
-          word(s.s, "}");
+        print_view_paths(s, vps);
       }
     }
     word(s.s, ";");
     end(s); // end inner head-block
-
     end(s); // end outer head-block
-
 }