diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-01-31 19:30:40 -0800 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-02-03 22:47:35 -0800 |
| commit | f3343b35717edbfb88c7d1fae790e43d5d7cb732 (patch) | |
| tree | 6d93ac26b11428dfe4324cbc44a3e68f56f6859d /src/comp/syntax/parse | |
| parent | d65eabd5de4c41e4bc93b9c6c03d6278299ceb76 (diff) | |
| download | rust-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.rs | 106 |
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 |
