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 {...@@ -22,6 +22,7 @@ pub const Node = struct {
22 StringLiteral,22 StringLiteral,
23 BuiltinCall,23 BuiltinCall,
24 LineComment,24 LineComment,
25 TestDecl,
25 };26 };
2627
27 pub fn iterate(base: &Node, index: usize) ?&Node {28 pub fn iterate(base: &Node, index: usize) ?&Node {
...@@ -39,6 +40,7 @@ pub const Node = struct {...@@ -39,6 +40,7 @@ pub const Node = struct {
39 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),40 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),
40 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),41 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
41 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),42 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
43 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),
42 };44 };
43 }45 }
4446
...@@ -57,6 +59,7 @@ pub const Node = struct {...@@ -57,6 +59,7 @@ pub const Node = struct {
57 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),59 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),
58 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),60 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
59 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),61 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
62 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),
60 };63 };
61 }64 }
6265
...@@ -75,6 +78,7 @@ pub const Node = struct {...@@ -75,6 +78,7 @@ pub const Node = struct {
75 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),78 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),
76 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),79 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
77 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),80 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
81 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
78 };82 };
79 }83 }
80};84};
...@@ -476,3 +480,28 @@ pub const NodeLineComment = struct {...@@ -476,3 +480,28 @@ pub const NodeLineComment = struct {
476 return self.lines.at(self.lines.len - 1);480 return self.lines.at(self.lines.len - 1);
477 }481 }
478};482};
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 {...@@ -171,6 +171,22 @@ pub const Parser = struct {
171 stack.append(State { .TopLevelExtern = token }) catch unreachable;171 stack.append(State { .TopLevelExtern = token }) catch unreachable;
172 continue;172 continue;
173 },173 },
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 },
174 Token.Id.Eof => {190 Token.Id.Eof => {
175 root_node.eof_token = token;191 root_node.eof_token = token;
176 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};192 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};
...@@ -733,6 +749,20 @@ pub const Parser = struct {...@@ -733,6 +749,20 @@ pub const Parser = struct {
733 return node;749 return node;
734 }750 }
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
736 fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,766 fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,
737 cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto767 cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
738 {768 {
...@@ -867,6 +897,14 @@ pub const Parser = struct {...@@ -867,6 +897,14 @@ pub const Parser = struct {
867 return node;897 return node;
868 }898 }
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
870 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {908 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
871 const loc = self.tokenizer.getTokenLocation(token);909 const loc = self.tokenizer.getTokenLocation(token);
872 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, token.line + 1, token.column + 1, args);910 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, token.line + 1, token.column + 1, args);
...@@ -1032,7 +1070,11 @@ pub const Parser = struct {...@@ -1032,7 +1070,11 @@ pub const Parser = struct {
1032 ast.Node.Id.VarDecl => {1070 ast.Node.Id.VarDecl => {
1033 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);1071 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
1034 try stack.append(RenderState { .VarDecl = var_decl});1072 try stack.append(RenderState { .VarDecl = var_decl});
10351073 },
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 });
1036 },1078 },
1037 else => unreachable,1079 else => unreachable,
1038 }1080 }
...@@ -1201,6 +1243,7 @@ pub const Parser = struct {...@@ -1201,6 +1243,7 @@ pub const Parser = struct {
12011243
1202 ast.Node.Id.Root,1244 ast.Node.Id.Root,
1203 ast.Node.Id.VarDecl,1245 ast.Node.Id.VarDecl,
1246 ast.Node.Id.TestDecl,
1204 ast.Node.Id.ParamDecl => unreachable,1247 ast.Node.Id.ParamDecl => unreachable,
1205 },1248 },
1206 RenderState.FnProtoRParen => |fn_proto| {1249 RenderState.FnProtoRParen => |fn_proto| {
...@@ -1422,4 +1465,12 @@ test "zig fmt" {...@@ -1422,4 +1465,12 @@ test "zig fmt" {
1422 \\}1465 \\}
1423 \\1466 \\
1424 );1467 );
1468
1469 try testCanonical(
1470 \\test "test name" {
1471 \\ const a = 1;
1472 \\ var b = 1;
1473 \\}
1474 \\
1475 );
1425}1476}