parser: Consolidate some duplicated code

This commit is contained in:
Marijn Haverbeke 2012-05-08 15:37:32 +02:00
parent 4885ffb579
commit df3bf7c2a0

View File

@ -618,7 +618,7 @@ fn parse_field(p: parser, sep: token::token) -> ast::field {
ret spanned(lo, e.span.hi, {mutbl: m, ident: i, expr: e});
}
fn mk_expr(p: parser, lo: uint, hi: uint, node: ast::expr_) -> @ast::expr {
fn mk_expr(p: parser, lo: uint, hi: uint, +node: ast::expr_) -> @ast::expr {
ret @{id: p.get_id(), node: node, span: mk_sp(lo, hi)};
}
@ -1501,7 +1501,7 @@ fn parse_instance_var(p:parser, pr: ast::privacy) -> @ast::class_member {
span: mk_sp(lo, p.last_span.hi)};
}
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
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
if vec::is_not_empty(current_attrs) {
@ -1603,7 +1603,7 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
}
fn parse_block_tail_(p: parser, lo: uint, s: ast::blk_check_mode,
first_item_attrs: [ast::attribute]) -> ast::blk {
+first_item_attrs: [ast::attribute]) -> ast::blk {
let mut stmts = [];
let mut expr = none;
let view_items = maybe_parse_view_import_only(p, first_item_attrs);
@ -1788,8 +1788,8 @@ fn parse_fn_header(p: parser) -> {ident: ast::ident, tps: [ast::ty_param]} {
ret {ident: id, tps: ty_params};
}
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
attrs: [ast::attribute]) -> @ast::item {
fn mk_item(p: parser, lo: uint, hi: uint, +ident: ast::ident,
+node: ast::item_, +attrs: [ast::attribute]) -> @ast::item {
ret @{ident: ident,
attrs: attrs,
id: p.get_id(),
@ -1797,15 +1797,13 @@ fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_,
span: mk_sp(lo, hi)};
}
fn parse_item_fn(p: parser, purity: ast::purity,
attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
type item_info = (ast::ident, ast::item_, option<[ast::attribute]>);
fn parse_item_fn(p: parser, purity: ast::purity) -> item_info {
let t = parse_fn_header(p);
let (decl, _) = parse_fn_decl(p, purity, parse_arg);
let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
let attrs = attrs + inner_attrs;
ret mk_item(p, lo, body.span.hi, t.ident,
ast::item_fn(decl, t.tps, body), attrs);
(t.ident, ast::item_fn(decl, t.tps, body), some(inner_attrs))
}
fn parse_method_name(p: parser) -> ast::ident {
@ -1834,21 +1832,19 @@ fn parse_method(p: parser, pr: ast::privacy) -> @ast::method {
self_id: p.get_id(), privacy: pr}
}
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo, ident = parse_ident(p);
fn parse_item_iface(p: parser) -> item_info {
let ident = parse_ident(p);
let rp = parse_region_param(p);
let tps = parse_ty_params(p);
let meths = parse_ty_methods(p);
ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_iface(tps, rp, meths), attrs);
(ident, ast::item_iface(tps, rp, meths), none)
}
// Parses three variants (with the region/type params always optional):
// impl /&<T: copy> of to_str for [T] { ... }
// impl name/&<T> of to_str for [T] { ... }
// impl name/&<T> for [T] { ... }
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_impl(p: parser) -> item_info {
fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty {
@{id: p.get_id(), node: ast::ty_path(pt, p.get_id()), span: pt.span}
}
@ -1882,12 +1878,10 @@ fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
let mut meths = [];
expect(p, token::LBRACE);
while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; }
ret mk_item(p, lo, p.last_span.hi, ident,
ast::item_impl(tps, rp, ifce, ty, meths), attrs);
(ident, ast::item_impl(tps, rp, ifce, ty, meths), none)
}
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_res(p: parser) -> item_info {
let ident = parse_value_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p);
@ -1897,20 +1891,17 @@ fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
let t = parse_ty(p, false);
expect(p, token::RPAREN);
let dtor = parse_block_no_value(p);
let decl =
{inputs:
[{mode: ast::expl(ast::by_ref), ty: t,
ident: arg_ident, id: p.get_id()}],
output: @{id: p.get_id(),
node: ast::ty_nil,
span: mk_sp(lo, lo)},
purity: ast::impure_fn,
cf: ast::return_val,
constraints: []};
ret mk_item(p, lo, dtor.span.hi, ident,
ast::item_res(decl, ty_params, dtor,
p.get_id(), p.get_id(), rp),
attrs);
let decl = {
inputs: [{mode: ast::expl(ast::by_ref), ty: t,
ident: arg_ident, id: p.get_id()}],
output: @{id: p.get_id(), node: ast::ty_nil,
span: ast_util::dummy_sp()},
purity: ast::impure_fn,
cf: ast::return_val,
constraints: []
};
(ident, ast::item_res(decl, ty_params, dtor,
p.get_id(), p.get_id(), rp), none)
}
// Instantiates ident <i> with references to <typarams> as arguments. Used to
@ -1946,8 +1937,7 @@ fn parse_iface_ref_list(p:parser) -> [@ast::iface_ref] {
parse_iface_ref, p)
}
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_class(p: parser) -> item_info {
let class_name = parse_value_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p);
@ -1970,13 +1960,15 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
p.bump();
alt the_ctor {
some((ct_d, ct_b, ct_s)) {
ret mk_item(p, lo, p.last_span.hi, class_name,
ast::item_class(ty_params, ifaces, ms,
{node: {id: ctor_id,
self_id: p.get_id(),
dec: ct_d,
body: ct_b},
span: ct_s}, rp), attrs); }
(class_name,
ast::item_class(ty_params, ifaces, ms, {
node: {id: ctor_id,
self_id: p.get_id(),
dec: ct_d,
body: ct_b},
span: ct_s}, rp),
none)
}
/*
Is it strange for the parser to check this?
*/
@ -2034,13 +2026,14 @@ fn parse_class_item(p:parser, class_name_with_tps: @ast::path)
}
fn parse_mod_items(p: parser, term: token::token,
first_item_attrs: [ast::attribute]) -> ast::_mod {
+first_item_attrs: [ast::attribute]) -> ast::_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 mut items: [@ast::item] = [];
let mut initial_attrs = first_item_attrs;
let mut first = true;
while p.token != term {
let attrs = initial_attrs + parse_outer_attributes(p);
let mut attrs = parse_outer_attributes(p);
if first { attrs = first_item_attrs + attrs; first = false; }
#debug["parse_mod_items: parse_item(attrs=%?)", attrs];
alt parse_item(p, attrs) {
some(i) { items += [i]; }
@ -2050,10 +2043,9 @@ fn parse_mod_items(p: parser, term: token::token,
}
}
#debug["parse_mod_items: attrs=%?", attrs];
initial_attrs = [];
}
if vec::is_not_empty(initial_attrs) {
if first && first_item_attrs.len() > 0u {
// We parsed attributes for the first item but didn't find the item
p.fatal("expected item");
}
@ -2061,31 +2053,26 @@ fn parse_mod_items(p: parser, term: token::token,
ret {view_items: view_items, items: items};
}
fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_const(p: parser) -> item_info {
let id = parse_value_ident(p);
expect(p, token::COLON);
let ty = parse_ty(p, false);
expect(p, token::EQ);
let e = parse_expr(p);
let mut hi = p.span.hi;
expect(p, token::SEMI);
ret mk_item(p, lo, hi, id, ast::item_const(ty, e), attrs);
(id, ast::item_const(ty, e), none)
}
fn parse_item_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_mod(p: parser) -> item_info {
let id = parse_ident(p);
expect(p, token::LBRACE);
let inner_attrs = parse_inner_attrs_and_next(p);
let first_item_outer_attrs = inner_attrs.next;
let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
let mut hi = p.span.hi;
let m = parse_mod_items(p, token::RBRACE, inner_attrs.next);
expect(p, token::RBRACE);
ret mk_item(p, lo, hi, id, ast::item_mod(m), attrs + inner_attrs.inner);
(id, ast::item_mod(m), some(inner_attrs.inner))
}
fn parse_item_native_fn(p: parser, attrs: [ast::attribute],
fn parse_item_native_fn(p: parser, +attrs: [ast::attribute],
purity: ast::purity) -> @ast::native_item {
let lo = p.last_span.lo;
let t = parse_fn_header(p);
@ -2109,12 +2096,12 @@ fn parse_fn_purity(p: parser) -> ast::purity {
else { unexpected(p); }
}
fn parse_native_item(p: parser, attrs: [ast::attribute]) ->
fn parse_native_item(p: parser, +attrs: [ast::attribute]) ->
@ast::native_item {
parse_item_native_fn(p, attrs, parse_fn_purity(p))
}
fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
fn parse_native_mod_items(p: parser, +first_item_attrs: [ast::attribute]) ->
ast::native_mod {
// Shouldn't be any view items since we've already parsed an item attr
let view_items =
@ -2132,18 +2119,14 @@ fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
items: items};
}
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_native_mod(p: parser) -> item_info {
expect_keyword(p, "mod");
let id = parse_ident(p);
expect(p, token::LBRACE);
let more_attrs = parse_inner_attrs_and_next(p);
let inner_attrs = more_attrs.inner;
let first_item_outer_attrs = more_attrs.next;
let m = parse_native_mod_items(p, first_item_outer_attrs);
let mut hi = p.span.hi;
let m = parse_native_mod_items(p, more_attrs.next);
expect(p, token::RBRACE);
ret mk_item(p, lo, hi, id, ast::item_native_mod(m), attrs + inner_attrs);
(id, ast::item_native_mod(m), some(more_attrs.inner))
}
fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
@ -2152,15 +2135,14 @@ fn parse_type_decl(p: parser) -> {lo: uint, ident: ast::ident} {
ret {lo: lo, ident: id};
}
fn parse_item_type(p: parser, attrs: [ast::attribute]) -> @ast::item {
fn parse_item_type(p: parser) -> item_info {
let t = parse_type_decl(p);
let rp = parse_region_param(p);
let tps = parse_ty_params(p);
expect(p, token::EQ);
let ty = parse_ty(p, false);
let mut hi = p.span.hi;
expect(p, token::SEMI);
ret mk_item(p, t.lo, hi, t.ident, ast::item_ty(ty, tps, rp), attrs);
(t.ident, ast::item_ty(ty, tps, rp), none)
}
fn parse_region_param(p: parser) -> ast::region_param {
@ -2172,8 +2154,7 @@ fn parse_region_param(p: parser) -> ast::region_param {
}
}
fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo;
fn parse_item_enum(p: parser) -> item_info {
let id = parse_ident(p);
let rp = parse_region_param(p);
let ty_params = parse_ty_params(p);
@ -2191,8 +2172,7 @@ fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
args: [{ty: ty, id: p.get_id()}],
id: p.get_id(),
disr_expr: none});
ret mk_item(p, lo, ty.span.hi, id,
ast::item_enum([variant], ty_params, rp), attrs);
ret (id, ast::item_enum([variant], ty_params, rp), none);
}
expect(p, token::LBRACE);
@ -2227,8 +2207,7 @@ fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
if (have_disr && !all_nullary) {
p.fatal("discriminator values can only be used with a c-like enum");
}
ret mk_item(p, lo, p.last_span.hi, id,
ast::item_enum(variants, ty_params, rp), attrs);
(id, ast::item_enum(variants, ty_params, rp), none)
}
fn parse_fn_ty_proto(p: parser) -> ast::proto {
@ -2262,40 +2241,44 @@ fn fn_expr_lookahead(tok: token::token) -> bool {
}
}
fn parse_item(p: parser, attrs: [ast::attribute]) -> option<@ast::item> {
if eat_keyword(p, "const") {
ret some(parse_item_const(p, attrs));
fn parse_item(p: parser, +attrs: [ast::attribute]) -> option<@ast::item> {
let lo = p.span.lo;
let (ident, item_, extra_attrs) = if eat_keyword(p, "const") {
parse_item_const(p)
} else if is_keyword(p, "fn") && !fn_expr_lookahead(p.look_ahead(1u)) {
p.bump();
ret some(parse_item_fn(p, ast::impure_fn, attrs));
parse_item_fn(p, ast::impure_fn)
} else if eat_keyword(p, "pure") {
expect_keyword(p, "fn");
ret some(parse_item_fn(p, ast::pure_fn, attrs));
parse_item_fn(p, ast::pure_fn)
} else if is_keyword(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
p.bump();
expect_keyword(p, "fn");
ret some(parse_item_fn(p, ast::unsafe_fn, attrs));
parse_item_fn(p, ast::unsafe_fn)
} else if eat_keyword(p, "crust") {
expect_keyword(p, "fn");
ret some(parse_item_fn(p, ast::crust_fn, attrs));
parse_item_fn(p, ast::crust_fn)
} else if eat_keyword(p, "mod") {
ret some(parse_item_mod(p, attrs));
parse_item_mod(p)
} else if eat_keyword(p, "native") {
ret some(parse_item_native_mod(p, attrs));
} if eat_keyword(p, "type") {
ret some(parse_item_type(p, attrs));
parse_item_native_mod(p)
} else if eat_keyword(p, "type") {
parse_item_type(p)
} else if eat_keyword(p, "enum") {
ret some(parse_item_enum(p, attrs));
parse_item_enum(p)
} else if eat_keyword(p, "iface") {
ret some(parse_item_iface(p, attrs));
parse_item_iface(p)
} else if eat_keyword(p, "impl") {
ret some(parse_item_impl(p, attrs));
parse_item_impl(p)
} else if eat_keyword(p, "resource") {
ret some(parse_item_res(p, attrs));
parse_item_res(p)
} else if eat_keyword(p, "class") {
ret some(parse_item_class(p, attrs));
}
else { ret none; }
parse_item_class(p)
} else { ret none; };
some(mk_item(p, lo, p.last_span.hi, ident, item_, alt extra_attrs {
some(as) { attrs + as }
none { attrs }
}))
}
fn parse_use(p: parser) -> ast::view_item_ {