提交 a936f78d 编写于 作者: H Haitao Li 提交者: Brian Anderson

rustc: Allow trailing comma in record fields

上级 901b9adb
...@@ -290,7 +290,7 @@ fn parse_fn_input_ty(p: parser) -> ast::ty_arg { ...@@ -290,7 +290,7 @@ fn parse_fn_input_ty(p: parser) -> ast::ty_arg {
ret spanned(lo, t.span.hi, {mode: mode, ty: t}); ret spanned(lo, t.span.hi, {mode: mode, ty: t});
} }
let inputs = let inputs =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_fn_input_ty, p); parse_fn_input_ty, p);
// FIXME: there's no syntax for this right now anyway // FIXME: there's no syntax for this right now anyway
// auto constrs = parse_constrs(~[], p); // auto constrs = parse_constrs(~[], p);
...@@ -319,7 +319,8 @@ fn parse_method_sig(p: parser) -> ast::ty_method { ...@@ -319,7 +319,8 @@ fn parse_method_sig(p: parser) -> ast::ty_method {
} }
} }
let meths = let meths =
parse_seq(token::LBRACE, token::RBRACE, none, parse_method_sig, p); parse_seq(token::LBRACE, token::RBRACE, seq_sep_none(),
parse_method_sig, p);
ret ast::ty_obj(meths.node); ret ast::ty_obj(meths.node);
} }
...@@ -376,7 +377,7 @@ fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr { ...@@ -376,7 +377,7 @@ fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
let lo = p.get_lo_pos(); let lo = p.get_lo_pos();
let path = parse_path(p); let path = parse_path(p);
let args: {node: [@ast::constr_arg], span: span} = let args: {node: [@ast::constr_arg], span: span} =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
{|p| parse_constr_arg(fn_args, p)}, p); {|p| parse_constr_arg(fn_args, p)}, p);
ret @spanned(lo, args.span.hi, ret @spanned(lo, args.span.hi,
{path: path, args: args.node, id: p.get_id()}); {path: path, args: args.node, id: p.get_id()});
...@@ -386,7 +387,7 @@ fn parse_constr_in_type(p: parser) -> @ast::ty_constr { ...@@ -386,7 +387,7 @@ fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
let lo = p.get_lo_pos(); let lo = p.get_lo_pos();
let path = parse_path(p); let path = parse_path(p);
let args: [@ast::ty_constr_arg] = let args: [@ast::ty_constr_arg] =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_type_constr_arg, p).node; parse_type_constr_arg, p).node;
let hi = p.get_lo_pos(); let hi = p.get_lo_pos();
let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()}; let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
...@@ -540,7 +541,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty { ...@@ -540,7 +541,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
t = ast::ty_ptr(parse_mt(p)); t = ast::ty_ptr(parse_mt(p));
} else if p.peek() == token::LBRACE { } else if p.peek() == token::LBRACE {
let elems = let elems =
parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA), parse_seq(token::LBRACE, token::RBRACE, seq_sep_opt(token::COMMA),
parse_ty_field, p); parse_ty_field, p);
let hi = elems.span.hi; let hi = elems.span.hi;
t = ast::ty_rec(elems.node); t = ast::ty_rec(elems.node);
...@@ -631,23 +632,39 @@ fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>, ...@@ -631,23 +632,39 @@ fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>,
ret spanned(lo, hi, result); ret spanned(lo, hi, result);
} }
fn parse_seq_to_end<copy T>(ket: token::token, sep: option::t<token::token>, fn parse_seq_to_end<copy T>(ket: token::token, sep: seq_sep,
f: block(parser) -> T, p: parser) -> [T] { f: block(parser) -> T, p: parser) -> [T] {
let val = parse_seq_to_before_end(ket, sep, f, p); let val = parse_seq_to_before_end(ket, sep, f, p);
p.bump(); p.bump();
ret val; ret val;
} }
type seq_sep = {
sep: option::t<token::token>,
trailing_opt: bool // is trailing separator optional?
};
fn seq_sep(t: token::token) -> seq_sep {
ret {sep: option::some(t), trailing_opt: false};
}
fn seq_sep_opt(t: token::token) -> seq_sep {
ret {sep: option::some(t), trailing_opt: true};
}
fn seq_sep_none() -> seq_sep {
ret {sep: option::none, trailing_opt: false};
}
fn parse_seq_to_before_end<copy T>(ket: token::token, fn parse_seq_to_before_end<copy T>(ket: token::token,
sep: option::t<token::token>, sep: seq_sep,
f: block(parser) -> T, p: parser) -> [T] { f: block(parser) -> T, p: parser) -> [T] {
let first: bool = true; let first: bool = true;
let v: [T] = []; let v: [T] = [];
while p.peek() != ket { while p.peek() != ket {
alt sep { alt sep.sep {
some(t) { if first { first = false; } else { expect(p, t); } } some(t) { if first { first = false; } else { expect(p, t); } }
_ { } _ { }
} }
if sep.trailing_opt && p.peek() == ket { break; }
v += [f(p)]; v += [f(p)];
} }
ret v; ret v;
...@@ -655,7 +672,7 @@ fn parse_seq_to_before_end<copy T>(ket: token::token, ...@@ -655,7 +672,7 @@ fn parse_seq_to_before_end<copy T>(ket: token::token,
fn parse_seq<copy T>(bra: token::token, ket: token::token, fn parse_seq<copy T>(bra: token::token, ket: token::token,
sep: option::t<token::token>, f: block(parser) -> T, sep: seq_sep, f: block(parser) -> T,
p: parser) -> spanned<[T]> { p: parser) -> spanned<[T]> {
let lo = p.get_lo_pos(); let lo = p.get_lo_pos();
expect(p, bra); expect(p, bra);
...@@ -810,6 +827,10 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ...@@ -810,6 +827,10 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
while p.peek() != token::RBRACE { while p.peek() != token::RBRACE {
if eat_word(p, "with") { base = some(parse_expr(p)); break; } if eat_word(p, "with") { base = some(parse_expr(p)); break; }
expect(p, token::COMMA); expect(p, token::COMMA);
if p.peek() == token::RBRACE {
// record ends by an optional trailing comma
break;
}
fields += [parse_field(p, token::COLON)]; fields += [parse_field(p, token::COLON)];
} }
hi = p.get_hi_pos(); hi = p.get_hi_pos();
...@@ -850,8 +871,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ...@@ -850,8 +871,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
p.bump(); p.bump();
let mut = parse_mutability(p); let mut = parse_mutability(p);
let es = let es =
parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr, parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
p); parse_expr, p);
ex = ast::expr_vec(es, mut); ex = ast::expr_vec(es, mut);
} else if p.peek() == token::POUND_LT { } else if p.peek() == token::POUND_LT {
p.bump(); p.bump();
...@@ -876,7 +897,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ...@@ -876,7 +897,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
if p.peek() == token::LPAREN { if p.peek() == token::LPAREN {
p.bump(); p.bump();
fields = fields =
some(parse_seq_to_end(token::RPAREN, some(token::COMMA), some(parse_seq_to_end(token::RPAREN, seq_sep(token::COMMA),
parse_anon_obj_field, p)); parse_anon_obj_field, p));
} }
let meths: [@ast::method] = []; let meths: [@ast::method] = [];
...@@ -906,7 +927,7 @@ fn parse_expr_opt(p: parser) -> option::t<@ast::expr> { ...@@ -906,7 +927,7 @@ fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
} }
} }
let es = let es =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_expr_opt, p); parse_expr_opt, p);
hi = es.span.hi; hi = es.span.hi;
ex = ast::expr_bind(e, es.node); ex = ast::expr_bind(e, es.node);
...@@ -977,7 +998,7 @@ fn parse_expr_opt(p: parser) -> option::t<@ast::expr> { ...@@ -977,7 +998,7 @@ fn parse_expr_opt(p: parser) -> option::t<@ast::expr> {
// The rest is a call expression. // The rest is a call expression.
let f: @ast::expr = parse_self_method(p); let f: @ast::expr = parse_self_method(p);
let es = let es =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_expr, p); parse_expr, p);
hi = es.span.hi; hi = es.span.hi;
ex = ast::expr_call(f, es.node, false); ex = ast::expr_call(f, es.node, false);
...@@ -1016,13 +1037,12 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr { ...@@ -1016,13 +1037,12 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
p.fatal("expected a syntax expander name"); p.fatal("expected a syntax expander name");
} }
//temporary for a backwards-compatible cycle: //temporary for a backwards-compatible cycle:
let sep = seq_sep(token::COMMA);
let es = let es =
if p.peek() == token::LPAREN { if p.peek() == token::LPAREN {
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
parse_expr, p)
} else { } else {
parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA), parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
parse_expr, p)
}; };
let hi = es.span.hi; let hi = es.span.hi;
let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm)); let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
...@@ -1053,7 +1073,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr { ...@@ -1053,7 +1073,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
} else { } else {
// Call expr. // Call expr.
let es = parse_seq(token::LPAREN, token::RPAREN, let es = parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA), parse_expr, p); seq_sep(token::COMMA), parse_expr, p);
hi = es.span.hi; hi = es.span.hi;
let nd = ast::expr_call(e, es.node, false); let nd = ast::expr_call(e, es.node, false);
e = mk_expr(p, lo, hi, nd); e = mk_expr(p, lo, hi, nd);
...@@ -1508,7 +1528,7 @@ fn parse_pat(p: parser) -> @ast::pat { ...@@ -1508,7 +1528,7 @@ fn parse_pat(p: parser) -> @ast::pat {
token::LPAREN. { token::LPAREN. {
let a = let a =
parse_seq(token::LPAREN, token::RPAREN, parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA), parse_pat, p); seq_sep(token::COMMA), parse_pat, p);
args = a.node; args = a.node;
hi = a.span.hi; hi = a.span.hi;
} }
...@@ -1761,8 +1781,8 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] { ...@@ -1761,8 +1781,8 @@ fn parse_ty_params(p: parser) -> [ast::ty_param] {
fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) -> fn parse_fn_decl(p: parser, purity: ast::purity, il: ast::inlineness) ->
ast::fn_decl { ast::fn_decl {
let inputs: ast::spanned<[ast::arg]> = let inputs: ast::spanned<[ast::arg]> =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg, parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
p); parse_arg, p);
// Use the args list to translate each bound variable // Use the args list to translate each bound variable
// mentioned in a constraint to an arg index. // mentioned in a constraint to an arg index.
// Seems weird to do this in the parser, but I'm not sure how else to. // Seems weird to do this in the parser, but I'm not sure how else to.
...@@ -1787,7 +1807,7 @@ fn parse_fn_block_decl(p: parser) -> ast::fn_decl { ...@@ -1787,7 +1807,7 @@ fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
[] []
} else { } else {
parse_seq(token::BINOP(token::OR), token::BINOP(token::OR), parse_seq(token::BINOP(token::OR), token::BINOP(token::OR),
some(token::COMMA), parse_fn_block_arg, p).node seq_sep(token::COMMA), parse_fn_block_arg, p).node
}; };
ret {inputs: inputs, ret {inputs: inputs,
output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer), output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
...@@ -1861,7 +1881,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item { ...@@ -1861,7 +1881,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
let ident = parse_value_ident(p); let ident = parse_value_ident(p);
let ty_params = parse_ty_params(p); let ty_params = parse_ty_params(p);
let fields: ast::spanned<[ast::obj_field]> = let fields: ast::spanned<[ast::obj_field]> =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_obj_field, p); parse_obj_field, p);
let meths: [@ast::method] = []; let meths: [@ast::method] = [];
expect(p, token::LBRACE); expect(p, token::LBRACE);
...@@ -2066,7 +2086,7 @@ fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item { ...@@ -2066,7 +2086,7 @@ fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
alt p.peek() { alt p.peek() {
token::LPAREN. { token::LPAREN. {
let arg_tys = parse_seq(token::LPAREN, token::RPAREN, let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA), seq_sep(token::COMMA),
{|p| parse_ty(p, false)}, p); {|p| parse_ty(p, false)}, p);
for ty: @ast::ty in arg_tys.node { for ty: @ast::ty in arg_tys.node {
args += [{ty: ty, id: p.get_id()}]; args += [{ty: ty, id: p.get_id()}];
...@@ -2258,7 +2278,7 @@ fn parse_meta_item(p: parser) -> @ast::meta_item { ...@@ -2258,7 +2278,7 @@ fn parse_meta_item(p: parser) -> @ast::meta_item {
} }
fn parse_meta_seq(p: parser) -> [@ast::meta_item] { fn parse_meta_seq(p: parser) -> [@ast::meta_item] {
ret parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), ret parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_meta_item, p).node; parse_meta_item, p).node;
} }
...@@ -2315,7 +2335,7 @@ fn parse_import_ident(p: parser) -> ast::import_ident { ...@@ -2315,7 +2335,7 @@ fn parse_import_ident(p: parser) -> ast::import_ident {
ret spanned(lo, hi, {name: ident, id: p.get_id()}); ret spanned(lo, hi, {name: ident, id: p.get_id()});
} }
let from_idents_ = let from_idents_ =
parse_seq(token::LBRACE, token::RBRACE, some(token::COMMA), parse_seq(token::LBRACE, token::RBRACE, seq_sep(token::COMMA),
parse_import_ident, p).node; parse_import_ident, p).node;
if vec::is_empty(from_idents_) { if vec::is_empty(from_idents_) {
p.fatal("at least one import is required"); p.fatal("at least one import is required");
...@@ -2385,7 +2405,7 @@ fn parse_import(p: parser) -> ast::view_item_ { ...@@ -2385,7 +2405,7 @@ fn parse_import(p: parser) -> ast::view_item_ {
fn parse_export(p: parser) -> ast::view_item_ { fn parse_export(p: parser) -> ast::view_item_ {
let ids = let ids =
parse_seq_to_before_end(token::SEMI, option::some(token::COMMA), parse_seq_to_before_end(token::SEMI, seq_sep(token::COMMA),
parse_ident, p); parse_ident, p);
ret ast::view_item_export(ids, p.get_id()); ret ast::view_item_export(ids, p.get_id());
} }
......
...@@ -294,7 +294,7 @@ fn print_field(s: ps, f: ast::ty_field) { ...@@ -294,7 +294,7 @@ fn print_field(s: ps, f: ast::ty_field) {
} }
fn get_span(f: ast::ty_field) -> codemap::span { ret f.span; } fn get_span(f: ast::ty_field) -> codemap::span { ret f.span; }
commasep_cmnt(s, consistent, fields, print_field, get_span); commasep_cmnt(s, consistent, fields, print_field, get_span);
word(s.s, "}"); word(s.s, ",}");
} }
ast::ty_tup(elts) { ast::ty_tup(elts) {
popen(s); popen(s);
...@@ -693,7 +693,7 @@ fn print_field(s: ps, field: ast::field) { ...@@ -693,7 +693,7 @@ fn print_field(s: ps, field: ast::field) {
print_expr(s, expr); print_expr(s, expr);
end(s); end(s);
} }
_ { } _ { word(s.s, ","); }
} }
word(s.s, "}"); word(s.s, "}");
} }
......
// pp-exact
type thing = {x: int, y: int,};
fn main() {
let sth = {x: 0, y: 1,};
let sth2 = {y: 9 with sth};
assert (sth.x + sth2.y == 9);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册