disallow declarations between container fields
This commit is contained in:
parent
6c907a3509
commit
fff00c3bbb
@ -526,6 +526,15 @@ static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ContainerFieldState {
|
||||||
|
// no fields have been seen
|
||||||
|
ContainerFieldStateNone,
|
||||||
|
// currently parsing fields
|
||||||
|
ContainerFieldStateSeen,
|
||||||
|
// saw fields and then a declaration after them
|
||||||
|
ContainerFieldStateEnd,
|
||||||
|
};
|
||||||
|
|
||||||
// ContainerMembers
|
// ContainerMembers
|
||||||
// <- TestDecl ContainerMembers
|
// <- TestDecl ContainerMembers
|
||||||
// / TopLevelComptime ContainerMembers
|
// / TopLevelComptime ContainerMembers
|
||||||
@ -537,17 +546,29 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
|
|||||||
AstNodeContainerDecl res = {};
|
AstNodeContainerDecl res = {};
|
||||||
Buf tld_doc_comment_buf = BUF_INIT;
|
Buf tld_doc_comment_buf = BUF_INIT;
|
||||||
buf_resize(&tld_doc_comment_buf, 0);
|
buf_resize(&tld_doc_comment_buf, 0);
|
||||||
|
ContainerFieldState field_state = ContainerFieldStateNone;
|
||||||
|
Token *first_token = nullptr;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ast_parse_container_doc_comments(pc, &tld_doc_comment_buf);
|
ast_parse_container_doc_comments(pc, &tld_doc_comment_buf);
|
||||||
|
|
||||||
|
Token *peeked_token = peek_token(pc);
|
||||||
|
|
||||||
AstNode *test_decl = ast_parse_test_decl(pc);
|
AstNode *test_decl = ast_parse_test_decl(pc);
|
||||||
if (test_decl != nullptr) {
|
if (test_decl != nullptr) {
|
||||||
|
if (field_state == ContainerFieldStateSeen) {
|
||||||
|
field_state = ContainerFieldStateEnd;
|
||||||
|
first_token = peeked_token;
|
||||||
|
}
|
||||||
res.decls.append(test_decl);
|
res.decls.append(test_decl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *top_level_comptime = ast_parse_top_level_comptime(pc);
|
AstNode *top_level_comptime = ast_parse_top_level_comptime(pc);
|
||||||
if (top_level_comptime != nullptr) {
|
if (top_level_comptime != nullptr) {
|
||||||
|
if (field_state == ContainerFieldStateSeen) {
|
||||||
|
field_state = ContainerFieldStateEnd;
|
||||||
|
first_token = peeked_token;
|
||||||
|
}
|
||||||
res.decls.append(top_level_comptime);
|
res.decls.append(top_level_comptime);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -555,11 +576,17 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
|
|||||||
Buf doc_comment_buf = BUF_INIT;
|
Buf doc_comment_buf = BUF_INIT;
|
||||||
ast_parse_doc_comments(pc, &doc_comment_buf);
|
ast_parse_doc_comments(pc, &doc_comment_buf);
|
||||||
|
|
||||||
|
peeked_token = peek_token(pc);
|
||||||
|
|
||||||
Token *visib_token = eat_token_if(pc, TokenIdKeywordPub);
|
Token *visib_token = eat_token_if(pc, TokenIdKeywordPub);
|
||||||
VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate;
|
VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate;
|
||||||
|
|
||||||
AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf);
|
AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf);
|
||||||
if (top_level_decl != nullptr) {
|
if (top_level_decl != nullptr) {
|
||||||
|
if (field_state == ContainerFieldStateSeen) {
|
||||||
|
field_state = ContainerFieldStateEnd;
|
||||||
|
first_token = peeked_token;
|
||||||
|
}
|
||||||
res.decls.append(top_level_decl);
|
res.decls.append(top_level_decl);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -572,6 +599,16 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
|
|||||||
|
|
||||||
AstNode *container_field = ast_parse_container_field(pc);
|
AstNode *container_field = ast_parse_container_field(pc);
|
||||||
if (container_field != nullptr) {
|
if (container_field != nullptr) {
|
||||||
|
switch (field_state) {
|
||||||
|
case ContainerFieldStateNone:
|
||||||
|
field_state = ContainerFieldStateSeen;
|
||||||
|
break;
|
||||||
|
case ContainerFieldStateSeen:
|
||||||
|
break;
|
||||||
|
case ContainerFieldStateEnd:
|
||||||
|
ast_error(pc, first_token, "declarations are not allowed between container fields");
|
||||||
|
}
|
||||||
|
|
||||||
assert(container_field->type == NodeTypeStructField);
|
assert(container_field->type == NodeTypeStructField);
|
||||||
container_field->data.struct_field.doc_comments = doc_comment_buf;
|
container_field->data.struct_field.doc_comments = doc_comment_buf;
|
||||||
container_field->data.struct_field.comptime_token = comptime_token;
|
container_field->data.struct_field.comptime_token = comptime_token;
|
||||||
|
@ -2,6 +2,21 @@ const tests = @import("tests.zig");
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.add("declaration between fields",
|
||||||
|
\\const S = struct {
|
||||||
|
\\ a: usize,
|
||||||
|
\\ const foo = 2;
|
||||||
|
\\ const bar = 2;
|
||||||
|
\\ const baz = 2;
|
||||||
|
\\ b: usize,
|
||||||
|
\\};
|
||||||
|
\\comptime {
|
||||||
|
\\ _ = S;
|
||||||
|
\\}
|
||||||
|
, &[_][]const u8{
|
||||||
|
"tmp.zig:3:5: error: declarations are not allowed between container fields",
|
||||||
|
});
|
||||||
|
|
||||||
cases.add("non-extern function with var args",
|
cases.add("non-extern function with var args",
|
||||||
\\fn foo(args: ...) void {}
|
\\fn foo(args: ...) void {}
|
||||||
\\export fn entry() void {
|
\\export fn entry() void {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user