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,...@@ -302,13 +302,13 @@ static void ast_parse_param_decl_list(ParseContext *pc, size_t *token_index,
302302
303 ast_eat_token(pc, token_index, TokenIdLParen);303 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
311 for (;;) {305 for (;;) {
306 Token *token = &pc->tokens->at(*token_index);
307 if (token->id == TokenIdRParen) {
308 *token_index += 1;
309 return;
310 }
311
312 AstNode *param_decl_node = ast_parse_param_decl(pc, token_index);312 AstNode *param_decl_node = ast_parse_param_decl(pc, token_index);
313 bool expect_end = false;313 bool expect_end = false;
314 assert(param_decl_node);314 assert(param_decl_node);
...@@ -316,31 +316,33 @@ static void ast_parse_param_decl_list(ParseContext *pc, size_t *token_index,...@@ -316,31 +316,33 @@ static void ast_parse_param_decl_list(ParseContext *pc, size_t *token_index,
316 expect_end = param_decl_node->data.param_decl.is_var_args;316 expect_end = param_decl_node->data.param_decl.is_var_args;
317 *is_var_args = expect_end;317 *is_var_args = expect_end;
318318
319 Token *token = &pc->tokens->at(*token_index);319 token = &pc->tokens->at(*token_index);
320 *token_index += 1;320 *token_index += 1;
321 if (token->id == TokenIdRParen) {321 if (token->id == TokenIdRParen) {
322 return;322 return;
323 } else if (expect_end) {
324 ast_invalid_token_error(pc, token);
325 } else {323 } else {
326 ast_expect_token(pc, token, TokenIdComma);324 ast_expect_token(pc, token, TokenIdComma);
325 if (expect_end) {
326 ast_eat_token(pc, token_index, TokenIdRParen);
327 return;
328 }
327 }329 }
328 }330 }
329 zig_unreachable();331 zig_unreachable();
330}332}
331333
332static void ast_parse_fn_call_param_list(ParseContext *pc, size_t *token_index, ZigList<AstNode*> *params) {334static 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
339 for (;;) {335 for (;;) {
336 Token *token = &pc->tokens->at(*token_index);
337 if (token->id == TokenIdRParen) {
338 *token_index += 1;
339 return;
340 }
341
340 AstNode *expr = ast_parse_expression(pc, token_index, true);342 AstNode *expr = ast_parse_expression(pc, token_index, true);
341 params->append(expr);343 params->append(expr);
342344
343 Token *token = &pc->tokens->at(*token_index);345 token = &pc->tokens->at(*token_index);
344 *token_index += 1;346 *token_index += 1;
345 if (token->id == TokenIdRParen) {347 if (token->id == TokenIdRParen) {
346 return;348 return;
...@@ -482,7 +484,13 @@ static void ast_parse_asm_clobbers(ParseContext *pc, size_t *token_index, AstNod...@@ -482,7 +484,13 @@ static void ast_parse_asm_clobbers(ParseContext *pc, size_t *token_index, AstNod
482484
483 if (comma->id == TokenIdComma) {485 if (comma->id == TokenIdComma) {
484 *token_index += 1;486 *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 }
486 } else {494 } else {
487 break;495 break;
488 }496 }
...@@ -513,7 +521,13 @@ static void ast_parse_asm_input(ParseContext *pc, size_t *token_index, AstNode *...@@ -513,7 +521,13 @@ static void ast_parse_asm_input(ParseContext *pc, size_t *token_index, AstNode *
513521
514 if (comma->id == TokenIdComma) {522 if (comma->id == TokenIdComma) {
515 *token_index += 1;523 *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 }
517 } else {531 } else {
518 break;532 break;
519 }533 }
...@@ -546,7 +560,13 @@ static void ast_parse_asm_output(ParseContext *pc, size_t *token_index, AstNode...@@ -546,7 +560,13 @@ static void ast_parse_asm_output(ParseContext *pc, size_t *token_index, AstNode
546560
547 if (comma->id == TokenIdComma) {561 if (comma->id == TokenIdComma) {
548 *token_index += 1;562 *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 }
550 } else {570 } else {
551 break;571 break;
552 }572 }
...@@ -1783,7 +1803,13 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo...@@ -1783,7 +1803,13 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
1783 Token *comma_tok = &pc->tokens->at(*token_index);1803 Token *comma_tok = &pc->tokens->at(*token_index);
1784 if (comma_tok->id == TokenIdComma) {1804 if (comma_tok->id == TokenIdComma) {
1785 *token_index += 1;1805 *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 }
1787 }1813 }
1788 break;1814 break;
1789 }1815 }
...@@ -1812,7 +1838,15 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo...@@ -1812,7 +1838,15 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
1812 }1838 }
18131839
1814 prong_node->data.switch_prong.expr = ast_parse_expression(pc, token_index, true);1840 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
1817 }1851 }
1818}1852}
...@@ -2364,17 +2398,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2364,17 +2398,28 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2364 field_node->data.struct_field.visib_mod = visib_mod;2398 field_node->data.struct_field.visib_mod = visib_mod;
2365 field_node->data.struct_field.name = token_buf(token);2399 field_node->data.struct_field.name = token_buf(token);
23662400
2367 Token *expr_or_comma = &pc->tokens->at(*token_index);2401 Token *token = &pc->tokens->at(*token_index);
2368 if (expr_or_comma->id == TokenIdComma) {2402 if (token->id == TokenIdComma || token->id == TokenIdRBrace) {
2369 field_node->data.struct_field.type = ast_create_void_type_node(pc, expr_or_comma);2403 field_node->data.struct_field.type = ast_create_void_type_node(pc, token);
2370 *token_index += 1;2404 *token_index += 1;
2405 node->data.container_decl.fields.append(field_node);
2406
2407 if (token->id == TokenIdRBrace) {
2408 break;
2409 }
2371 } else {2410 } else {
2372 ast_eat_token(pc, token_index, TokenIdColon);2411 ast_eat_token(pc, token_index, TokenIdColon);
2373 field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);2412 field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);
2374 ast_eat_token(pc, token_index, TokenIdComma);2413 node->data.container_decl.fields.append(field_node);
2375 }
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 }
2378 } else {2423 } else {
2379 ast_invalid_token_error(pc, token);2424 ast_invalid_token_error(pc, token);
2380 }2425 }
test/behavior.zig+1
...@@ -34,6 +34,7 @@ comptime {...@@ -34,6 +34,7 @@ comptime {
34 _ = @import("cases/switch.zig");34 _ = @import("cases/switch.zig");
35 _ = @import("cases/switch_prong_err_enum.zig");35 _ = @import("cases/switch_prong_err_enum.zig");
36 _ = @import("cases/switch_prong_implicit_cast.zig");36 _ = @import("cases/switch_prong_implicit_cast.zig");
37 _ = @import("cases/syntax.zig");
37 _ = @import("cases/this.zig");38 _ = @import("cases/this.zig");
38 _ = @import("cases/try.zig");39 _ = @import("cases/try.zig");
39 _ = @import("cases/undefined.zig");40 _ = @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}