From 5765cbd2de9d31bc1135d3b8f7e1a579078bc3ba Mon Sep 17 00:00:00 2001 From: hryx Date: Mon, 22 Apr 2019 00:14:21 -0700 Subject: Allow tag expr for enum but not struct --- src/parser.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 9172e21b92..9e72954b64 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2750,12 +2750,19 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { } // ContainerDeclType -// <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? +// <- KEYWORD_struct +// / KEYWORD_enum (LPAREN Expr RPAREN)? // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? static AstNode *ast_parse_container_decl_type(ParseContext *pc) { Token *first = eat_token_if(pc, TokenIdKeywordStruct); - if (first == nullptr) - first = eat_token_if(pc, TokenIdKeywordEnum); + if (first != nullptr) { + AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); + res->data.container_decl.init_arg_expr = nullptr; + res->data.container_decl.kind = ContainerKindStruct; + return res; + } + + first = eat_token_if(pc, TokenIdKeywordEnum); if (first != nullptr) { AstNode *init_arg_expr = nullptr; if (eat_token_if(pc, TokenIdLParen) != nullptr) { @@ -2764,9 +2771,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { } AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); res->data.container_decl.init_arg_expr = init_arg_expr; - res->data.container_decl.kind = first->id == TokenIdKeywordStruct - ? ContainerKindStruct - : ContainerKindEnum; + res->data.container_decl.kind = ContainerKindEnum; return res; } -- cgit v1.2.3 From 6b10f03b4a868cc02fc0535193ea0108c77ddd1f Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Fri, 10 May 2019 16:09:58 +0200 Subject: Fixes and simplifications for stage 1 parser --- src/ir.cpp | 7 ++--- src/parser.cpp | 74 +++++++++++++++++++------------------------------ test/compile_errors.zig | 9 ------ 3 files changed, 31 insertions(+), 59 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index d333708402..f764cbd983 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5433,10 +5433,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod add_node_error(irb->codegen, variable_declaration->section_expr, buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); } - if (variable_declaration->threadlocal_tok != nullptr) { - add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok, - buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol))); - } + + // Parser should ensure that this never happens + assert(variable_declaration->threadlocal_tok == nullptr); // Temporarily set the name of the IrExecutable to the VariableDeclaration // so that the struct or enum from the init expression inherits the name. diff --git a/src/parser.cpp b/src/parser.cpp index 9e72954b64..36ca3ed863 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -577,7 +577,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { // TopLevelDecl // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) -// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl +// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl // / KEYWORD_use Expr SEMICOLON static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { Token *first = eat_token_if(pc, TokenIdKeywordExport); @@ -632,13 +632,18 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { ast_invalid_token_error(pc, peek_token(pc)); } + Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); var_decl->data.variable_declaration.visib_mod = visib_mod; + var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; return var_decl; } + if (thread_local_kw != nullptr) + put_back_token(pc); + AstNode *fn_proto = ast_parse_fn_proto(pc); if (fn_proto != nullptr) { AstNode *body = ast_parse_block(pc); @@ -741,17 +746,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON static AstNode *ast_parse_var_decl(ParseContext *pc) { - Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst); if (mut_kw == nullptr) mut_kw = eat_token_if(pc, TokenIdKeywordVar); - if (mut_kw == nullptr) { - if (thread_local_kw == nullptr) { - return nullptr; - } else { - ast_invalid_token_error(pc, peek_token(pc)); - } - } + if (mut_kw == nullptr) + return nullptr; + Token *identifier = expect_token(pc, TokenIdSymbol); AstNode *type_expr = nullptr; if (eat_token_if(pc, TokenIdColon) != nullptr) @@ -766,7 +766,6 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { expect_token(pc, TokenIdSemicolon); AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); - res->data.variable_declaration.threadlocal_tok = thread_local_kw; res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst; res->data.variable_declaration.symbol = token_buf(identifier); res->data.variable_declaration.type = type_expr; @@ -952,17 +951,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) static AstNode *ast_parse_loop_statement(ParseContext *pc) { - Token *label = ast_parse_block_label(pc); - Token *first = label; - Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); - if (first == nullptr) - first = inline_token; - AstNode *for_statement = ast_parse_for_statement(pc); if (for_statement != nullptr) { assert(for_statement->type == NodeTypeForExpr); - for_statement->data.for_expr.name = token_buf(label); for_statement->data.for_expr.is_inline = inline_token != nullptr; return for_statement; } @@ -970,12 +962,11 @@ static AstNode *ast_parse_loop_statement(ParseContext *pc) { AstNode *while_statement = ast_parse_while_statement(pc); if (while_statement != nullptr) { assert(while_statement->type == NodeTypeWhileExpr); - while_statement->data.while_expr.name = token_buf(label); while_statement->data.while_expr.is_inline = inline_token != nullptr; return while_statement; } - if (first != nullptr) + if (inline_token != nullptr) ast_invalid_token_error(pc, peek_token(pc)); return nullptr; } @@ -1117,7 +1108,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc) { // CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? static AstNode *ast_parse_compare_expr(ParseContext *pc) { - return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_compare_op, ast_parse_bitwise_expr); + return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_compare_op, ast_parse_bitwise_expr); } // BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* @@ -1246,11 +1237,8 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { } AstNode *block = ast_parse_block(pc); - if (block != nullptr) { - assert(block->type == NodeTypeBlock); - block->data.block.name = token_buf(label); + if (block != nullptr) return block; - } AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc); if (curly_suffix != nullptr) @@ -1672,32 +1660,26 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto static AstNode *ast_parse_container_decl(ParseContext *pc) { - Token *extern_token = eat_token_if(pc, TokenIdKeywordExtern); - if (extern_token != nullptr) { - AstNode *res = ast_parse_container_decl_auto(pc); - if (res == nullptr) { - put_back_token(pc); - return nullptr; - } + Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern); + if (layout_token == nullptr) + layout_token = eat_token_if(pc, TokenIdKeywordPacked); - assert(res->type == NodeTypeContainerDecl); - res->line = extern_token->start_line; - res->column = extern_token->start_column; - res->data.container_decl.layout = ContainerLayoutExtern; - return res; + AstNode *res = ast_parse_container_decl_auto(pc); + if (res == nullptr) { + if (layout_token != nullptr) + put_back_token(pc); + return nullptr; } - Token *packed_token = eat_token_if(pc, TokenIdKeywordPacked); - if (packed_token != nullptr) { - AstNode *res = ast_expect(pc, ast_parse_container_decl_auto); - assert(res->type == NodeTypeContainerDecl); - res->line = packed_token->start_line; - res->column = packed_token->start_column; - res->data.container_decl.layout = ContainerLayoutPacked; - return res; + assert(res->type == NodeTypeContainerDecl); + if (layout_token != nullptr) { + res->line = layout_token->start_line; + res->column = layout_token->start_column; + res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern + ? ContainerLayoutExtern + : ContainerLayoutPacked; } - - return ast_parse_container_decl_auto(pc); + return res; } // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 40256f660a..63835e8c1b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -587,15 +587,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:13: error: threadlocal variable cannot be constant", ); - cases.add( - "threadlocal qualifier on local variable", - \\export fn entry() void { - \\ threadlocal var x: i32 = 1234; - \\} - , - "tmp.zig:2:5: error: function-local variable 'x' cannot be threadlocal", - ); - cases.add( "@bitCast same size but bit count mismatch", \\export fn entry(byte: u8) void { -- cgit v1.2.3 From c051904903e65f6bd2cb9d71f52688ce9d17d52d Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Sat, 11 May 2019 18:48:52 +0200 Subject: Fixed parser for extern threadlocal variables --- src/parser.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 36ca3ed863..197cb3a33e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -591,17 +591,22 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { lib_name = eat_token_if(pc, TokenIdStringLiteral); if (first->id != TokenIdKeywordInline) { + Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); var_decl->line = first->start_line; var_decl->column = first->start_column; + var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; var_decl->data.variable_declaration.visib_mod = visib_mod; var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern; var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport; var_decl->data.variable_declaration.lib_name = token_buf(lib_name); return var_decl; } + + if (thread_local_kw != nullptr) + put_back_token(pc); } AstNode *fn_proto = ast_parse_fn_proto(pc); -- cgit v1.2.3 From 6cf7fb1177848c2f2a20c1f4093b1e003c477911 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Sat, 11 May 2019 20:51:59 +0200 Subject: fixes #2235 --- src/parser.cpp | 18 +++++++++++++----- test/stage1/behavior/enum.zig | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 197cb3a33e..583accfd72 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1158,10 +1158,6 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) { // / Block // / CurlySuffixExpr static AstNode *ast_parse_primary_expr(ParseContext *pc) { - AstNode *enum_lit = ast_parse_enum_lit(pc); - if (enum_lit != nullptr) - return enum_lit; - AstNode *asm_expr = ast_parse_asm_expr(pc); if (asm_expr != nullptr) return asm_expr; @@ -1496,6 +1492,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { // <- BUILTINIDENTIFIER FnCallArguments // / CHAR_LITERAL // / ContainerDecl +// / DOT IDENTIFIER // / ErrorSetDecl // / FLOAT // / FnProto @@ -1556,6 +1553,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { if (container_decl != nullptr) return container_decl; + AstNode *enum_lit = ast_parse_enum_lit(pc); + if (enum_lit != nullptr) + return enum_lit; + AstNode *error_set_decl = ast_parse_error_set_decl(pc); if (error_set_decl != nullptr) return error_set_decl; @@ -1958,7 +1959,14 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { return nullptr; Token *name = expect_token(pc, TokenIdSymbol); - expect_token(pc, TokenIdEq); + if (eat_token_if(pc, TokenIdEq) == nullptr) { + // Because ".Name" can also be intepreted as an enum literal, we should put back + // those two tokens again so that the parser can try to parse them as the enum + // literal later. + put_back_token(pc); + put_back_token(pc); + return nullptr; + } AstNode *expr = ast_expect(pc, ast_parse_expr); AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first); diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index f584fc265a..70515ec35b 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -923,3 +923,18 @@ test "peer type resolution with enum literal" { expect(Items.two == .two); expect(.two == Items.two); } + +test "enum literal in array literal" { + const Items = enum { + one, + two, + }; + + const array = []Items { + .one, + .two, + }; + + expect(array[0] == .one); + expect(array[1] == .two); +} -- cgit v1.2.3