authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-17 10:35:22-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-17 10:35:22-04:00
log76344a6fc4ec9ca2e47e195568798f9076afea33
treeac1aff8f36ab82ff6e13cfab2780e286e5ebeb0e
parent1566ca21c4bbe7f5aa5f385c7ebc22c780e54c8f
parent1a63f2724729a08e4f82d218542c60035aa91ce0

Merge branch 'trailing-commas'


3 files changed, 133 insertions(+), 27 deletions(-)

src/parser.cpp+72-27
......@@ -302,13 +302,13 @@ static void ast_parse_param_decl_list(ParseContext *pc, size_t *token_index,
302302
303303 ast_eat_token(pc, token_index, TokenIdLParen);
304304
305 Token *token = &pc->tokens->at(*token_index);
306 if (token->id == TokenIdRParen) {
307 *token_index += 1;
308 return;
309 }
310
311305 for (;;) {
306 Token *token = &pc->tokens->at(*token_index);
307 if (token->id == TokenIdRParen) {
308 *token_index += 1;
309 return;
310 }
311
312312 AstNode *param_decl_node = ast_parse_param_decl(pc, token_index);
313313 bool expect_end = false;
314314 assert(param_decl_node);
......@@ -316,31 +316,33 @@ static void ast_parse_param_decl_list(ParseContext *pc, size_t *token_index,
316316 expect_end = param_decl_node->data.param_decl.is_var_args;
317317 *is_var_args = expect_end;
318318
319 Token *token = &pc->tokens->at(*token_index);
319 token = &pc->tokens->at(*token_index);
320320 *token_index += 1;
321321 if (token->id == TokenIdRParen) {
322322 return;
323 } else if (expect_end) {
324 ast_invalid_token_error(pc, token);
325323 } else {
326324 ast_expect_token(pc, token, TokenIdComma);
325 if (expect_end) {
326 ast_eat_token(pc, token_index, TokenIdRParen);
327 return;
328 }
327329 }
328330 }
329331 zig_unreachable();
330332}
331333
332334static void ast_parse_fn_call_param_list(ParseContext *pc, size_t *token_index, ZigList<AstNode*> *params) {
333 Token *token = &pc->tokens->at(*token_index);
334 if (token->id == TokenIdRParen) {
335 *token_index += 1;
336 return;
337 }
338
339335 for (;;) {
336 Token *token = &pc->tokens->at(*token_index);
337 if (token->id == TokenIdRParen) {
338 *token_index += 1;
339 return;
340 }
341
340342 AstNode *expr = ast_parse_expression(pc, token_index, true);
341343 params->append(expr);
342344
343 Token *token = &pc->tokens->at(*token_index);
345 token = &pc->tokens->at(*token_index);
344346 *token_index += 1;
345347 if (token->id == TokenIdRParen) {
346348 return;
......@@ -482,7 +484,13 @@ static void ast_parse_asm_clobbers(ParseContext *pc, size_t *token_index, AstNod
482484
483485 if (comma->id == TokenIdComma) {
484486 *token_index += 1;
485 continue;
487
488 Token *token = &pc->tokens->at(*token_index);
489 if (token->id == TokenIdRParen) {
490 break;
491 } else {
492 continue;
493 }
486494 } else {
487495 break;
488496 }
......@@ -513,7 +521,13 @@ static void ast_parse_asm_input(ParseContext *pc, size_t *token_index, AstNode *
513521
514522 if (comma->id == TokenIdComma) {
515523 *token_index += 1;
516 continue;
524
525 Token *token = &pc->tokens->at(*token_index);
526 if (token->id == TokenIdColon || token->id == TokenIdRParen) {
527 break;
528 } else {
529 continue;
530 }
517531 } else {
518532 break;
519533 }
......@@ -546,7 +560,13 @@ static void ast_parse_asm_output(ParseContext *pc, size_t *token_index, AstNode
546560
547561 if (comma->id == TokenIdComma) {
548562 *token_index += 1;
549 continue;
563
564 Token *token = &pc->tokens->at(*token_index);
565 if (token->id == TokenIdColon || token->id == TokenIdRParen) {
566 break;
567 } else {
568 continue;
569 }
550570 } else {
551571 break;
552572 }
......@@ -1783,7 +1803,13 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
17831803 Token *comma_tok = &pc->tokens->at(*token_index);
17841804 if (comma_tok->id == TokenIdComma) {
17851805 *token_index += 1;
1786 continue;
1806
1807 Token *token = &pc->tokens->at(*token_index);
1808 if (token->id == TokenIdFatArrow) {
1809 break;
1810 } else {
1811 continue;
1812 }
17871813 }
17881814 break;
17891815 }
......@@ -1812,7 +1838,15 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
18121838 }
18131839
18141840 prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);
1815 ast_eat_token(pc, token_index, TokenIdComma);
1841
1842 Token *trailing_token = &pc->tokens->at(*token_index);
1843 if (trailing_token->id == TokenIdRBrace) {
1844 *token_index += 1;
1845
1846 return node;
1847 } else {
1848 ast_eat_token(pc, token_index, TokenIdComma);
1849 }
18161850
18171851 }
18181852}
......@@ -2364,17 +2398,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
23642398 field_node->data.struct_field.visib_mod = visib_mod;
23652399 field_node->data.struct_field.name = token_buf(token);
23662400
2367 Token *expr_or_comma = &pc->tokens->at(*token_index);
2368 if (expr_or_comma->id == TokenIdComma) {
2369 field_node->data.struct_field.type = ast_create_void_type_node(pc, expr_or_comma);
2401 Token *token = &pc->tokens->at(*token_index);
2402 if (token->id == TokenIdComma || token->id == TokenIdRBrace) {
2403 field_node->data.struct_field.type = ast_create_void_type_node(pc, token);
23702404 *token_index += 1;
2405 node->data.container_decl.fields.append(field_node);
2406
2407 if (token->id == TokenIdRBrace) {
2408 break;
2409 }
23712410 } else {
23722411 ast_eat_token(pc, token_index, TokenIdColon);
23732412 field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);
2374 ast_eat_token(pc, token_index, TokenIdComma);
2375 }
2413 node->data.container_decl.fields.append(field_node);
23762414
2377 node->data.container_decl.fields.append(field_node);
2415 Token *token = &pc->tokens->at(*token_index);
2416 if (token->id == TokenIdRBrace) {
2417 *token_index += 1;
2418 break;
2419 } else {
2420 ast_eat_token(pc, token_index, TokenIdComma);
2421 }
2422 }
23782423 } else {
23792424 ast_invalid_token_error(pc, token);
23802425 }
test/behavior.zig+1
......@@ -34,6 +34,7 @@ comptime {
3434 _ = @import("cases/switch.zig");
3535 _ = @import("cases/switch_prong_err_enum.zig");
3636 _ = @import("cases/switch_prong_implicit_cast.zig");
37 _ = @import("cases/syntax.zig");
3738 _ = @import("cases/this.zig");
3839 _ = @import("cases/try.zig");
3940 _ = @import("cases/undefined.zig");
test/cases/syntax.zig created+60
......@@ -0,0 +1,60 @@
1// Test trailing comma syntax
2
3const struct_trailing_comma = struct { x: i32, y: i32, };
4const struct_no_comma = struct { x: i32, y: i32 };
5const struct_no_comma_void_type = struct { x: i32, y };
6const struct_fn_no_comma = struct { fn m() {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9const enum_no_comma_type = enum { A, B: i32 };
10
11fn container_init() {
12 const S = struct { x: i32, y: i32 };
13 _ = S { .x = 1, .y = 2 };
14 _ = S { .x = 1, .y = 2, };
15}
16
17fn switch_cases(x: i32) {
18 switch (x) {
19 1,2,3 => {},
20 4,5, => {},
21 6...8, => {},
22 else => {},
23 }
24}
25
26fn switch_prongs(x: i32) {
27 switch (x) {
28 0 => {},
29 else => {},
30 }
31 switch (x) {
32 0 => {},
33 else => {}
34 }
35}
36
37const fn_no_comma = fn(i32, i32);
38const fn_trailing_comma = fn(i32, i32,);
39const fn_vararg_trailing_comma = fn(i32, i32, ...,);
40
41fn fn_calls() {
42 fn add(x: i32, y: i32,) -> i32 { x + y };
43 _ = add(1, 2);
44 _ = add(1, 2,);
45
46 fn swallow(x: ...,) {};
47 _ = swallow(1,2,3,);
48 _ = swallow();
49}
50
51fn asm_lists() {
52 if (false) { // Build AST but don't analyze
53 asm ("not real assembly"
54 :[a] "x" (x),);
55 asm ("not real assembly"
56 :[a] "x" (->i32),:[a] "x" (1),);
57 asm ("still not real assembly"
58 :::"a","b",);
59 }
60}