aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2021-05-20 12:15:14 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2021-05-20 12:15:14 +0200
commit44ee0f2cdc773fc3ba3261de076b8a8a7fb64f03 (patch)
treec408237d1bd2e6bfcb0c5526d9c0d8cdb97bbf69 /src/parser.cpp
parent50035f257eb33769211ca49a30c51f9a20440a0e (diff)
parent92abddddc5ca4be622e93856c7246159b594e9e9 (diff)
Merge branch 'master' into prototype-fmt
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp334
1 files changed, 159 insertions, 175 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index a7e4c9162..a5180b4dd 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1,110 +1,4 @@
-Token ast_token(Ast *node) {
- switch (node->kind) {
- case Ast_Ident: return node->Ident.token;
- case Ast_Implicit: return node->Implicit;
- case Ast_Undef: return node->Undef;
- case Ast_BasicLit: return node->BasicLit.token;
- case Ast_BasicDirective: return node->BasicDirective.token;
- case Ast_ProcGroup: return node->ProcGroup.token;
- case Ast_ProcLit: return ast_token(node->ProcLit.type);
- case Ast_CompoundLit:
- if (node->CompoundLit.type != nullptr) {
- return ast_token(node->CompoundLit.type);
- }
- return node->CompoundLit.open;
-
- case Ast_TagExpr: return node->TagExpr.token;
- case Ast_BadExpr: return node->BadExpr.begin;
- case Ast_UnaryExpr: return node->UnaryExpr.op;
- case Ast_BinaryExpr: return ast_token(node->BinaryExpr.left);
- case Ast_ParenExpr: return node->ParenExpr.open;
- case Ast_CallExpr: return ast_token(node->CallExpr.proc);
- case Ast_SelectorExpr:
- if (node->SelectorExpr.selector != nullptr) {
- return ast_token(node->SelectorExpr.selector);
- }
- return node->SelectorExpr.token;
- case Ast_SelectorCallExpr:
- if (node->SelectorCallExpr.expr != nullptr) {
- return ast_token(node->SelectorCallExpr.expr);
- }
- return node->SelectorCallExpr.token;
- case Ast_ImplicitSelectorExpr:
- if (node->ImplicitSelectorExpr.selector != nullptr) {
- return ast_token(node->ImplicitSelectorExpr.selector);
- }
- return node->ImplicitSelectorExpr.token;
- case Ast_IndexExpr: return node->IndexExpr.open;
- case Ast_SliceExpr: return node->SliceExpr.open;
- case Ast_Ellipsis: return node->Ellipsis.token;
- case Ast_FieldValue: return node->FieldValue.eq;
- case Ast_DerefExpr: return node->DerefExpr.op;
- case Ast_TernaryExpr: return ast_token(node->TernaryExpr.cond);
- case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
- case Ast_TernaryWhenExpr: return ast_token(node->TernaryWhenExpr.x);
- case Ast_TypeAssertion: return ast_token(node->TypeAssertion.expr);
- case Ast_TypeCast: return node->TypeCast.token;
- case Ast_AutoCast: return node->AutoCast.token;
- case Ast_InlineAsmExpr: return node->InlineAsmExpr.token;
-
- case Ast_BadStmt: return node->BadStmt.begin;
- case Ast_EmptyStmt: return node->EmptyStmt.token;
- case Ast_ExprStmt: return ast_token(node->ExprStmt.expr);
- case Ast_TagStmt: return node->TagStmt.token;
- case Ast_AssignStmt: return node->AssignStmt.op;
- case Ast_BlockStmt: return node->BlockStmt.open;
- case Ast_IfStmt: return node->IfStmt.token;
- case Ast_WhenStmt: return node->WhenStmt.token;
- case Ast_ReturnStmt: return node->ReturnStmt.token;
- case Ast_ForStmt: return node->ForStmt.token;
- case Ast_RangeStmt: return node->RangeStmt.token;
- case Ast_UnrollRangeStmt: return node->UnrollRangeStmt.unroll_token;
- case Ast_CaseClause: return node->CaseClause.token;
- case Ast_SwitchStmt: return node->SwitchStmt.token;
- case Ast_TypeSwitchStmt: return node->TypeSwitchStmt.token;
- case Ast_DeferStmt: return node->DeferStmt.token;
- case Ast_BranchStmt: return node->BranchStmt.token;
- case Ast_UsingStmt: return node->UsingStmt.token;
-
- case Ast_BadDecl: return node->BadDecl.begin;
- case Ast_Label: return node->Label.token;
-
- case Ast_ValueDecl: return ast_token(node->ValueDecl.names[0]);
- case Ast_PackageDecl: return node->PackageDecl.token;
- case Ast_ImportDecl: return node->ImportDecl.token;
- case Ast_ForeignImportDecl: return node->ForeignImportDecl.token;
-
- case Ast_ForeignBlockDecl: return node->ForeignBlockDecl.token;
-
- case Ast_Attribute:
- return node->Attribute.token;
-
- case Ast_Field:
- if (node->Field.names.count > 0) {
- return ast_token(node->Field.names[0]);
- }
- return ast_token(node->Field.type);
- case Ast_FieldList:
- return node->FieldList.token;
-
- case Ast_TypeidType: return node->TypeidType.token;
- case Ast_HelperType: return node->HelperType.token;
- case Ast_DistinctType: return node->DistinctType.token;
- case Ast_PolyType: return node->PolyType.token;
- case Ast_ProcType: return node->ProcType.token;
- case Ast_RelativeType: return ast_token(node->RelativeType.tag);
- case Ast_PointerType: return node->PointerType.token;
- case Ast_ArrayType: return node->ArrayType.token;
- case Ast_DynamicArrayType: return node->DynamicArrayType.token;
- case Ast_StructType: return node->StructType.token;
- case Ast_UnionType: return node->UnionType.token;
- case Ast_EnumType: return node->EnumType.token;
- case Ast_BitSetType: return node->BitSetType.token;
- case Ast_MapType: return node->MapType.token;
- }
-
- return empty_token;
-}
+#include "parser_pos.cpp"
Token token_end_of_line(AstFile *f, Token tok) {
u8 const *start = f->tokenizer.start + tok.pos.offset;
@@ -116,6 +10,48 @@ Token token_end_of_line(AstFile *f, Token tok) {
return tok;
}
+gbString get_file_line_as_string(TokenPos const &pos, i32 *offset_) {
+ AstFile *file = get_ast_file_from_id(pos.file_id);
+ if (file == nullptr) {
+ return nullptr;
+ }
+ isize offset = pos.offset;
+
+ u8 *start = file->tokenizer.start;
+ u8 *end = file->tokenizer.end;
+ isize len = end-start;
+ if (len < offset) {
+ return nullptr;
+ }
+
+ u8 *pos_offset = start+offset;
+
+ u8 *line_start = pos_offset;
+ u8 *line_end = pos_offset;
+ while (line_start >= start) {
+ if (*line_start == '\n') {
+ line_start += 1;
+ break;
+ }
+ line_start -= 1;
+ }
+
+ while (line_end < end) {
+ if (*line_end == '\n') {
+ line_end -= 1;
+ break;
+ }
+ line_end += 1;
+ }
+ String the_line = make_string(line_start, line_end-line_start);
+ the_line = string_trim_whitespace(the_line);
+
+ if (offset_) *offset_ = cast(i32)(pos_offset - the_line.text);
+
+ return gb_string_make_length(heap_allocator(), the_line.text, the_line.len);
+}
+
+
isize ast_node_size(AstKind kind) {
return align_formula_isize(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind], gb_align_of(void *));
@@ -241,11 +177,6 @@ Ast *clone_ast(Ast *node) {
n->FieldValue.value = clone_ast(n->FieldValue.value);
break;
- case Ast_TernaryExpr:
- n->TernaryExpr.cond = clone_ast(n->TernaryExpr.cond);
- n->TernaryExpr.x = clone_ast(n->TernaryExpr.x);
- n->TernaryExpr.y = clone_ast(n->TernaryExpr.y);
- break;
case Ast_TernaryIfExpr:
n->TernaryIfExpr.x = clone_ast(n->TernaryIfExpr.x);
n->TernaryIfExpr.cond = clone_ast(n->TernaryIfExpr.cond);
@@ -438,12 +369,15 @@ Ast *clone_ast(Ast *node) {
void error(Ast *node, char const *fmt, ...) {
Token token = {};
+ TokenPos end_pos = {};
if (node != nullptr) {
token = ast_token(node);
+ end_pos = ast_end_pos(node);
}
+
va_list va;
va_start(va, fmt);
- error_va(token, fmt, va);
+ error_va(token.pos, end_pos, fmt, va);
va_end(va);
if (node != nullptr && node->file != nullptr) {
node->file->error_count += 1;
@@ -457,7 +391,7 @@ void error_no_newline(Ast *node, char const *fmt, ...) {
}
va_list va;
va_start(va, fmt);
- error_no_newline_va(token, fmt, va);
+ error_no_newline_va(token.pos, fmt, va);
va_end(va);
if (node != nullptr && node->file != nullptr) {
node->file->error_count += 1;
@@ -465,16 +399,28 @@ void error_no_newline(Ast *node, char const *fmt, ...) {
}
void warning(Ast *node, char const *fmt, ...) {
+ Token token = {};
+ TokenPos end_pos = {};
+ if (node != nullptr) {
+ token = ast_token(node);
+ end_pos = ast_end_pos(node);
+ }
va_list va;
va_start(va, fmt);
- warning_va(ast_token(node), fmt, va);
+ warning_va(token.pos, end_pos, fmt, va);
va_end(va);
}
void syntax_error(Ast *node, char const *fmt, ...) {
+ Token token = {};
+ TokenPos end_pos = {};
+ if (node != nullptr) {
+ token = ast_token(node);
+ end_pos = ast_end_pos(node);
+ }
va_list va;
va_start(va, fmt);
- syntax_error_va(ast_token(node), fmt, va);
+ syntax_error_va(token.pos, end_pos, fmt, va);
va_end(va);
if (node != nullptr && node->file != nullptr) {
node->file->error_count += 1;
@@ -646,7 +592,7 @@ Ast *ast_basic_lit(AstFile *f, Token basic_lit) {
return result;
}
-Ast *ast_basic_directive(AstFile *f, Token token, String name) {
+Ast *ast_basic_directive(AstFile *f, Token token, Token name) {
Ast *result = alloc_ast_node(f, Ast_BasicDirective);
result->BasicDirective.token = token;
result->BasicDirective.name = name;
@@ -698,13 +644,6 @@ Ast *ast_compound_lit(AstFile *f, Ast *type, Array<Ast *> const &elems, Token op
}
-Ast *ast_ternary_expr(AstFile *f, Ast *cond, Ast *x, Ast *y) {
- Ast *result = alloc_ast_node(f, Ast_TernaryExpr);
- result->TernaryExpr.cond = cond;
- result->TernaryExpr.x = x;
- result->TernaryExpr.y = y;
- return result;
-}
Ast *ast_ternary_if_expr(AstFile *f, Ast *x, Ast *cond, Ast *y) {
Ast *result = alloc_ast_node(f, Ast_TernaryIfExpr);
result->TernaryIfExpr.x = x;
@@ -1357,6 +1296,7 @@ Token expect_token_after(AstFile *f, TokenKind kind, char const *msg) {
bool is_token_range(TokenKind kind) {
switch (kind) {
case Token_Ellipsis:
+ case Token_RangeFull:
case Token_RangeHalf:
return true;
}
@@ -1587,6 +1527,10 @@ void expect_semicolon(AstFile *f, Ast *s) {
return;
}
+ if (f->curr_token.kind == Token_EOF) {
+ return;
+ }
+
if (s != nullptr) {
bool insert_semi = (f->tokenizer.flags & TokenizerFlag_InsertSemicolon) != 0;
if (insert_semi) {
@@ -2007,35 +1951,28 @@ Ast *parse_operand(AstFile *f, bool lhs) {
Token name = expect_token(f, Token_Ident);
if (name.string == "type") {
return ast_helper_type(f, token, parse_type(f));
- } /* else if (name.string == "no_deferred") {
- operand = parse_expr(f, false);
- if (unparen_expr(operand)->kind != Ast_CallExpr) {
- syntax_error(operand, "#no_deferred can only be applied to procedure calls");
- operand = ast_bad_expr(f, token, f->curr_token);
- }
- operand->state_flags |= StateFlag_no_deferred;
- } */ else if (name.string == "file") {
- return ast_basic_directive(f, token, name.string);
- } else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
- } else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
- } else if (name.string == "caller_location") { return ast_basic_directive(f, token, name.string);
+ } else if (name.string == "file") {
+ return ast_basic_directive(f, token, name);
+ } else if (name.string == "line") { return ast_basic_directive(f, token, name);
+ } else if (name.string == "procedure") { return ast_basic_directive(f, token, name);
+ } else if (name.string == "caller_location") { return ast_basic_directive(f, token, name);
} else if (name.string == "location") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
return parse_call_expr(f, tag);
} else if (name.string == "load") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
return parse_call_expr(f, tag);
} else if (name.string == "assert") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
return parse_call_expr(f, tag);
} else if (name.string == "defined") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
return parse_call_expr(f, tag);
} else if (name.string == "config") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
return parse_call_expr(f, tag);
} else if (name.string == "soa" || name.string == "simd") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
Ast *original_type = parse_type(f);
Ast *type = unparen_expr(original_type);
switch (type->kind) {
@@ -2047,7 +1984,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
}
return original_type;
} else if (name.string == "partial") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
Ast *original_type = parse_type(f);
Ast *type = unparen_expr(original_type);
switch (type->kind) {
@@ -2059,6 +1996,10 @@ Ast *parse_operand(AstFile *f, bool lhs) {
return original_type;
} else if (name.string == "bounds_check") {
Ast *operand = parse_expr(f, lhs);
+ if (operand == nullptr) {
+ syntax_error(token, "Invalid expresssion for #%.*s", LIT(name.string));
+ return nullptr;
+ }
operand->state_flags |= StateFlag_bounds_check;
if ((operand->state_flags & StateFlag_no_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
@@ -2066,13 +2007,17 @@ Ast *parse_operand(AstFile *f, bool lhs) {
return operand;
} else if (name.string == "no_bounds_check") {
Ast *operand = parse_expr(f, lhs);
+ if (operand == nullptr) {
+ syntax_error(token, "Invalid expresssion for #%.*s", LIT(name.string));
+ return nullptr;
+ }
operand->state_flags |= StateFlag_no_bounds_check;
if ((operand->state_flags & StateFlag_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
}
return operand;
} else if (name.string == "relative") {
- Ast *tag = ast_basic_directive(f, token, name.string);
+ Ast *tag = ast_basic_directive(f, token, name);
tag = parse_call_expr(f, tag);
Ast *type = parse_type(f);
return ast_relative_type(f, tag, type);
@@ -2158,6 +2103,8 @@ Ast *parse_operand(AstFile *f, bool lhs) {
return type;
}
+ skip_possible_newline_for_literal(f);
+
if (allow_token(f, Token_Undef)) {
if (where_token.kind != Token_Invalid) {
syntax_error(where_token, "'where' clauses are not allowed on procedure literals without a defined body (replaced with ---)");
@@ -2170,6 +2117,14 @@ Ast *parse_operand(AstFile *f, bool lhs) {
body = parse_body(f);
f->curr_proc = curr_proc;
+ // Apply the tags directly to the body rather than the type
+ if (tags & ProcTag_no_bounds_check) {
+ body->state_flags |= StateFlag_no_bounds_check;
+ }
+ if (tags & ProcTag_bounds_check) {
+ body->state_flags |= StateFlag_bounds_check;
+ }
+
return ast_proc_lit(f, type, body, tags, where_token, where_clauses);
} else if (allow_token(f, Token_do)) {
Ast *curr_proc = f->curr_proc;
@@ -2317,7 +2272,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
f->expr_level = prev_level;
}
-
+ skip_possible_newline_for_literal(f);
Token open = expect_token_after(f, Token_OpenBrace, "struct");
isize name_count = 0;
@@ -2394,6 +2349,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
}
+ skip_possible_newline_for_literal(f);
Token open = expect_token_after(f, Token_OpenBrace, "union");
while (f->curr_token.kind != Token_CloseBrace &&
@@ -2418,6 +2374,8 @@ Ast *parse_operand(AstFile *f, bool lhs) {
if (f->curr_token.kind != Token_OpenBrace) {
base_type = parse_type(f);
}
+
+ skip_possible_newline_for_literal(f);
Token open = expect_token(f, Token_OpenBrace);
Array<Ast *> values = parse_element_list(f);
@@ -2509,6 +2467,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
}
}
+ skip_possible_newline_for_literal(f);
Token open = expect_token(f, Token_OpenBrace);
Ast *asm_string = parse_expr(f, false);
expect_token(f, Token_Comma);
@@ -2673,6 +2632,7 @@ Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
switch (f->curr_token.kind) {
case Token_Ellipsis:
+ case Token_RangeFull:
case Token_RangeHalf:
// NOTE(bill): Do not err yet
case Token_Colon:
@@ -2684,6 +2644,7 @@ Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
switch (f->curr_token.kind) {
case Token_Ellipsis:
+ case Token_RangeFull:
case Token_RangeHalf:
syntax_error(f->curr_token, "Expected a colon, not a range");
/* fallthrough */
@@ -2722,6 +2683,16 @@ Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
}
break;
+ case Token_Increment:
+ case Token_Decrement:
+ if (!lhs) {
+ Token token = advance_token(f);
+ syntax_error(token, "Postfix '%.*s' operator is not supported", LIT(token.string));
+ } else {
+ loop = false;
+ }
+ break;
+
default:
loop = false;
break;
@@ -2752,16 +2723,26 @@ Ast *parse_unary_expr(AstFile *f, bool lhs) {
return ast_auto_cast(f, token, expr);
}
+
case Token_Add:
case Token_Sub:
- case Token_Not:
case Token_Xor:
- case Token_And: {
+ case Token_And:
+ case Token_Not: {
Token token = advance_token(f);
Ast *expr = parse_unary_expr(f, lhs);
return ast_unary_expr(f, token, expr);
}
+ case Token_Increment:
+ case Token_Decrement: {
+ Token token = advance_token(f);
+ syntax_error(token, "Unary '%.*s' operator is not supported", LIT(token.string));
+ Ast *expr = parse_unary_expr(f, lhs);
+ return ast_unary_expr(f, token, expr);
+ }
+
+
case Token_Period: {
Token token = expect_token(f, Token_Period);
Ast *ident = parse_ident(f);
@@ -2790,6 +2771,7 @@ i32 token_precedence(AstFile *f, TokenKind t) {
case Token_when:
return 1;
case Token_Ellipsis:
+ case Token_RangeFull:
case Token_RangeHalf:
if (!f->allow_range) {
return 0;
@@ -2857,7 +2839,7 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
Ast *x = parse_expr(f, lhs);
Token token_c = expect_token(f, Token_Colon);
Ast *y = parse_expr(f, lhs);
- expr = ast_ternary_expr(f, cond, x, y);
+ expr = ast_ternary_if_expr(f, x, cond, y);
} else if (op.kind == Token_if) {
Ast *x = expr;
// Token_if
@@ -2979,7 +2961,7 @@ Ast *parse_foreign_block(AstFile *f, Token token) {
defer (f->in_foreign_block = prev_in_foreign_block);
f->in_foreign_block = true;
-
+ skip_possible_newline_for_literal(f);
open = expect_token(f, Token_OpenBrace);
while (f->curr_token.kind != Token_CloseBrace &&
@@ -3151,6 +3133,13 @@ Ast *parse_simple_stmt(AstFile *f, u32 flags) {
return ast_bad_stmt(f, token, f->curr_token);
}
+ switch (token.kind) {
+ case Token_Increment:
+ case Token_Decrement:
+ advance_token(f);
+ syntax_error(token, "Postfix '%.*s' statement is not supported", LIT(token.string));
+ break;
+ }
#if 0
@@ -3220,6 +3209,7 @@ ProcCallingConvention string_to_calling_convention(String s) {
if (s == "fastcall") return ProcCC_FastCall;
if (s == "fast") return ProcCC_FastCall;
if (s == "none") return ProcCC_None;
+ if (s == "naked") return ProcCC_Naked;
return ProcCC_Invalid;
}
@@ -3896,12 +3886,6 @@ Ast *parse_return_stmt(AstFile *f) {
while (f->curr_token.kind != Token_Semicolon) {
Ast *arg = parse_expr(f, false);
- // if (f->curr_token.kind == Token_Eq) {
- // Token eq = expect_token(f, Token_Eq);
- // Ast *value = parse_value(f);
- // arg = ast_field_value(f, arg, value, eq);
- // }
-
array_add(&results, arg);
if (f->curr_token.kind != Token_Comma ||
f->curr_token.kind == Token_EOF) {
@@ -3966,7 +3950,7 @@ Ast *parse_for_stmt(AstFile *f) {
}
}
- if (!is_range && allow_token(f, Token_Semicolon)) {
+ if (!is_range && parse_control_statement_semicolon_separator(f)) {
init = cond;
cond = nullptr;
if (f->curr_token.kind != Token_Semicolon) {
@@ -4022,7 +4006,7 @@ Ast *parse_case_clause(AstFile *f, bool is_type) {
}
f->allow_range = prev_allow_range;
f->allow_in_expr = prev_allow_in_expr;
- expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
+ expect_token(f, Token_Colon);
Array<Ast *> stmts = parse_stmt_list(f);
return ast_case_clause(f, token, list, stmts);
@@ -4332,6 +4316,16 @@ Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) {
return ast_unroll_range_stmt(f, unroll_token, for_token, val0, val1, in_token, expr, body);
}
+void parse_check_directive_for_empty_statement(Ast *s, Token const &name) {
+ if (s != nullptr && s->kind == Ast_EmptyStmt) {
+ if (s->EmptyStmt.token.string == "\n") {
+ syntax_error(name, "#%.*s cannot be followed by a newline", LIT(name.string));
+ } else {
+ syntax_error(name, "#%.*s cannot be applied to an empty statement ';'", LIT(name.string));
+ }
+ }
+}
+
Ast *parse_stmt(AstFile *f) {
Ast *s = nullptr;
Token token = f->curr_token;
@@ -4438,6 +4432,7 @@ Ast *parse_stmt(AstFile *f) {
if (tag == "bounds_check") {
s = parse_stmt(f);
+ parse_check_directive_for_empty_statement(s, name);
s->state_flags |= StateFlag_bounds_check;
if ((s->state_flags & StateFlag_no_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
@@ -4445,27 +4440,12 @@ Ast *parse_stmt(AstFile *f) {
return s;
} else if (tag == "no_bounds_check") {
s = parse_stmt(f);
+ parse_check_directive_for_empty_statement(s, name);
s->state_flags |= StateFlag_no_bounds_check;
if ((s->state_flags & StateFlag_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
}
return s;
- } else if (tag == "complete") {
- s = parse_stmt(f);
- switch (s->kind) {
- case Ast_SwitchStmt:
- s->SwitchStmt.partial = false;
- syntax_warning(token, "#complete is now the default and has been replaced with its opposite: #partial");
- break;
- case Ast_TypeSwitchStmt:
- s->TypeSwitchStmt.partial = false;
- syntax_warning(token, "#complete is now the default and has been replaced with its opposite: #partial");
- break;
- default:
- syntax_error(token, "#complete can only be applied to a switch statement");
- break;
- }
- return s;
} else if (tag == "partial") {
s = parse_stmt(f);
switch (s->kind) {
@@ -4475,16 +4455,19 @@ Ast *parse_stmt(AstFile *f) {
case Ast_TypeSwitchStmt:
s->TypeSwitchStmt.partial = true;
break;
+ case Ast_EmptyStmt:
+ parse_check_directive_for_empty_statement(s, name);
+ break;
default:
syntax_error(token, "#partial can only be applied to a switch statement");
break;
}
return s;
} else if (tag == "assert") {
- Ast *t = ast_basic_directive(f, hash_token, tag);
+ Ast *t = ast_basic_directive(f, hash_token, name);
return ast_expr_stmt(f, parse_call_expr(f, t));
} else if (tag == "panic") {
- Ast *t = ast_basic_directive(f, hash_token, tag);
+ Ast *t = ast_basic_directive(f, hash_token, name);
return ast_expr_stmt(f, parse_call_expr(f, t));
} else if (name.string == "force_inline" ||
name.string == "force_no_inline") {
@@ -4571,6 +4554,7 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) {
GB_ASSERT(f != nullptr);
f->fullpath = string_trim_whitespace(fullpath); // Just in case
set_file_path_string(f->id, fullpath);
+ set_ast_file_from_id(f->id, f);
if (!string_ends_with(f->fullpath, str_lit(".odin"))) {
return ParseFile_WrongExtension;
}