1
Fork 0

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}); 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)}; 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)}; 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]) { fn check_expected_item(p: parser, current_attrs: [ast::attribute]) {
// If we have attributes then we should have an item // If we have attributes then we should have an item
if vec::is_not_empty(current_attrs) { 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, 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 stmts = [];
let mut expr = none; let mut expr = none;
let view_items = maybe_parse_view_import_only(p, first_item_attrs); 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}; ret {ident: id, tps: ty_params};
} }
fn mk_item(p: parser, lo: uint, hi: uint, ident: ast::ident, node: ast::item_, fn mk_item(p: parser, lo: uint, hi: uint, +ident: ast::ident,
attrs: [ast::attribute]) -> @ast::item { +node: ast::item_, +attrs: [ast::attribute]) -> @ast::item {
ret @{ident: ident, ret @{ident: ident,
attrs: attrs, attrs: attrs,
id: p.get_id(), 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)}; span: mk_sp(lo, hi)};
} }
fn parse_item_fn(p: parser, purity: ast::purity, type item_info = (ast::ident, ast::item_, option<[ast::attribute]>);
attrs: [ast::attribute]) -> @ast::item {
let lo = p.last_span.lo; fn parse_item_fn(p: parser, purity: ast::purity) -> item_info {
let t = parse_fn_header(p); let t = parse_fn_header(p);
let (decl, _) = parse_fn_decl(p, purity, parse_arg); let (decl, _) = parse_fn_decl(p, purity, parse_arg);
let (inner_attrs, body) = parse_inner_attrs_and_block(p, true); let (inner_attrs, body) = parse_inner_attrs_and_block(p, true);
let attrs = attrs + inner_attrs; (t.ident, ast::item_fn(decl, t.tps, body), some(inner_attrs))
ret mk_item(p, lo, body.span.hi, t.ident,
ast::item_fn(decl, t.tps, body), attrs);
} }
fn parse_method_name(p: parser) -> ast::ident { 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} self_id: p.get_id(), privacy: pr}
} }
fn parse_item_iface(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_iface(p: parser) -> item_info {
let lo = p.last_span.lo, ident = parse_ident(p); let ident = parse_ident(p);
let rp = parse_region_param(p); let rp = parse_region_param(p);
let tps = parse_ty_params(p); let tps = parse_ty_params(p);
let meths = parse_ty_methods(p); let meths = parse_ty_methods(p);
ret mk_item(p, lo, p.last_span.hi, ident, (ident, ast::item_iface(tps, rp, meths), none)
ast::item_iface(tps, rp, meths), attrs);
} }
// Parses three variants (with the region/type params always optional): // Parses three variants (with the region/type params always optional):
// impl /&<T: copy> of to_str for [T] { ... } // impl /&<T: copy> of to_str for [T] { ... }
// impl name/&<T> of to_str for [T] { ... } // impl name/&<T> of to_str for [T] { ... }
// impl name/&<T> for [T] { ... } // impl name/&<T> for [T] { ... }
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_impl(p: parser) -> item_info {
let lo = p.last_span.lo;
fn wrap_path(p: parser, pt: @ast::path) -> @ast::ty { 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} @{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 = []; let mut meths = [];
expect(p, token::LBRACE); expect(p, token::LBRACE);
while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; } while !eat(p, token::RBRACE) { meths += [parse_method(p, ast::pub)]; }
ret mk_item(p, lo, p.last_span.hi, ident, (ident, ast::item_impl(tps, rp, ifce, ty, meths), none)
ast::item_impl(tps, rp, ifce, ty, meths), attrs);
} }
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_res(p: parser) -> item_info {
let lo = p.last_span.lo;
let ident = parse_value_ident(p); let ident = parse_value_ident(p);
let rp = parse_region_param(p); let rp = parse_region_param(p);
let ty_params = parse_ty_params(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); let t = parse_ty(p, false);
expect(p, token::RPAREN); expect(p, token::RPAREN);
let dtor = parse_block_no_value(p); let dtor = parse_block_no_value(p);
let decl = let decl = {
{inputs: inputs: [{mode: ast::expl(ast::by_ref), ty: t,
[{mode: ast::expl(ast::by_ref), ty: t, ident: arg_ident, id: p.get_id()}],
ident: arg_ident, id: p.get_id()}], output: @{id: p.get_id(), node: ast::ty_nil,
output: @{id: p.get_id(), span: ast_util::dummy_sp()},
node: ast::ty_nil, purity: ast::impure_fn,
span: mk_sp(lo, lo)}, cf: ast::return_val,
purity: ast::impure_fn, constraints: []
cf: ast::return_val, };
constraints: []}; (ident, ast::item_res(decl, ty_params, dtor,
ret mk_item(p, lo, dtor.span.hi, ident, p.get_id(), p.get_id(), rp), none)
ast::item_res(decl, ty_params, dtor,
p.get_id(), p.get_id(), rp),
attrs);
} }
// Instantiates ident <i> with references to <typarams> as arguments. Used to // 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) parse_iface_ref, p)
} }
fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_class(p: parser) -> item_info {
let lo = p.last_span.lo;
let class_name = parse_value_ident(p); let class_name = parse_value_ident(p);
let rp = parse_region_param(p); let rp = parse_region_param(p);
let ty_params = parse_ty_params(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(); p.bump();
alt the_ctor { alt the_ctor {
some((ct_d, ct_b, ct_s)) { some((ct_d, ct_b, ct_s)) {
ret mk_item(p, lo, p.last_span.hi, class_name, (class_name,
ast::item_class(ty_params, ifaces, ms, ast::item_class(ty_params, ifaces, ms, {
{node: {id: ctor_id, node: {id: ctor_id,
self_id: p.get_id(), self_id: p.get_id(),
dec: ct_d, dec: ct_d,
body: ct_b}, body: ct_b},
span: ct_s}, rp), attrs); } span: ct_s}, rp),
none)
}
/* /*
Is it strange for the parser to check this? 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, 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 // 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 view_items = maybe_parse_view(p, first_item_attrs);
let mut items: [@ast::item] = []; let mut items: [@ast::item] = [];
let mut initial_attrs = first_item_attrs; let mut first = true;
while p.token != term { 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]; #debug["parse_mod_items: parse_item(attrs=%?)", attrs];
alt parse_item(p, attrs) { alt parse_item(p, attrs) {
some(i) { items += [i]; } some(i) { items += [i]; }
@ -2050,10 +2043,9 @@ fn parse_mod_items(p: parser, term: token::token,
} }
} }
#debug["parse_mod_items: attrs=%?", attrs]; #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 // We parsed attributes for the first item but didn't find the item
p.fatal("expected 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}; ret {view_items: view_items, items: items};
} }
fn parse_item_const(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_const(p: parser) -> item_info {
let lo = p.last_span.lo;
let id = parse_value_ident(p); let id = parse_value_ident(p);
expect(p, token::COLON); expect(p, token::COLON);
let ty = parse_ty(p, false); let ty = parse_ty(p, false);
expect(p, token::EQ); expect(p, token::EQ);
let e = parse_expr(p); let e = parse_expr(p);
let mut hi = p.span.hi;
expect(p, token::SEMI); 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 { fn parse_item_mod(p: parser) -> item_info {
let lo = p.last_span.lo;
let id = parse_ident(p); let id = parse_ident(p);
expect(p, token::LBRACE); expect(p, token::LBRACE);
let inner_attrs = parse_inner_attrs_and_next(p); 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, inner_attrs.next);
let m = parse_mod_items(p, token::RBRACE, first_item_outer_attrs);
let mut hi = p.span.hi;
expect(p, token::RBRACE); 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 { purity: ast::purity) -> @ast::native_item {
let lo = p.last_span.lo; let lo = p.last_span.lo;
let t = parse_fn_header(p); let t = parse_fn_header(p);
@ -2109,12 +2096,12 @@ fn parse_fn_purity(p: parser) -> ast::purity {
else { unexpected(p); } else { unexpected(p); }
} }
fn parse_native_item(p: parser, attrs: [ast::attribute]) -> fn parse_native_item(p: parser, +attrs: [ast::attribute]) ->
@ast::native_item { @ast::native_item {
parse_item_native_fn(p, attrs, parse_fn_purity(p)) 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 { ast::native_mod {
// Shouldn't be any view items since we've already parsed an item attr // Shouldn't be any view items since we've already parsed an item attr
let view_items = let view_items =
@ -2132,18 +2119,14 @@ fn parse_native_mod_items(p: parser, first_item_attrs: [ast::attribute]) ->
items: items}; items: items};
} }
fn parse_item_native_mod(p: parser, attrs: [ast::attribute]) -> @ast::item { fn parse_item_native_mod(p: parser) -> item_info {
let lo = p.last_span.lo;
expect_keyword(p, "mod"); expect_keyword(p, "mod");
let id = parse_ident(p); let id = parse_ident(p);
expect(p, token::LBRACE); expect(p, token::LBRACE);
let more_attrs = parse_inner_attrs_and_next(p); let more_attrs = parse_inner_attrs_and_next(p);
let inner_attrs = more_attrs.inner; let m = parse_native_mod_items(p, more_attrs.next);
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;
expect(p, token::RBRACE); 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} { 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}; 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 t = parse_type_decl(p);
let rp = parse_region_param(p); let rp = parse_region_param(p);
let tps = parse_ty_params(p); let tps = parse_ty_params(p);
expect(p, token::EQ); expect(p, token::EQ);
let ty = parse_ty(p, false); let ty = parse_ty(p, false);
let mut hi = p.span.hi;
expect(p, token::SEMI); 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 { 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 { fn parse_item_enum(p: parser) -> item_info {
let lo = p.last_span.lo;
let id = parse_ident(p); let id = parse_ident(p);
let rp = parse_region_param(p); let rp = parse_region_param(p);
let ty_params = parse_ty_params(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()}], args: [{ty: ty, id: p.get_id()}],
id: p.get_id(), id: p.get_id(),
disr_expr: none}); disr_expr: none});
ret mk_item(p, lo, ty.span.hi, id, ret (id, ast::item_enum([variant], ty_params, rp), none);
ast::item_enum([variant], ty_params, rp), attrs);
} }
expect(p, token::LBRACE); expect(p, token::LBRACE);
@ -2227,8 +2207,7 @@ fn parse_item_enum(p: parser, attrs: [ast::attribute]) -> @ast::item {
if (have_disr && !all_nullary) { if (have_disr && !all_nullary) {
p.fatal("discriminator values can only be used with a c-like enum"); p.fatal("discriminator values can only be used with a c-like enum");
} }
ret mk_item(p, lo, p.last_span.hi, id, (id, ast::item_enum(variants, ty_params, rp), none)
ast::item_enum(variants, ty_params, rp), attrs);
} }
fn parse_fn_ty_proto(p: parser) -> ast::proto { 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> { fn parse_item(p: parser, +attrs: [ast::attribute]) -> option<@ast::item> {
if eat_keyword(p, "const") { let lo = p.span.lo;
ret some(parse_item_const(p, attrs)); 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)) { } else if is_keyword(p, "fn") && !fn_expr_lookahead(p.look_ahead(1u)) {
p.bump(); 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") { } else if eat_keyword(p, "pure") {
expect_keyword(p, "fn"); 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 { } else if is_keyword(p, "unsafe") && p.look_ahead(1u) != token::LBRACE {
p.bump(); p.bump();
expect_keyword(p, "fn"); 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") { } else if eat_keyword(p, "crust") {
expect_keyword(p, "fn"); 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") { } else if eat_keyword(p, "mod") {
ret some(parse_item_mod(p, attrs)); parse_item_mod(p)
} else if eat_keyword(p, "native") { } else if eat_keyword(p, "native") {
ret some(parse_item_native_mod(p, attrs)); parse_item_native_mod(p)
} if eat_keyword(p, "type") { } else if eat_keyword(p, "type") {
ret some(parse_item_type(p, attrs)); parse_item_type(p)
} else if eat_keyword(p, "enum") { } else if eat_keyword(p, "enum") {
ret some(parse_item_enum(p, attrs)); parse_item_enum(p)
} else if eat_keyword(p, "iface") { } else if eat_keyword(p, "iface") {
ret some(parse_item_iface(p, attrs)); parse_item_iface(p)
} else if eat_keyword(p, "impl") { } else if eat_keyword(p, "impl") {
ret some(parse_item_impl(p, attrs)); parse_item_impl(p)
} else if eat_keyword(p, "resource") { } else if eat_keyword(p, "resource") {
ret some(parse_item_res(p, attrs)); parse_item_res(p)
} else if eat_keyword(p, "class") { } else if eat_keyword(p, "class") {
ret some(parse_item_class(p, attrs)); parse_item_class(p)
} } else { ret none; };
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_ { fn parse_use(p: parser) -> ast::view_item_ {