aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2025-02-22 17:58:14 +0000
committergingerBill <bill@gingerbill.org>2025-02-22 17:58:14 +0000
commitde755f95ecd5574f291d03b9488b5c4b8f07042c (patch)
tree0481f38bdd124f3b4ccd845070d1cf55da0ee2a7 /src/parser.cpp
parent875dbf3140935d43bd996443fbe5bb05a5044395 (diff)
Minor rearrange for parsing field lists
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp229
1 files changed, 116 insertions, 113 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index a3e95f451..f09590a55 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -4342,33 +4342,132 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
}
- if (f->curr_token.kind == Token_Colon) {
- if (f->prev_token.kind == Token_Comma) {
- syntax_error(f->prev_token, "Trailing comma before a colon is not allowed");
+ if (f->curr_token.kind != Token_Colon) {
+ // NOTE(bill): proc(Type, Type, Type)
+ for (AstAndFlags const &item : list) {
+ Ast *type = item.node;
+ Token token = blank_token;
+ if (allowed_flags&FieldFlag_Results) {
+ // NOTE(bill): Make this nothing and not `_`
+ token.string = str_lit("");
+ }
+
+ auto names = array_make<Ast *>(ast_allocator(f), 1);
+ token.pos = ast_token(type).pos;
+ names[0] = ast_ident(f, token);
+ u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags);
+ Token tag = {};
+ Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment);
+ array_add(&params, param);
+ }
+
+ if (name_count_) *name_count_ = total_name_count;
+ return ast_field_list(f, start_token, params);
+ }
+
+ // NOTE(bill): proc(ident, ident, ident: Type)
+
+ if (f->prev_token.kind == Token_Comma) {
+ syntax_error(f->prev_token, "Trailing comma before a colon is not allowed");
+ }
+ Array<Ast *> names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons
+ if (names.count == 0) {
+ syntax_error(f->curr_token, "Empty field declaration");
+ }
+ bool any_polymorphic_names = check_procedure_name_list(names);
+ u32 set_flags = 0;
+ if (list.count > 0) {
+ set_flags = list[0].flags;
+ }
+ set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags);
+ total_name_count += names.count;
+
+ Ast *type = nullptr;
+ Ast *default_value = nullptr;
+ Token tag = {};
+
+ expect_token_after(f, Token_Colon, "field list");
+ if (f->curr_token.kind != Token_Eq) {
+ type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
+ Ast *tt = unparen_expr(type);
+ if (tt == nullptr) {
+ syntax_error(f->prev_token, "Invalid type expression in field list");
+ } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
+ syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
+ }
+ }
+
+ if (allow_token(f, Token_Eq)) {
+ default_value = parse_expr(f, false);
+ if (!allow_default_parameters) {
+ syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
+ default_value = nullptr;
+ }
+ }
+
+ if (default_value != nullptr && names.count > 1) {
+ syntax_error(f->curr_token, "Default parameters can only be applied to single values");
+ }
+
+ if (allowed_flags == FieldFlag_Struct && default_value != nullptr) {
+ syntax_error(default_value, "Default parameters are not allowed for structs");
+ default_value = nullptr;
+ }
+
+ if (type != nullptr && type->kind == Ast_Ellipsis) {
+ if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis");
+ seen_ellipsis = true;
+ if (names.count != 1) {
+ syntax_error(type, "Variadic parameters can only have one field name");
}
- Array<Ast *> names = convert_to_ident_list(f, list, true, allow_poly_names); // Copy for semantic reasons
+ } else if (seen_ellipsis && default_value == nullptr) {
+ syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value");
+ }
+
+ if (type != nullptr && default_value == nullptr) {
+ if (f->curr_token.kind == Token_String) {
+ tag = expect_token(f, Token_String);
+ if ((allowed_flags & FieldFlag_Tags) == 0) {
+ syntax_error(tag, "Field tags are only allowed within structures");
+ }
+ }
+ }
+
+ bool more_fields = allow_field_separator(f);
+ Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment);
+ array_add(&params, param);
+
+ if (!more_fields) {
+ if (name_count_) *name_count_ = total_name_count;
+ return ast_field_list(f, start_token, params);
+ }
+
+ while (f->curr_token.kind != follow &&
+ f->curr_token.kind != Token_EOF &&
+ f->curr_token.kind != Token_Semicolon) {
+ CommentGroup *docs = f->lead_comment;
+
+ if (!is_signature) parse_enforce_tabs(f);
+ u32 set_flags = parse_field_prefixes(f);
+ Token tag = {};
+ Array<Ast *> names = parse_ident_list(f, allow_poly_names);
if (names.count == 0) {
syntax_error(f->curr_token, "Empty field declaration");
+ break;
}
bool any_polymorphic_names = check_procedure_name_list(names);
- u32 set_flags = 0;
- if (list.count > 0) {
- set_flags = list[0].flags;
- }
set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags);
total_name_count += names.count;
Ast *type = nullptr;
Ast *default_value = nullptr;
- Token tag = {};
-
expect_token_after(f, Token_Colon, "field list");
if (f->curr_token.kind != Token_Eq) {
type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
Ast *tt = unparen_expr(type);
- if (tt == nullptr) {
- syntax_error(f->prev_token, "Invalid type expression in field list");
- } else if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
+ if (is_signature && !any_polymorphic_names &&
+ tt != nullptr &&
+ tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
}
}
@@ -4385,11 +4484,6 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
syntax_error(f->curr_token, "Default parameters can only be applied to single values");
}
- if (allowed_flags == FieldFlag_Struct && default_value != nullptr) {
- syntax_error(default_value, "Default parameters are not allowed for structs");
- default_value = nullptr;
- }
-
if (type != nullptr && type->kind == Ast_Ellipsis) {
if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis");
seen_ellipsis = true;
@@ -4409,105 +4503,14 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
}
}
- bool more_fields = allow_field_separator(f);
+
+ bool ok = allow_field_separator(f);
Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment);
array_add(&params, param);
- if (!more_fields) {
- if (name_count_) *name_count_ = total_name_count;
- return ast_field_list(f, start_token, params);
- }
-
- while (f->curr_token.kind != follow &&
- f->curr_token.kind != Token_EOF &&
- f->curr_token.kind != Token_Semicolon) {
- CommentGroup *docs = f->lead_comment;
-
- if (!is_signature) parse_enforce_tabs(f);
- u32 set_flags = parse_field_prefixes(f);
- Token tag = {};
- Array<Ast *> names = parse_ident_list(f, allow_poly_names);
- if (names.count == 0) {
- syntax_error(f->curr_token, "Empty field declaration");
- break;
- }
- bool any_polymorphic_names = check_procedure_name_list(names);
- set_flags = check_field_prefixes(f, names.count, allowed_flags, set_flags);
- total_name_count += names.count;
-
- Ast *type = nullptr;
- Ast *default_value = nullptr;
- expect_token_after(f, Token_Colon, "field list");
- if (f->curr_token.kind != Token_Eq) {
- type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
- Ast *tt = unparen_expr(type);
- if (is_signature && !any_polymorphic_names &&
- tt != nullptr &&
- tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
- syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
- }
- }
-
- if (allow_token(f, Token_Eq)) {
- default_value = parse_expr(f, false);
- if (!allow_default_parameters) {
- syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
- default_value = nullptr;
- }
- }
-
- if (default_value != nullptr && names.count > 1) {
- syntax_error(f->curr_token, "Default parameters can only be applied to single values");
- }
-
- if (type != nullptr && type->kind == Ast_Ellipsis) {
- if (seen_ellipsis) syntax_error(type, "Extra variadic parameter after ellipsis");
- seen_ellipsis = true;
- if (names.count != 1) {
- syntax_error(type, "Variadic parameters can only have one field name");
- }
- } else if (seen_ellipsis && default_value == nullptr) {
- syntax_error(f->curr_token, "Extra parameter after ellipsis without a default value");
- }
-
- if (type != nullptr && default_value == nullptr) {
- if (f->curr_token.kind == Token_String) {
- tag = expect_token(f, Token_String);
- if ((allowed_flags & FieldFlag_Tags) == 0) {
- syntax_error(tag, "Field tags are only allowed within structures");
- }
- }
- }
-
-
- bool ok = allow_field_separator(f);
- Ast *param = ast_field(f, names, type, default_value, set_flags, tag, docs, f->line_comment);
- array_add(&params, param);
-
- if (!ok) {
- break;
- }
- }
-
- if (name_count_) *name_count_ = total_name_count;
- return ast_field_list(f, start_token, params);
- }
-
- for (AstAndFlags const &item : list) {
- Ast *type = item.node;
- Token token = blank_token;
- if (allowed_flags&FieldFlag_Results) {
- // NOTE(bill): Make this nothing and not `_`
- token.string = str_lit("");
+ if (!ok) {
+ break;
}
-
- auto names = array_make<Ast *>(ast_allocator(f), 1);
- token.pos = ast_token(type).pos;
- names[0] = ast_ident(f, token);
- u32 flags = check_field_prefixes(f, list.count, allowed_flags, item.flags);
- Token tag = {};
- Ast *param = ast_field(f, names, item.node, nullptr, flags, tag, docs, f->line_comment);
- array_add(&params, param);
}
if (name_count_) *name_count_ = total_name_count;