Commit 6cddf9d723

Vexu <15308111+Vexu@users.noreply.github.com>
2019-11-17 16:07:48
properly parse anon literal in array
1 parent 8c4784f
Changed files (4)
lib
src
test
stage1
behavior
lib/std/zig/parse.zig
@@ -1630,7 +1630,11 @@ fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenInd
 /// FieldInit <- DOT IDENTIFIER EQUAL Expr
 fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
     const period_token = eatToken(it, .Period) orelse return null;
-    const name_token = try expectToken(it, tree, .Identifier);
+    const name_token = eatToken(it, .Identifier) orelse {
+        // Because of anon literals `.{` is also valid.
+        putBackToken(it, period_token);
+        return null;
+    };
     const eq_token = eatToken(it, .Equal) orelse {
         // `.Name` may also be an enum literal, which is a later rule.
         putBackToken(it, name_token);
lib/std/zig/parser_test.zig
@@ -1,3 +1,13 @@
+test "zig fmt: anon literal in array" {
+    try testCanonical(
+        \\var arr: [2]Foo = .{
+        \\    .{ .a = 2 },
+        \\    .{ .b = 3 },
+        \\};
+        \\
+    );
+}
+
 test "zig fmt: anon struct literal syntax" {
     try testCanonical(
         \\const x = .{
src/parser.cpp
@@ -2025,7 +2025,12 @@ static AstNode *ast_parse_field_init(ParseContext *pc) {
     if (first == nullptr)
         return nullptr;
 
-    Token *name = expect_token(pc, TokenIdSymbol);
+    Token *name = eat_token_if(pc, TokenIdSymbol);
+    if (name == nullptr) {
+        // Because of anon literals ".{" is also valid.
+        put_back_token(pc);
+        return nullptr;
+    }
     if (eat_token_if(pc, TokenIdEq) == nullptr) {
         // Because ".Name" can also be intepreted as an enum literal, we should put back
         // those two tokens again so that the parser can try to parse them as the enum
test/stage1/behavior/array.zig
@@ -312,3 +312,24 @@ test "anonymous list literal syntax" {
     S.doTheTest();
     comptime S.doTheTest();
 }
+
+test "anonymous literal in array" {
+    const S = struct {
+        const Foo = struct {
+            a: usize = 2,
+            b: usize = 4,
+        };
+        fn doTheTest() void {
+            var array: [2]Foo = .{
+                .{.a = 3},
+                .{.b = 3},
+            };
+            expect(array[0].a == 3);
+            expect(array[0].b == 4);
+            expect(array[1].a == 2);
+            expect(array[1].b == 3);
+        }
+    };
+    S.doTheTest();
+    comptime S.doTheTest();
+}