authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-16 15:56:03+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-05-16 15:56:03+03:00
log758de71d9769b3539f042aea8821c3ac18bed74c
tree9767474967f6944d28d1b06d3f01c2cc26ad886a
parent092f726eeca1b73d29efb7074bc3302f974aba7d
parent5ac684ec502096196f05a1c6ed1841b886d6db92
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5353 from Vexu/parser

Self-hosted parser fixes

7 files changed, 171 insertions(+), 115 deletions(-)

doc/langref.html.in+5-5
......@@ -10098,7 +10098,7 @@ FnProto &lt;- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? Link
1009810098
1009910099VarDecl &lt;- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
1010010100
10101ContainerField &lt;- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
10101ContainerField &lt;- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
1010210102
1010310103# *** Block Level ***
1010410104Statement
......@@ -10212,7 +10212,7 @@ PrimaryTypeExpr
1021210212 / KEYWORD_error DOT IDENTIFIER
1021310213 / KEYWORD_false
1021410214 / KEYWORD_null
10215 / KEYWORD_promise
10215 / KEYWORD_anyframe
1021610216 / KEYWORD_true
1021710217 / KEYWORD_undefined
1021810218 / KEYWORD_unreachable
......@@ -10356,7 +10356,7 @@ PrefixOp
1035610356
1035710357PrefixTypeOp
1035810358 &lt;- QUESTIONMARK
10359 / KEYWORD_promise MINUSRARROW
10359 / KEYWORD_anyframe MINUSRARROW
1036010360 / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1036110361 / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1036210362
......@@ -10503,6 +10503,7 @@ end_of_word &lt;- ![a-zA-Z0-9_] skip
1050310503KEYWORD_align &lt;- 'align' end_of_word
1050410504KEYWORD_allowzero &lt;- 'allowzero' end_of_word
1050510505KEYWORD_and &lt;- 'and' end_of_word
10506KEYWORD_anyframe &lt;- 'anyframe' end_of_word
1050610507KEYWORD_asm &lt;- 'asm' end_of_word
1050710508KEYWORD_async &lt;- 'async' end_of_word
1050810509KEYWORD_await &lt;- 'await' end_of_word
......@@ -10529,7 +10530,6 @@ KEYWORD_null &lt;- 'null' end_of_word
1052910530KEYWORD_or &lt;- 'or' end_of_word
1053010531KEYWORD_orelse &lt;- 'orelse' end_of_word
1053110532KEYWORD_packed &lt;- 'packed' end_of_word
10532KEYWORD_promise &lt;- 'promise' end_of_word
1053310533KEYWORD_pub &lt;- 'pub' end_of_word
1053410534KEYWORD_resume &lt;- 'resume' end_of_word
1053510535KEYWORD_return &lt;- 'return' end_of_word
......@@ -10556,7 +10556,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_asm
1055610556 / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false
1055710557 / KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline
1055810558 / KEYWORD_noalias / KEYWORD_null / KEYWORD_or
10559 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
10559 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_anyframe / KEYWORD_pub
1056010560 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
1056110561 / KEYWORD_struct / KEYWORD_suspend
1056210562 / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
lib/std/zig/ast.zig+19-6
......@@ -986,14 +986,22 @@ pub const Node = struct {
986986 comptime_token: ?TokenIndex,
987987 noalias_token: ?TokenIndex,
988988 name_token: ?TokenIndex,
989 type_node: *Node,
990 var_args_token: ?TokenIndex,
989 param_type: ParamType,
990
991 pub const ParamType = union(enum) {
992 var_type: *Node,
993 var_args: TokenIndex,
994 type_expr: *Node,
995 };
991996
992997 pub fn iterate(self: *ParamDecl, index: usize) ?*Node {
993998 var i = index;
994999
9951000 if (i < 1) {
996 return if (self.var_args_token == null) self.type_node else null;
1001 switch (self.param_type) {
1002 .var_args => return null,
1003 .var_type, .type_expr => |node| return node,
1004 }
9971005 }
9981006 i -= 1;
9991007
......@@ -1004,12 +1012,17 @@ pub const Node = struct {
10041012 if (self.comptime_token) |comptime_token| return comptime_token;
10051013 if (self.noalias_token) |noalias_token| return noalias_token;
10061014 if (self.name_token) |name_token| return name_token;
1007 return self.type_node.firstToken();
1015 switch (self.param_type) {
1016 .var_args => |tok| return tok,
1017 .var_type, .type_expr => |node| return node.firstToken(),
1018 }
10081019 }
10091020
10101021 pub fn lastToken(self: *const ParamDecl) TokenIndex {
1011 if (self.var_args_token) |var_args_token| return var_args_token;
1012 return self.type_node.lastToken();
1022 switch (self.param_type) {
1023 .var_args => |tok| return tok,
1024 .var_type, .type_expr => |node| return node.lastToken(),
1025 }
10131026 }
10141027 };
10151028
lib/std/zig/parse.zig+84-88
......@@ -57,16 +57,10 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree {
5757fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node.Root {
5858 const node = try arena.create(Node.Root);
5959 node.* = .{
60 .decls = try parseContainerMembers(arena, it, tree),
61 .eof_token = eatToken(it, .Eof) orelse blk: {
62 // parseContainerMembers will try to skip as much
63 // invalid tokens as it can so this can only be a '}'
64 const tok = eatToken(it, .RBrace).?;
65 try tree.errors.push(.{
66 .ExpectedContainerMembers = .{ .token = tok },
67 });
68 break :blk tok;
69 },
60 .decls = try parseContainerMembers(arena, it, tree, true),
61 // parseContainerMembers will try to skip as much
62 // invalid tokens as it can so this can only be the EOF
63 .eof_token = eatToken(it, .Eof).?,
7064 };
7165 return node;
7266}
......@@ -75,10 +69,10 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error
7569/// <- TestDecl ContainerMembers
7670/// / TopLevelComptime ContainerMembers
7771/// / KEYWORD_pub? TopLevelDecl ContainerMembers
78/// / KEYWORD_pub? ContainerField COMMA ContainerMembers
79/// / KEYWORD_pub? ContainerField
72/// / ContainerField COMMA ContainerMembers
73/// / ContainerField
8074/// /
81fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Root.DeclList {
75fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top_level: bool) !Node.Root.DeclList {
8276 var list = Node.Root.DeclList.init(arena);
8377
8478 var field_state: union(enum) {
......@@ -205,9 +199,15 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
205199 // try to continue parsing
206200 const index = it.index;
207201 findNextContainerMember(it);
208 switch (it.peek().?.id) {
209 .Eof, .RBrace => break,
202 const next = it.peek().?.id;
203 switch (next) {
204 .Eof => break,
210205 else => {
206 if (next == .RBrace) {
207 if (!top_level) break;
208 _ = nextToken(it);
209 }
210
211211 // add error and continue
212212 try tree.errors.push(.{
213213 .ExpectedToken = .{ .token = index, .expected_id = .Comma },
......@@ -228,12 +228,18 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No
228228 });
229229 }
230230
231 switch (it.peek().?.id) {
232 .Eof, .RBrace => break,
231 const next = it.peek().?.id;
232 switch (next) {
233 .Eof => break,
233234 else => {
235 const index = it.index;
236 if (next == .RBrace) {
237 if (!top_level) break;
238 _ = nextToken(it);
239 }
240
234241 // this was likely not supposed to end yet,
235242 // try to find the next declaration
236 const index = it.index;
237243 findNextContainerMember(it);
238244 try tree.errors.push(.{
239245 .ExpectedContainerMembers = .{ .token = index },
......@@ -278,7 +284,10 @@ fn findNextContainerMember(it: *TokenIterator) void {
278284 }
279285 },
280286 .LParen, .LBracket, .LBrace => level += 1,
281 .RParen, .RBracket, .RBrace => {
287 .RParen, .RBracket => {
288 if (level != 0) level -= 1;
289 },
290 .RBrace => {
282291 if (level == 0) {
283292 // end of container, exit
284293 putBackToken(it, tok.index);
......@@ -402,20 +411,16 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
402411 fn_node.*.extern_export_inline_token = extern_export_inline_token;
403412 fn_node.*.lib_name = lib_name;
404413 if (eatToken(it, .Semicolon)) |_| return node;
405 if (parseBlock(arena, it, tree) catch |err| switch (err) {
406 error.OutOfMemory => return error.OutOfMemory,
414
415 if (try expectNodeRecoverable(arena, it, tree, parseBlock, .{
407416 // since parseBlock only return error.ParseError on
408417 // a missing '}' we can assume this function was
409418 // supposed to end here.
410 error.ParseError => return node,
411 }) |body_node| {
419 .ExpectedSemiOrLBrace = .{ .token = it.index },
420 })) |body_node| {
412421 fn_node.body_node = body_node;
413 return node;
414422 }
415 try tree.errors.push(.{
416 .ExpectedSemiOrLBrace = .{ .token = it.index },
417 });
418 return error.ParseError;
423 return node;
419424 }
420425
421426 if (extern_export_inline_token) |token| {
......@@ -490,14 +495,11 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
490495 const exclamation_token = eatToken(it, .Bang);
491496
492497 const return_type_expr = (try parseVarType(arena, it, tree)) orelse
493 (try parseTypeExpr(arena, it, tree)) orelse blk: {
494 try tree.errors.push(.{
495 .ExpectedReturnType = .{ .token = it.index },
496 });
498 try expectNodeRecoverable(arena, it, tree, parseTypeExpr, .{
497499 // most likely the user forgot to specify the return type.
498500 // Mark return type as invalid and try to continue.
499 break :blk null;
500 };
501 .ExpectedReturnType = .{ .token = it.index },
502 });
501503
502504 // TODO https://github.com/ziglang/zig/issues/3750
503505 const R = Node.FnProto.ReturnType;
......@@ -508,9 +510,10 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
508510 else
509511 R{ .Explicit = return_type_expr.? };
510512
511 const var_args_token = if (params.len > 0)
512 params.at(params.len - 1).*.cast(Node.ParamDecl).?.var_args_token
513 else
513 const var_args_token = if (params.len > 0) blk: {
514 const param_type = params.at(params.len - 1).*.cast(Node.ParamDecl).?.param_type;
515 break :blk if (param_type == .var_args) param_type.var_args else null;
516 } else
514517 null;
515518
516519 const fn_proto_node = try arena.create(Node.FnProto);
......@@ -707,12 +710,7 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
707710 if (try parseLabeledStatement(arena, it, tree)) |node| return node;
708711 if (try parseSwitchExpr(arena, it, tree)) |node| return node;
709712 if (try parseAssignExpr(arena, it, tree)) |node| {
710 _ = eatToken(it, .Semicolon) orelse {
711 try tree.errors.push(.{
712 .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon },
713 });
714 // pretend we saw a semicolon and continue parsing
715 };
713 _ = try expectTokenRecoverable(it, tree, .Semicolon);
716714 return node;
717715 }
718716
......@@ -727,16 +725,12 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
727725 const if_prefix = if_node.cast(Node.If).?;
728726
729727 const block_expr = (try parseBlockExpr(arena, it, tree));
730 const assign_expr = if (block_expr == null) blk: {
731 break :blk (try parseAssignExpr(arena, it, tree)) orelse null;
732 } else null;
733
734 if (block_expr == null and assign_expr == null) {
735 try tree.errors.push(.{
728 const assign_expr = if (block_expr == null)
729 try expectNode(arena, it, tree, parseAdditionExpr, .{
736730 .ExpectedBlockOrAssignment = .{ .token = it.index },
737 });
738 return error.ParseError;
739 }
731 })
732 else
733 null;
740734
741735 const semicolon = if (assign_expr != null) eatToken(it, .Semicolon) else null;
742736
......@@ -773,10 +767,9 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
773767 try tree.errors.push(.{
774768 .ExpectedSemiOrElse = .{ .token = it.index },
775769 });
776 return error.ParseError;
777770 }
778771
779 unreachable;
772 return if_node;
780773}
781774
782775/// LabeledStatement <- BlockLabel? (Block / LoopStatement)
......@@ -882,7 +875,8 @@ fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
882875 try tree.errors.push(.{
883876 .ExpectedSemiOrElse = .{ .token = it.index },
884877 });
885 return null;
878
879 return node;
886880 }
887881
888882 return null;
......@@ -944,7 +938,8 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
944938 try tree.errors.push(.{
945939 .ExpectedSemiOrElse = .{ .token = it.index },
946940 });
947 return null;
941
942 return node;
948943 }
949944
950945 return null;
......@@ -956,12 +951,7 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
956951fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
957952 if (try parseBlockExpr(arena, it, tree)) |node| return node;
958953 if (try parseAssignExpr(arena, it, tree)) |node| {
959 _ = eatToken(it, .Semicolon) orelse {
960 try tree.errors.push(.{
961 .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon },
962 });
963 // pretend we saw a semicolon and continue parsing
964 };
954 _ = try expectTokenRecoverable(it, tree, .Semicolon);
965955 return node;
966956 }
967957 return null;
......@@ -1478,17 +1468,19 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
14781468 return &node.base;
14791469 }
14801470 if (eatToken(it, .Keyword_error)) |token| {
1481 const period = try expectToken(it, tree, .Period);
1482 const identifier = try expectNode(arena, it, tree, parseIdentifier, .{
1471 const period = try expectTokenRecoverable(it, tree, .Period);
1472 const identifier = try expectNodeRecoverable(arena, it, tree, parseIdentifier, .{
14831473 .ExpectedIdentifier = .{ .token = it.index },
14841474 });
14851475 const global_error_set = try createLiteral(arena, Node.ErrorType, token);
1476 if (period == null or identifier == null) return global_error_set;
1477
14861478 const node = try arena.create(Node.InfixOp);
14871479 node.* = .{
1488 .op_token = period,
1480 .op_token = period.?,
14891481 .lhs = global_error_set,
14901482 .op = .Period,
1491 .rhs = identifier,
1483 .rhs = identifier.?,
14921484 };
14931485 return &node.base;
14941486 }
......@@ -1948,15 +1940,8 @@ fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19481940 .comptime_token = comptime_token,
19491941 .noalias_token = noalias_token,
19501942 .name_token = name_token,
1951 // TODO: These should be squished into a ParamType enum
1952 .type_node = undefined,
1953 .var_args_token = null,
1943 .param_type = param_type,
19541944 };
1955 switch (param_type) {
1956 .VarType => |node| param_decl.type_node = node,
1957 .TypeExpr => |node| param_decl.type_node = node,
1958 .VarArgs => |token| param_decl.var_args_token = token,
1959 }
19601945 return &param_decl.base;
19611946}
19621947
......@@ -1964,20 +1949,15 @@ fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19641949/// <- KEYWORD_var
19651950/// / DOT3
19661951/// / TypeExpr
1967fn parseParamType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?ParamType {
1968 if (try parseVarType(arena, it, tree)) |node| return ParamType{ .VarType = node };
1969 if (eatToken(it, .Ellipsis3)) |token| return ParamType{ .VarArgs = token };
1970 if (try parseTypeExpr(arena, it, tree)) |node| return ParamType{ .TypeExpr = node };
1952fn parseParamType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?Node.ParamDecl.ParamType {
1953 // TODO cast from tuple to error union is broken
1954 const P = Node.ParamDecl.ParamType;
1955 if (try parseVarType(arena, it, tree)) |node| return P{ .var_type = node };
1956 if (eatToken(it, .Ellipsis3)) |token| return P{ .var_args = token };
1957 if (try parseTypeExpr(arena, it, tree)) |node| return P{ .type_expr = node };
19711958 return null;
19721959}
19731960
1974// TODO: Move to ast.Node.ParamDecl.ParamType
1975const ParamType = union(enum) {
1976 VarType: *Node,
1977 VarArgs: TokenIndex,
1978 TypeExpr: *Node,
1979};
1980
19811961/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
19821962fn parseIfPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
19831963 const if_token = eatToken(it, .Keyword_if) orelse return null;
......@@ -2778,7 +2758,7 @@ fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
27782758fn parseContainerDeclAuto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
27792759 const node = (try parseContainerDeclType(arena, it, tree)) orelse return null;
27802760 const lbrace = try expectToken(it, tree, .LBrace);
2781 const members = try parseContainerMembers(arena, it, tree);
2761 const members = try parseContainerMembers(arena, it, tree, false);
27822762 const rbrace = try expectToken(it, tree, .RBrace);
27832763
27842764 const decl_type = node.cast(Node.ContainerDecl).?;
......@@ -3250,6 +3230,11 @@ fn eatAnnotatedToken(it: *TokenIterator, id: Token.Id) ?AnnotatedToken {
32503230}
32513231
32523232fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex {
3233 return (try expectTokenRecoverable(it, tree, id)) orelse
3234 error.ParseError;
3235}
3236
3237fn expectTokenRecoverable(it: *TokenIterator, tree: *Tree, id: Token.Id) !?TokenIndex {
32533238 const token = nextToken(it);
32543239 if (token.ptr.id != id) {
32553240 try tree.errors.push(.{
......@@ -3257,7 +3242,7 @@ fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex {
32573242 });
32583243 // go back so that we can recover properly
32593244 putBackToken(it, token.index);
3260 return error.ParseError;
3245 return null;
32613246 }
32623247 return token.index;
32633248}
......@@ -3297,9 +3282,20 @@ fn expectNode(
32973282 parseFn: NodeParseFn,
32983283 err: AstError, // if parsing fails
32993284) Error!*Node {
3285 return (try expectNodeRecoverable(arena, it, tree, parseFn, err)) orelse
3286 return error.ParseError;
3287}
3288
3289fn expectNodeRecoverable(
3290 arena: *Allocator,
3291 it: *TokenIterator,
3292 tree: *Tree,
3293 parseFn: NodeParseFn,
3294 err: AstError, // if parsing fails
3295) !?*Node {
33003296 return (try parseFn(arena, it, tree)) orelse {
33013297 try tree.errors.push(err);
3302 return error.ParseError;
3298 return null;
33033299 };
33043300}
33053301
lib/std/zig/parser_test.zig+52
......@@ -148,6 +148,58 @@ test "recovery: invalid parameter" {
148148 });
149149}
150150
151test "recovery: extra '}' at top level" {
152 try testError(
153 \\}}}
154 \\test "" {
155 \\ a && b;
156 \\}
157 , &[_]Error{
158 .ExpectedContainerMembers,
159 .ExpectedContainerMembers,
160 .ExpectedContainerMembers,
161 .InvalidAnd,
162 });
163}
164
165test "recovery: mismatched bracket at top level" {
166 try testError(
167 \\const S = struct {
168 \\ arr: 128]?G
169 \\};
170 , &[_]Error{
171 .ExpectedToken,
172 });
173}
174
175test "recovery: invalid global error set access" {
176 try testError(
177 \\test "" {
178 \\ error && foo;
179 \\}
180 , &[_]Error{
181 .ExpectedToken,
182 .ExpectedIdentifier,
183 .InvalidAnd,
184 });
185}
186
187test "recovery: missing semicolon after if, for, while stmt" {
188 try testError(
189 \\test "" {
190 \\ if (foo) bar
191 \\ for (foo) |a| bar
192 \\ while (foo) bar
193 \\ a && b;
194 \\}
195 , &[_]Error{
196 .ExpectedSemiOrElse,
197 .ExpectedSemiOrElse,
198 .ExpectedSemiOrElse,
199 .InvalidAnd,
200 });
201}
202
151203test "zig fmt: top-level fields" {
152204 try testCanonical(
153205 \\a: did_you_know,
lib/std/zig/render.zig+3-4
......@@ -2150,10 +2150,9 @@ fn renderParamDecl(
21502150 try renderToken(tree, stream, name_token, indent, start_col, Space.None);
21512151 try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // :
21522152 }
2153 if (param_decl.var_args_token) |var_args_token| {
2154 try renderToken(tree, stream, var_args_token, indent, start_col, space);
2155 } else {
2156 try renderExpression(allocator, stream, tree, indent, start_col, param_decl.type_node, space);
2153 switch (param_decl.param_type) {
2154 .var_args => |token| try renderToken(tree, stream, token, indent, start_col, space),
2155 .var_type, .type_expr => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, space),
21572156 }
21582157}
21592158
src-self-hosted/translate_c.zig+5-9
......@@ -501,7 +501,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
501501 const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*);
502502 const param_name = if (param.name_token) |name_tok|
503503 tokenSlice(c, name_tok)
504 else if (param.var_args_token != null) {
504 else if (param.param_type == .var_args) {
505505 assert(it.next() == null);
506506 _ = proto_node.params.pop();
507507 break;
......@@ -4103,8 +4103,7 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a
41034103 .comptime_token = null,
41044104 .noalias_token = param.noalias_token,
41054105 .name_token = param_name_tok,
4106 .type_node = param.type_node,
4107 .var_args_token = null,
4106 .param_type = param.param_type,
41084107 };
41094108 try fn_params.push(&param_node.base);
41104109 }
......@@ -4678,8 +4677,7 @@ fn finishTransFnProto(
46784677 .comptime_token = null,
46794678 .noalias_token = noalias_tok,
46804679 .name_token = param_name_tok,
4681 .type_node = type_node,
4682 .var_args_token = null,
4680 .param_type = .{ .type_expr = type_node },
46834681 };
46844682 try fn_params.push(&param_node.base);
46854683
......@@ -4699,8 +4697,7 @@ fn finishTransFnProto(
46994697 .comptime_token = null,
47004698 .noalias_token = null,
47014699 .name_token = null,
4702 .type_node = undefined, // Note: Accessing this causes an access violation. Need to check .var_args_token first before trying this field
4703 .var_args_token = try appendToken(rp.c, .Ellipsis3, "..."),
4700 .param_type = .{ .var_args = try appendToken(rp.c, .Ellipsis3, "...") }
47044701 };
47054702 try fn_params.push(&var_arg_node.base);
47064703 }
......@@ -5108,8 +5105,7 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8,
51085105 .comptime_token = null,
51095106 .noalias_token = null,
51105107 .name_token = param_name_tok,
5111 .type_node = &identifier.base,
5112 .var_args_token = null,
5108 .param_type = .{ .type_expr = &identifier.base },
51135109 };
51145110 try fn_params.push(&param_node.base);
51155111
src/parser.cpp+3-3
......@@ -538,8 +538,8 @@ enum ContainerFieldState {
538538// <- TestDecl ContainerMembers
539539// / TopLevelComptime ContainerMembers
540540// / KEYWORD_pub? TopLevelDecl ContainerMembers
541// / KEYWORD_comptime? ContainerField COMMA ContainerMembers
542// / KEYWORD_comptime? ContainerField
541// / ContainerField COMMA ContainerMembers
542// / ContainerField
543543// /
544544static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
545545 AstNodeContainerDecl res = {};
......@@ -862,7 +862,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
862862 return res;
863863}
864864
865// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
865// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
866866static AstNode *ast_parse_container_field(ParseContext *pc) {
867867 Token *identifier = eat_token_if(pc, TokenIdSymbol);
868868 if (identifier == nullptr)