aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp88
1 files changed, 50 insertions, 38 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 8c26d8cba..b6a86a7c0 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2616,8 +2616,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) {
bool prefix_ellipsis = false;
if (f->curr_token.kind == Token_Ellipsis) {
prefix_ellipsis = true;
- ellipsis = f->curr_token;
- advance_token(f);
+ ellipsis = expect_token(f, Token_Ellipsis);
}
AstNode *arg = parse_expr(f, false);
@@ -2627,10 +2626,6 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) {
if (prefix_ellipsis) {
syntax_error(ellipsis, "`...` must be applied to value rather than the field name");
}
- if (f->curr_token.kind == Token_Ellipsis) {
- ellipsis = f->curr_token;
- advance_token(f);
- }
AstNode *value = parse_value(f);
arg = ast_field_value(f, arg, value, eq);
@@ -3339,12 +3334,13 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token)
enum FieldPrefixKind {
- FieldPrefix_Invalid,
+ FieldPrefix_Unknown = -1,
+ FieldPrefix_Invalid = 0,
- FieldPrefix_Using,
- FieldPrefix_NoAlias,
- FieldPrefix_CVarArg,
- FieldPrefix_Const,
+ FieldPrefix_using,
+ FieldPrefix_no_alias,
+ FieldPrefix_c_var_arg,
+ FieldPrefix_const,
};
FieldPrefixKind is_token_field_prefix(AstFile *f) {
@@ -3353,23 +3349,22 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
return FieldPrefix_Invalid;
case Token_using:
- return FieldPrefix_Using;
-
+ return FieldPrefix_using;
- case Token_Hash: {
+ case Token_Hash:
advance_token(f);
switch (f->curr_token.kind) {
case Token_Ident:
if (f->curr_token.string == "no_alias") {
- return FieldPrefix_NoAlias;
+ return FieldPrefix_no_alias;
} else if (f->curr_token.string == "c_vararg") {
- return FieldPrefix_CVarArg;
+ return FieldPrefix_c_var_arg;
} else if (f->curr_token.string == "const") {
- return FieldPrefix_Const;
+ return FieldPrefix_const;
}
break;
}
- } break;
+ return FieldPrefix_Unknown;
}
return FieldPrefix_Invalid;
}
@@ -3386,24 +3381,30 @@ u32 parse_field_prefixes(AstFile *f) {
if (kind == FieldPrefix_Invalid) {
break;
}
+ if (kind == FieldPrefix_Unknown) {
+ syntax_error(f->curr_token, "Unknown prefix kind `#%.*s`", LIT(f->curr_token.string));
+ advance_token(f);
+ continue;
+ }
+
switch (kind) {
- case FieldPrefix_Using: using_count += 1; advance_token(f); break;
- case FieldPrefix_NoAlias: no_alias_count += 1; advance_token(f); break;
- case FieldPrefix_CVarArg: c_vararg_count += 1; advance_token(f); break;
- case FieldPrefix_Const: const_count += 1; advance_token(f); break;
+ case FieldPrefix_using: using_count += 1; advance_token(f); break;
+ case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break;
+ case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break;
+ case FieldPrefix_const: const_count += 1; advance_token(f); break;
}
}
if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `#no_alias` in this field list");
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple `#c_vararg` in this field list");
- if (const_count > 1) syntax_error(f->curr_token, "Multiple `$` in this field list");
+ if (const_count > 1) syntax_error(f->curr_token, "Multiple `#const` in this field list");
u32 field_flags = 0;
if (using_count > 0) field_flags |= FieldFlag_using;
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
- if (const_count > 0) field_flags |= FieldFlag_const;
+ if (const_count > 0) field_flags |= FieldFlag_const;
return field_flags;
}
@@ -3534,10 +3535,10 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
u32 flags = parse_field_prefixes(f);
AstNode *param = parse_var_type(f, allow_ellipsis, allow_type_token);
if (param->kind == AstNode_Ellipsis) {
- if (seen_ellipsis) syntax_error(param, "Extra variadic parameter");
+ if (seen_ellipsis) syntax_error(param, "Extra variadic parameter after ellipsis");
seen_ellipsis = true;
} else if (seen_ellipsis) {
- syntax_error(param, "Extra parameter have variadic parameters");
+ syntax_error(param, "Extra parameter after ellipsis");
}
AstNodeAndFlags naf = {param, flags};
array_add(&list, naf);
@@ -3566,12 +3567,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
if (f->curr_token.kind != Token_Eq) {
type = parse_var_type(f, allow_ellipsis, allow_type_token);
}
- if (type != nullptr && type->kind == AstNode_Ellipsis) {
- if (seen_ellipsis) syntax_error(type, "Extra variadic parameter");
- seen_ellipsis = true;
- } else if (seen_ellipsis) {
- syntax_error(f->curr_token, "Extra variadic parameter");
- }
+
if (allow_token(f, Token_Eq)) {
// TODO(bill): Should this be true==lhs or false==rhs?
default_value = parse_expr(f, false);
@@ -3584,6 +3580,16 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
syntax_error(f->curr_token, "Default parameters can only be applied to single values");
}
+ if (type != nullptr && type->kind == AstNode_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");
+ }
+
parse_expect_field_separator(f, type);
AstNode *param = ast_field(f, names, type, default_value, set_flags, docs, f->line_comment);
array_add(&params, param);
@@ -3608,12 +3614,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
if (f->curr_token.kind != Token_Eq) {
type = parse_var_type(f, allow_ellipsis, allow_type_token);
}
- if (type != nullptr && type->kind == AstNode_Ellipsis) {
- if (seen_ellipsis) syntax_error(type, "Extra variadic parameter");
- seen_ellipsis = true;
- } else if (seen_ellipsis) {
- syntax_error(f->curr_token, "Extra variadic parameter");
- }
+
if (allow_token(f, Token_Eq)) {
// TODO(bill): Should this be true==lhs or false==rhs?
default_value = parse_expr(f, false);
@@ -3626,6 +3627,17 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
syntax_error(f->curr_token, "Default parameters can only be applied to single values");
}
+ if (type != nullptr && type->kind == AstNode_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");
+ }
+
+
bool ok = parse_expect_field_separator(f, param);
AstNode *param = ast_field(f, names, type, default_value, set_flags, docs, f->line_comment);
array_add(&params, param);