authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-29 13:43:17+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-29 13:43:17+02:00
log9df2a6a5027be17cba7f11ac9d7c106c3497647b
tree8c20dd9d84f5957cb0f666ee80b0b3957cd91677
parent032fccf6151ff201ce4b8c7ab28ca460fed794c0

std.zig.parser can now parse top level test declarations


2 files changed, 81 insertions(+), 1 deletions(-)

std/zig/ast.zig+29
......@@ -22,6 +22,7 @@ pub const Node = struct {
2222 StringLiteral,
2323 BuiltinCall,
2424 LineComment,
25 TestDecl,
2526 };
2627
2728 pub fn iterate(base: &Node, index: usize) ?&Node {
......@@ -39,6 +40,7 @@ pub const Node = struct {
3940 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),
4041 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
4142 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
43 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),
4244 };
4345 }
4446
......@@ -57,6 +59,7 @@ pub const Node = struct {
5759 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),
5860 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
5961 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
62 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),
6063 };
6164 }
6265
......@@ -75,6 +78,7 @@ pub const Node = struct {
7578 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),
7679 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
7780 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
81 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
7882 };
7983 }
8084};
......@@ -476,3 +480,28 @@ pub const NodeLineComment = struct {
476480 return self.lines.at(self.lines.len - 1);
477481 }
478482};
483
484pub const NodeTestDecl = struct {
485 base: Node,
486 test_token: Token,
487 name_token: Token,
488 body_node: &Node,
489
490 pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node {
491 var i = index;
492
493 if (i < 1) return self.body_node;
494 i -= 1;
495
496 return null;
497 }
498
499 pub fn firstToken(self: &NodeTestDecl) Token {
500 return self.test_token;
501 }
502
503 pub fn lastToken(self: &NodeTestDecl) Token {
504 return self.body_node.lastToken();
505 }
506};
507
std/zig/parser.zig+52-1
......@@ -171,6 +171,22 @@ pub const Parser = struct {
171171 stack.append(State { .TopLevelExtern = token }) catch unreachable;
172172 continue;
173173 },
174 Token.Id.Keyword_test => {
175 stack.append(State.TopLevel) catch unreachable;
176
177 const name_token = self.getNextToken();
178 if (name_token.id != Token.Id.StringLiteral)
179 return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.StringLiteral), @tagName(name_token.id));
180
181 const lbrace = self.getNextToken();
182 if (lbrace.id != Token.Id.LBrace)
183 return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id));
184
185 const block = try self.createBlock(arena, token);
186 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, name_token, block);
187 try stack.append(State { .Block = block });
188 continue;
189 },
174190 Token.Id.Eof => {
175191 root_node.eof_token = token;
176192 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};
......@@ -733,6 +749,20 @@ pub const Parser = struct {
733749 return node;
734750 }
735751
752 fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name_token: &const Token,
753 block: &ast.NodeBlock) !&ast.NodeTestDecl
754 {
755 const node = try arena.create(ast.NodeTestDecl);
756
757 *node = ast.NodeTestDecl {
758 .base = self.initNode(ast.Node.Id.TestDecl),
759 .test_token = *test_token,
760 .name_token = *name_token,
761 .body_node = &block.base,
762 };
763 return node;
764 }
765
736766 fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,
737767 cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
738768 {
......@@ -867,6 +897,14 @@ pub const Parser = struct {
867897 return node;
868898 }
869899
900 fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
901 test_token: &const Token, name_token: &const Token, block: &ast.NodeBlock) !&ast.NodeTestDecl
902 {
903 const node = try self.createTestDecl(arena, test_token, name_token, block);
904 try list.append(&node.base);
905 return node;
906 }
907
870908 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
871909 const loc = self.tokenizer.getTokenLocation(token);
872910 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, token.line + 1, token.column + 1, args);
......@@ -1032,7 +1070,11 @@ pub const Parser = struct {
10321070 ast.Node.Id.VarDecl => {
10331071 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
10341072 try stack.append(RenderState { .VarDecl = var_decl});
1035
1073 },
1074 ast.Node.Id.TestDecl => {
1075 const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl);
1076 try stream.print("test {} ", self.tokenizer.getTokenSlice(test_decl.name_token));
1077 try stack.append(RenderState { .Expression = test_decl.body_node });
10361078 },
10371079 else => unreachable,
10381080 }
......@@ -1201,6 +1243,7 @@ pub const Parser = struct {
12011243
12021244 ast.Node.Id.Root,
12031245 ast.Node.Id.VarDecl,
1246 ast.Node.Id.TestDecl,
12041247 ast.Node.Id.ParamDecl => unreachable,
12051248 },
12061249 RenderState.FnProtoRParen => |fn_proto| {
......@@ -1422,4 +1465,12 @@ test "zig fmt" {
14221465 \\}
14231466 \\
14241467 );
1468
1469 try testCanonical(
1470 \\test "test name" {
1471 \\ const a = 1;
1472 \\ var b = 1;
1473 \\}
1474 \\
1475 );
14251476}