about summary refs log tree commit diff
path: root/src/comp/syntax/parse
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-12-20 16:33:55 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2011-12-23 18:09:25 +0100
commit057617c6654bfd5a677112cd26141d0b9c137145 (patch)
tree316c1b2cbcb11aa3cd02f05107e76fa5cd624fef /src/comp/syntax/parse
parent92927449595782926c4db5a579ba7e4c6952287d (diff)
downloadrust-057617c6654bfd5a677112cd26141d0b9c137145.tar.gz
rust-057617c6654bfd5a677112cd26141d0b9c137145.zip
Parse `iface` items and interface references in `impl` items.
The (temporary) syntax is

    iface seq<T> {
        fn len() -> uint;
        fn iter(f: block(T));
    }

    // The 'blah<T>' can be left of to default the name of the
    // impl to seq<T>. The 'of seq<T>' can be left off when
    // not implementing a named interface.
    impl blah<T> of seq<T> for [T] {
        fn len() -> uint { vec::len(self) }
        fn iter(f: block(T)) { for x in self { f(x); } }
    }
Diffstat (limited to 'src/comp/syntax/parse')
-rw-r--r--src/comp/syntax/parse/parser.rs117
1 files changed, 61 insertions, 56 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 484659f4bc5..8299f23ae20 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -165,7 +165,7 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
                  "cont", "ret", "be", "fail", "type", "resource", "check",
                  "assert", "claim", "native", "fn", "lambda", "pure",
                  "unsafe", "block", "import", "export", "let", "const",
-                 "log", "tag", "obj", "copy", "sendfn", "impl"] {
+                 "log", "tag", "obj", "copy", "sendfn", "impl", "iface"] {
         words.insert(word, ());
     }
     words
@@ -285,7 +285,7 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
                     constraints: constrs});
 }
 
-fn parse_ty_obj(p: parser) -> ast::ty_ {
+fn parse_ty_methods(p: parser) -> [ast::ty_method] {
     fn parse_method_sig(p: parser) -> ast::ty_method {
         let flo = p.get_lo_pos();
         let proto: ast::proto = parse_method_proto(p);
@@ -298,10 +298,8 @@ fn parse_ty_obj(p: parser) -> ast::ty_ {
           }
         }
     }
-    let meths =
-        parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(),
-                  parse_method_sig, p);
-    ret ast::ty_obj(meths.node);
+    parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(),
+              parse_method_sig, p).node
 }
 
 fn parse_mt(p: parser) -> ast::mt {
@@ -519,7 +517,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
     } else if eat_word(p, "sendfn") {
         t = parse_ty_fn(ast::proto_send, p);
     } else if eat_word(p, "obj") {
-        t = parse_ty_obj(p);
+        t = ast::ty_obj(parse_ty_methods(p));
     } else if p.peek() == token::MOD_SEP || is_ident(p.peek()) {
         let path = parse_path(p);
         t = ast::ty_path(path, p.get_id());
@@ -676,47 +674,22 @@ fn is_plain_ident(p: parser) -> bool {
 
 fn parse_path(p: parser) -> @ast::path {
     let lo = p.get_lo_pos();
-    let hi = lo;
-
-    let global;
-    if p.peek() == token::MOD_SEP {
-        global = true;
-        p.bump();
-    } else { global = false; }
-
-    let ids: [ast::ident] = [];
-    while true {
-        alt p.peek() {
-          token::IDENT(i, _) {
-            hi = p.get_hi_pos();
-            ids += [p.get_str(i)];
-            hi = p.get_hi_pos();
-            p.bump();
-            if p.peek() == token::MOD_SEP && p.look_ahead(1u) != token::LT {
-                p.bump();
-            } else { break; }
-          }
-          _ { break; }
-        }
+    let global = eat(p, token::MOD_SEP), ids = [parse_ident(p)];
+    while p.look_ahead(1u) != token::LT && eat(p, token::MOD_SEP) {
+        ids += [parse_ident(p)];
     }
-    ret @spanned(lo, hi, {global: global, idents: ids, types: []});
+    ret @spanned(lo, p.get_last_hi_pos(),
+                 {global: global, idents: ids, types: []});
 }
 
-fn parse_path_and_ty_param_substs(p: parser) -> @ast::path {
+fn parse_path_and_ty_param_substs(p: parser, colons: bool) -> @ast::path {
     let lo = p.get_lo_pos();
     let path = parse_path(p);
-    if p.peek() == token::MOD_SEP {
-        p.bump();
-
-        let seq =
-            parse_seq_lt_gt(some(token::COMMA), {|p| parse_ty(p, false)}, p);
-        let hi = seq.span.hi;
-        path = @spanned(lo, hi,
-                        {global: path.node.global,
-                         idents: path.node.idents,
-                         types: seq.node});
-    }
-    ret path;
+    if colons ? eat(p, token::MOD_SEP) : p.peek() == token::LT {
+        let seq = parse_seq_lt_gt(some(token::COMMA),
+                                  {|p| parse_ty(p, false)}, p);
+        @spanned(lo, seq.span.hi, {types: seq.node with path.node})
+    } else { path }
 }
 
 fn parse_mutability(p: parser) -> ast::mutability {
@@ -958,7 +931,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
                   is_ident(p.peek()) && !is_word(p, "true") &&
                       !is_word(p, "false") {
         check_bad_word(p);
-        let pth = parse_path_and_ty_param_substs(p);
+        let pth = parse_path_and_ty_param_substs(p, true);
         hi = pth.span.hi;
         ex = ast::expr_path(pth);
     } else {
@@ -984,10 +957,11 @@ fn parse_syntax_ext(p: parser) -> @ast::expr {
 }
 
 fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
-    let pth = parse_path(p);
-    if vec::len(pth.node.idents) == 0u {
-        p.fatal("expected a syntax expander name");
+    alt p.peek() {
+      token::IDENT(_, _) {}
+      _ { p.fatal("expected a syntax expander name"); }
     }
+    let pth = parse_path(p);
     //temporary for a backwards-compatible cycle:
     let sep = seq_sep(token::COMMA);
     let es =
@@ -1518,7 +1492,7 @@ fn parse_pat(p: parser) -> @ast::pat {
             let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
             pat = ast::pat_bind(name, sub);
         } else {
-            let tag_path = parse_path_and_ty_param_substs(p);
+            let tag_path = parse_path_and_ty_param_substs(p, true);
             hi = tag_path.span.hi;
             let args: [@ast::pat];
             alt p.peek() {
@@ -1751,12 +1725,9 @@ fn parse_ty_param(p: parser) -> ast::ty_param {
 }
 
 fn parse_ty_params(p: parser) -> [ast::ty_param] {
-    let ty_params: [ast::ty_param] = [];
-    if p.peek() == token::LT {
-        p.bump();
-        ty_params = parse_seq_to_gt(some(token::COMMA), parse_ty_param, p);
-    }
-    ret ty_params;
+    if eat(p, token::LT) {
+        parse_seq_to_gt(some(token::COMMA), parse_ty_param, p)
+    } else { [] }
 }
 
 fn parse_fn_decl(p: parser, proto: ast::proto, purity: ast::purity)
@@ -1866,15 +1837,47 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
                 attrs);
 }
 
-fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
+fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
     let lo = p.get_last_lo_pos(), ident = parse_ident(p),
+        tps = parse_ty_params(p), meths = parse_ty_methods(p);
+    ret mk_item(p, lo, p.get_last_hi_pos(), ident,
+                ast::item_iface(tps, meths), attrs);
+}
+
+fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
+    let lo = p.get_last_lo_pos(), ident, tps, ifce;
+    fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
+        @{node: ast::ty_path(pt, p.get_id()), span: pt.span}
+    }
+    if eat_word(p, "of") {
+        let path = parse_path_and_ty_param_substs(p, false);
+        tps = vec::map(path.node.types, {|tp|
+            alt tp.node {
+              ast::ty_path(pt, _) {
+                if vec::len(pt.node.idents) == 1u &&
+                   vec::len(pt.node.types) == 0u {
+                     ret {ident: pt.node.idents[0], kind: ast::kind_sendable};
+                }
+              }
+              _ {}
+            }
+            p.fatal("only single-word, parameter-less types allowed here");
+        });
+        ident = path.node.idents[vec::len(path.node.idents)-1u];
+        ifce = some(wrap_path(p, path));
+    } else {
+        ident = parse_ident(p);
         tps = parse_ty_params(p);
+        ifce = if eat_word(p, "of") {
+            some(wrap_path(p, parse_path_and_ty_param_substs(p, false)))
+        } else { none };
+    };
     expect_word(p, "for");
     let ty = parse_ty(p, false), meths = [];
     expect(p, token::LBRACE);
     while !eat(p, token::RBRACE) { meths += [parse_method(p, true)]; }
     ret mk_item(p, lo, p.get_last_hi_pos(), ident,
-                ast::item_impl(tps, ty, meths), attrs);
+                ast::item_impl(tps, ifce, ty, meths), attrs);
 }
 
 fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
@@ -2145,6 +2148,8 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
     } else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
         p.bump();
         ret some(parse_item_obj(p, attrs));
+    } else if eat_word(p, "iface") {
+        ret some(parse_item_iface(p, attrs));
     } else if eat_word(p, "impl") {
         ret some(parse_item_impl(p, attrs));
     } else if eat_word(p, "resource") {