Sfoglia il codice sorgente

Fix #2818 (enforce `#partial label: switch`)

gingerBill 1 anno fa
parent
commit
9911b132d2
1 ha cambiato i file con 45 aggiunte e 0 eliminazioni
  1. 45 0
      src/parser.cpp

+ 45 - 0
src/parser.cpp

@@ -1361,6 +1361,22 @@ gb_internal Token peek_token(AstFile *f) {
 	return {};
 }
 
+gb_internal Token peek_token_n(AstFile *f, isize n) {
+	Token found = {};
+	for (isize i = f->curr_token_index+1; i < f->tokens.count; i++) {
+		Token tok = f->tokens[i];
+		if (tok.kind == Token_Comment) {
+			continue;
+		}
+		found = tok;
+		if (n-- == 0) {
+			return found;
+		}
+	}
+	return {};
+}
+
+
 gb_internal bool skip_possible_newline(AstFile *f) {
 	if (token_is_newline(f->curr_token)) {
 		advance_token(f);
@@ -2206,6 +2222,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 			Ast *tag = ast_basic_directive(f, token, name);
 			Ast *original_expr = parse_expr(f, lhs);
 			Ast *expr = unparen_expr(original_expr);
+			if (expr == nullptr) {
+				syntax_error(name, "Expected a compound literal after #%.*s", LIT(name.string));
+				return ast_bad_expr(f, token, name);
+			}
 			switch (expr->kind) {
 			case Ast_ArrayType:
 				syntax_error(expr, "#partial has been replaced with #sparse for non-contiguous enumerated array types");
@@ -3419,6 +3439,18 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
 	case Token_Colon:
 		expect_token_after(f, Token_Colon, "identifier list");
 		if ((flags&StmtAllowFlag_Label) && lhs.count == 1) {
+			bool is_partial = false;
+			Token partial_token = {};
+			if (f->curr_token.kind == Token_Hash) {
+				// NOTE(bill): This is purely for error messages
+				Token name = peek_token_n(f, 0);
+				if (name.kind == Token_Ident && name.string == "partial" &&
+				    peek_token_n(f, 1).kind == Token_switch) {
+					partial_token = expect_token(f, Token_Hash);
+					expect_token(f, Token_Ident);
+					is_partial = true;
+				}
+			}
 			switch (f->curr_token.kind) {
 			case Token_OpenBrace: // block statement
 			case Token_if:
@@ -3440,6 +3472,19 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
 					break;
 				}
 			#undef _SET_LABEL
+
+				if (is_partial) {
+					switch (stmt->kind) {
+					case Ast_SwitchStmt:
+						stmt->SwitchStmt.partial = true;
+						break;
+					case Ast_TypeSwitchStmt:
+						stmt->TypeSwitchStmt.partial = true;
+						break;
+					}
+					syntax_error(partial_token, "Incorrect use of directive, use '#partial %.*s: switch'", LIT(ast_token(name).string));
+				}
+
 				return stmt;
 			} break;
 			}