Commit aa7d16aba1

Jacob Young <jacobly0@users.noreply.github.com>
2024-03-06 06:49:17
grammar: remove gratuitous ambiguity
Previously, the following matched both ContainerField alternatives: * [IDENTIFIER] * [IDENTIFIER][COLON][TypeExpr]
1 parent 90ab8ea
Changed files (3)
doc/langref.html.in
@@ -11990,9 +11990,7 @@ VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteA
 
 GlobalVarDecl <- VarDeclProto (EQUAL Expr)? SEMICOLON
 
-ContainerField
-    <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? ByteAlign? (EQUAL Expr)?
-     / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)?
+ContainerField <- doc_comment? KEYWORD_comptime? !KEYWORD_fn (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)?
 
 # *** Block Level ***
 Statement
lib/std/zig/Ast.zig
@@ -661,7 +661,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
         .container_field,
         => {
             const name_token = main_tokens[n];
-            if (token_tags[name_token] != .keyword_comptime and name_token > 0 and token_tags[name_token - 1] == .keyword_comptime) {
+            if (name_token > 0 and token_tags[name_token - 1] == .keyword_comptime) {
                 end_offset += 1;
             }
             return name_token - end_offset;
@@ -2076,13 +2076,11 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)
         .ast = info,
         .comptime_token = null,
     };
-    if (token_tags[info.main_token] == .keyword_comptime) {
+    if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {
         // comptime type = init,
-        // ^
-        result.comptime_token = info.main_token;
-    } else if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {
+        // ^        ^
         // comptime name: type = init,
-        // ^
+        // ^        ^
         result.comptime_token = info.main_token - 1;
     }
     return result;
@@ -2580,13 +2578,10 @@ pub const full = struct {
 
         pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void {
             if (!cf.ast.tuple_like) return;
-            if (cf.ast.type_expr == 0) return;
             if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return;
 
-            const ident = nodes.items(.main_token)[cf.ast.type_expr];
-            cf.ast.tuple_like = false;
-            cf.ast.main_token = ident;
             cf.ast.type_expr = 0;
+            cf.ast.tuple_like = false;
         }
     };
 
lib/std/zig/Parse.zig
@@ -874,24 +874,13 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {
     return var_decl;
 }
 
-/// ContainerField
-///     <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? ByteAlign? (EQUAL Expr)?
-///      / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)?
+/// ContainerField <- doc_comment? KEYWORD_comptime? !KEYWORD_fn (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)?
 fn expectContainerField(p: *Parse) !Node.Index {
-    var main_token = p.tok_i;
     _ = p.eatToken(.keyword_comptime);
-    const tuple_like = p.token_tags[p.tok_i] != .identifier or p.token_tags[p.tok_i + 1] != .colon;
-    if (!tuple_like) {
-        main_token = p.assertToken(.identifier);
-    }
-
-    var align_expr: Node.Index = 0;
-    var type_expr: Node.Index = 0;
-    if (p.eatToken(.colon) != null or tuple_like) {
-        type_expr = try p.expectTypeExpr();
-        align_expr = try p.parseByteAlign();
-    }
-
+    const main_token = p.tok_i;
+    if (p.token_tags[p.tok_i] == .identifier and p.token_tags[p.tok_i + 1] == .colon) p.tok_i += 2;
+    const type_expr = try p.expectTypeExpr();
+    const align_expr = try p.parseByteAlign();
     const value_expr: Node.Index = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
 
     if (align_expr == 0) {