| ... | ... | @@ -92,6 +92,8 @@ pub const Parser = struct { |
| 92 | 92 | FnDef: &ast.NodeFnProto, |
| 93 | 93 | Block: &ast.NodeBlock, |
| 94 | 94 | Statement: &ast.NodeBlock, |
| 95 | ExprListItemOrEnd: &ArrayList(&ast.Node), |
| 96 | ExprListCommaOrEnd: &ArrayList(&ast.Node), |
| 95 | 97 | }; |
| 96 | 98 | |
| 97 | 99 | /// Returns an AST tree, allocated with the parser's allocator. |
| ... | ... | @@ -297,6 +299,21 @@ pub const Parser = struct { |
| 297 | 299 | try stack.append(State.AfterOperand); |
| 298 | 300 | continue; |
| 299 | 301 | }, |
| 302 | Token.Id.Builtin => { |
| 303 | const node = try arena.create(ast.NodeBuiltinCall); |
| 304 | *node = ast.NodeBuiltinCall { |
| 305 | .base = ast.Node {.id = ast.Node.Id.BuiltinCall}, |
| 306 | .builtin_token = token, |
| 307 | .params = ArrayList(&ast.Node).init(arena), |
| 308 | }; |
| 309 | try stack.append(State { |
| 310 | .Operand = &node.base |
| 311 | }); |
| 312 | try stack.append(State.AfterOperand); |
| 313 | try stack.append(State {.ExprListItemOrEnd = &node.params }); |
| 314 | try stack.append(State {.ExpectToken = Token.Id.LParen }); |
| 315 | continue; |
| 316 | }, |
| 300 | 317 | else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), |
| 301 | 318 | } |
| 302 | 319 | }, |
| ... | ... | @@ -352,6 +369,29 @@ pub const Parser = struct { |
| 352 | 369 | } |
| 353 | 370 | }, |
| 354 | 371 | |
| 372 | State.ExprListItemOrEnd => |params| { |
| 373 | var token = self.getNextToken(); |
| 374 | switch (token.id) { |
| 375 | Token.Id.RParen => continue, |
| 376 | else => { |
| 377 | self.putBackToken(token); |
| 378 | stack.append(State { .ExprListCommaOrEnd = params }) catch unreachable; |
| 379 | try stack.append(State { .Expression = DestPtr{.List = params} }); |
| 380 | }, |
| 381 | } |
| 382 | }, |
| 383 | |
| 384 | State.ExprListCommaOrEnd => |params| { |
| 385 | var token = self.getNextToken(); |
| 386 | switch (token.id) { |
| 387 | Token.Id.Comma => { |
| 388 | stack.append(State { .ExprListItemOrEnd = params }) catch unreachable; |
| 389 | }, |
| 390 | Token.Id.RParen => continue, |
| 391 | else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)), |
| 392 | } |
| 393 | }, |
| 394 | |
| 355 | 395 | State.AddrOfModifiers => |addr_of_info| { |
| 356 | 396 | var token = self.getNextToken(); |
| 357 | 397 | switch (token.id) { |
| ... | ... | @@ -539,8 +579,6 @@ pub const Parser = struct { |
| 539 | 579 | State.PrefixOp => unreachable, |
| 540 | 580 | State.Operand => unreachable, |
| 541 | 581 | } |
| 542 | | @import("std").debug.panic("{}", @tagName(state)); |
| 543 | | //unreachable; |
| 544 | 582 | } |
| 545 | 583 | } |
| 546 | 584 | |
| ... | ... | @@ -988,6 +1026,10 @@ pub const Parser = struct { |
| 988 | 1026 | const float_literal = @fieldParentPtr(ast.NodeFloatLiteral, "base", base); |
| 989 | 1027 | try stream.print("{}", self.tokenizer.getTokenSlice(float_literal.token)); |
| 990 | 1028 | }, |
| 1029 | ast.Node.Id.BuiltinCall => { |
| 1030 | const builtin_call = @fieldParentPtr(ast.NodeBuiltinCall, "base", base); |
| 1031 | try stream.print("{}()", self.tokenizer.getTokenSlice(builtin_call.builtin_token)); |
| 1032 | }, |
| 991 | 1033 | else => unreachable, |
| 992 | 1034 | }, |
| 993 | 1035 | RenderState.FnProtoRParen => |fn_proto| { |
| ... | ... | @@ -1098,6 +1140,11 @@ fn testCanonical(source: []const u8) !void { |
| 1098 | 1140 | } |
| 1099 | 1141 | |
| 1100 | 1142 | test "zig fmt" { |
| 1143 | try testCanonical( |
| 1144 | \\const std = @import(); |
| 1145 | \\ |
| 1146 | ); |
| 1147 | |
| 1101 | 1148 | try testCanonical( |
| 1102 | 1149 | \\extern fn puts(s: &const u8) c_int; |
| 1103 | 1150 | \\ |