about summary refs log tree commit diff
path: root/src/comp/syntax/parse
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-01-31 19:30:40 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-02-03 22:47:35 -0800
commitf3343b35717edbfb88c7d1fae790e43d5d7cb732 (patch)
tree6d93ac26b11428dfe4324cbc44a3e68f56f6859d /src/comp/syntax/parse
parentd65eabd5de4c41e4bc93b9c6c03d6278299ceb76 (diff)
downloadrust-f3343b35717edbfb88c7d1fae790e43d5d7cb732.tar.gz
rust-f3343b35717edbfb88c7d1fae790e43d5d7cb732.zip
Beginnings of front-end support for classes
Added class support to the parser, prettyprinter, fold, and visit.
(See Issue 1726.)

This is WIP -- the test case is xfailed, and attempting to compile
it will error out in resolve.
Diffstat (limited to 'src/comp/syntax/parse')
-rw-r--r--src/comp/syntax/parse/parser.rs106
1 files changed, 105 insertions, 1 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 7253109d022..a4ed54f2675 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -1616,6 +1616,21 @@ fn parse_let(p: parser) -> @ast::decl {
     ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
 }
 
+fn parse_instance_var(p:parser) -> @ast::class_member {
+    let is_mut = ast::class_immutable;
+    expect_word(p, "let");
+    if eat_word(p, "mutable") {
+            is_mut = ast::class_mutable;
+    }
+    if !is_plain_ident(p) {
+        p.fatal("expecting ident");
+    }
+    let name = parse_ident(p);
+    expect(p, token::COLON);
+    let ty = parse_ty(p, false);
+    ret @ast::instance_var(name, ty, is_mut, p.get_id());
+}
+
 fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
     fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
         // If we have attributes then we should have an item
@@ -1980,6 +1995,92 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
                 attrs);
 }
 
+fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
+    let lo = p.last_span.lo;
+    let class_name = parse_value_ident(p);
+    let ty_params = parse_ty_params(p);
+    expect(p, token::LBRACE);
+    let items: [@ast::class_item] = [];
+    let the_ctor : option<(ast::fn_decl, ast::blk)> = none;
+    while p.token != token::RBRACE {
+       alt parse_class_item(p) {
+            ctor_decl(a_fn_decl, blk) {
+                the_ctor = some((a_fn_decl, blk));
+            }
+            plain_decl(a_decl) {
+                items += [@{node: {privacy: ast::pub, decl: a_decl},
+                            span: p.last_span}];
+            }
+            priv_decls(some_decls) {
+                items += vec::map(some_decls, {|d|
+                            @{node: {privacy: ast::priv, decl: d},
+                                span: p.last_span}});
+            }
+       }
+    }
+    p.bump();
+    alt the_ctor {
+       some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
+                     ast::item_class(ty_params, items, ct_d, ct_b), attrs); }
+       /*
+         Is it strange for the parser to check this?
+       */
+       none { /* parse error */ fail "Class with no ctor"; }
+    }
+}
+
+// lets us identify the constructor declaration at
+// parse time
+// we don't really want just the fn_decl...
+enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
+                      // assumed to be public
+                      plain_decl(@ast::class_member),
+                      // contents of a priv section --
+                      // parse_class_item ensures that
+                      // none of these are a ctor decl
+                      priv_decls([@ast::class_member])}
+
+fn parse_class_item(p:parser) -> class_contents {
+    if eat_word(p, "new") {
+        // Can ctors have attrs?
+        let decl = parse_fn_decl(p, ast::impure_fn);
+        let body = parse_block(p);
+        ret ctor_decl(decl, body);
+    }
+    // TODO: refactor
+    else if eat_word(p, "priv") {
+            expect(p, token::LBRACE);
+            let results = [];
+            while p.token != token::RBRACE {
+               alt parse_item(p, []) {
+                 some(i) {
+                     results += [@ast::class_method(i)];
+                 }
+                 _ {
+                     let a_var = parse_instance_var(p);
+                     expect(p, token::SEMI);
+                     results += [a_var];
+                 }
+               }
+            }
+            p.bump();
+            ret priv_decls(results);
+    }
+    else {
+        // Probably need to parse attrs
+        alt parse_item(p, []) {
+         some(i) {
+             ret plain_decl(@ast::class_method(i));
+         }
+         _ {
+             let a_var = parse_instance_var(p);
+             expect(p, token::SEMI);
+             ret plain_decl(a_var);
+         }
+        }
+    }
+}
+
 fn parse_mod_items(p: parser, term: token::token,
                    first_item_attrs: [ast::attribute]) -> ast::_mod {
     // Shouldn't be any view items since we've already parsed an item attr
@@ -2222,7 +2323,10 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option<@ast::item> {
         ret some(parse_item_impl(p, attrs));
     } else if eat_word(p, "resource") {
         ret some(parse_item_res(p, attrs));
-    } else { ret none; }
+    } else if eat_word(p, "class") {
+        ret some(parse_item_class(p, attrs));
+    }
+else { ret none; }
 }
 
 // A type to distingush between the parsing of item attributes or syntax