Skip to content

rustc: Allow trailing comma in record fields #1207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 48 additions & 28 deletions src/comp/syntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
ret spanned(lo, t.span.hi, {mode: mode, ty: t});
}
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);
// FIXME: there's no syntax for this right now anyway
// auto constrs = parse_constrs(~[], p);
Expand Down Expand Up @@ -319,7 +319,8 @@ fn parse_ty_obj(p: parser) -> ast::ty_ {
}
}
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);
}

Expand Down Expand Up @@ -376,7 +377,7 @@ fn parse_ty_constr(fn_args: [ast::arg], p: parser) -> @ast::constr {
let lo = p.get_lo_pos();
let path = parse_path(p);
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);
ret @spanned(lo, args.span.hi,
{path: path, args: args.node, id: p.get_id()});
Expand All @@ -386,7 +387,7 @@ fn parse_constr_in_type(p: parser) -> @ast::ty_constr {
let lo = p.get_lo_pos();
let path = parse_path(p);
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;
let hi = p.get_lo_pos();
let tc: ast::ty_constr_ = {path: path, args: args, id: p.get_id()};
Expand Down Expand Up @@ -540,7 +541,7 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
t = ast::ty_ptr(parse_mt(p));
} else if p.peek() == token::LBRACE {
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);
let hi = elems.span.hi;
t = ast::ty_rec(elems.node);
Expand Down Expand Up @@ -631,31 +632,47 @@ fn parse_seq_lt_gt<copy T>(sep: option::t<token::token>,
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] {
let val = parse_seq_to_before_end(ket, sep, f, p);
p.bump();
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,
sep: option::t<token::token>,
sep: seq_sep,
f: block(parser) -> T, p: parser) -> [T] {
let first: bool = true;
let v: [T] = [];
while p.peek() != ket {
alt sep {
alt sep.sep {
some(t) { if first { first = false; } else { expect(p, t); } }
_ { }
}
if sep.trailing_opt && p.peek() == ket { break; }
v += [f(p)];
}
ret v;
}


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]> {
let lo = p.get_lo_pos();
expect(p, bra);
Expand Down Expand Up @@ -810,6 +827,10 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
while p.peek() != token::RBRACE {
if eat_word(p, "with") { base = some(parse_expr(p)); break; }
expect(p, token::COMMA);
if p.peek() == token::RBRACE {
// record ends by an optional trailing comma
break;
}
fields += [parse_field(p, token::COLON)];
}
hi = p.get_hi_pos();
Expand Down Expand Up @@ -850,8 +871,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
p.bump();
let mut = parse_mutability(p);
let es =
parse_seq_to_end(token::RBRACKET, some(token::COMMA), parse_expr,
p);
parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
parse_expr, p);
ex = ast::expr_vec(es, mut);
} else if p.peek() == token::POUND_LT {
p.bump();
Expand All @@ -876,7 +897,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
if p.peek() == token::LPAREN {
p.bump();
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));
}
let meths: [@ast::method] = [];
Expand Down Expand Up @@ -906,7 +927,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
}
}
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);
hi = es.span.hi;
ex = ast::expr_bind(e, es.node);
Expand Down Expand Up @@ -977,7 +998,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
// The rest is a call expression.
let f: @ast::expr = parse_self_method(p);
let es =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_expr, p);
hi = es.span.hi;
ex = ast::expr_call(f, es.node, false);
Expand Down Expand Up @@ -1016,13 +1037,12 @@ fn parse_syntax_ext_naked(p: parser, lo: uint) -> @ast::expr {
p.fatal("expected a syntax expander name");
}
//temporary for a backwards-compatible cycle:
let sep = seq_sep(token::COMMA);
let es =
if p.peek() == token::LPAREN {
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA),
parse_expr, p)
parse_seq(token::LPAREN, token::RPAREN, sep, parse_expr, p)
} else {
parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA),
parse_expr, p)
parse_seq(token::LBRACKET, token::RBRACKET, sep, parse_expr, p)
};
let hi = es.span.hi;
let e = mk_expr(p, es.span.lo, hi, ast::expr_vec(es.node, ast::imm));
Expand Down Expand Up @@ -1053,7 +1073,7 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
} else {
// Call expr.
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;
let nd = ast::expr_call(e, es.node, false);
e = mk_expr(p, lo, hi, nd);
Expand Down Expand Up @@ -1508,7 +1528,7 @@ fn parse_pat(p: parser) -> @ast::pat {
token::LPAREN. {
let a =
parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA), parse_pat, p);
seq_sep(token::COMMA), parse_pat, p);
args = a.node;
hi = a.span.hi;
}
Expand Down Expand Up @@ -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) ->
ast::fn_decl {
let inputs: ast::spanned<[ast::arg]> =
parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_arg,
p);
parse_seq(token::LPAREN, token::RPAREN, seq_sep(token::COMMA),
parse_arg, p);
// Use the args list to translate each bound variable
// mentioned in a constraint to an arg index.
// Seems weird to do this in the parser, but I'm not sure how else to.
Expand All @@ -1787,7 +1807,7 @@ fn parse_fn_block_decl(p: parser) -> ast::fn_decl {
[]
} else {
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,
output: @spanned(p.get_lo_pos(), p.get_hi_pos(), ast::ty_infer),
Expand Down Expand Up @@ -1861,7 +1881,7 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
let ident = parse_value_ident(p);
let ty_params = parse_ty_params(p);
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);
let meths: [@ast::method] = [];
expect(p, token::LBRACE);
Expand Down Expand Up @@ -2063,7 +2083,7 @@ fn parse_item_tag(p: parser, attrs: [ast::attribute]) -> @ast::item {
alt p.peek() {
token::LPAREN. {
let arg_tys = parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA),
seq_sep(token::COMMA),
{|p| parse_ty(p, false)}, p);
for ty: @ast::ty in arg_tys.node {
args += [{ty: ty, id: p.get_id()}];
Expand Down Expand Up @@ -2255,7 +2275,7 @@ fn parse_meta_item(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;
}

Expand Down Expand Up @@ -2312,7 +2332,7 @@ fn parse_rest_import_name(p: parser, first: ast::ident,
ret spanned(lo, hi, {name: ident, id: p.get_id()});
}
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;
if vec::is_empty(from_idents_) {
p.fatal("at least one import is required");
Expand Down Expand Up @@ -2382,7 +2402,7 @@ fn parse_import(p: parser) -> ast::view_item_ {

fn parse_export(p: parser) -> ast::view_item_ {
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);
ret ast::view_item_export(ids, p.get_id());
}
Expand Down
4 changes: 2 additions & 2 deletions src/comp/syntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn print_type(s: ps, &&ty: @ast::ty) {
}
fn get_span(f: ast::ty_field) -> codemap::span { ret f.span; }
commasep_cmnt(s, consistent, fields, print_field, get_span);
word(s.s, "}");
word(s.s, ",}");
}
ast::ty_tup(elts) {
popen(s);
Expand Down Expand Up @@ -693,7 +693,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
print_expr(s, expr);
end(s);
}
_ { }
_ { word(s.s, ","); }
}
word(s.s, "}");
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/pretty/record-trailing-comma.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 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);
}