| ... | @@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b | ... | @@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 676 | } | 676 | } |
| 677 | | 677 | |
| 678 | /* | 678 | /* |
| 679 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | 679 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl |
| 680 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" | 680 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" |
| 681 | */ | 681 | */ |
| 682 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 682 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| ... | @@ -791,13 +791,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -791,13 +791,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 791 | if (container_decl) | 791 | if (container_decl) |
| 792 | return container_decl; | 792 | return container_decl; |
| 793 | | 793 | |
| 794 | if (token->id == TokenIdKeywordExtern) { | | |
| 795 | *token_index += 1; | | |
| 796 | AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate); | | |
| 797 | node->data.fn_proto.is_extern = true; | | |
| 798 | return node; | | |
| 799 | } | | |
| 800 | | | |
| 801 | if (!mandatory) | 794 | if (!mandatory) |
| 802 | return nullptr; | 795 | return nullptr; |
| 803 | | 796 | |
| ... | @@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { | ... | @@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1534 | } | 1527 | } |
| 1535 | | 1528 | |
| 1536 | /* | 1529 | /* |
| 1537 | VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression | 1530 | VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression |
| 1538 | */ | 1531 | */ |
| 1539 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, | 1532 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, |
| 1540 | VisibMod visib_mod) | 1533 | VisibMod visib_mod, bool is_comptime, bool is_export) |
| 1541 | { | 1534 | { |
| 1542 | Token *first_token = &pc->tokens->at(*token_index); | 1535 | Token *first_token = &pc->tokens->at(*token_index); |
| 1543 | Token *var_token; | 1536 | Token *var_token; |
| 1544 | | 1537 | |
| 1545 | bool is_const; | 1538 | bool is_const; |
| 1546 | bool is_comptime; | 1539 | if (first_token->id == TokenIdKeywordVar) { |
| 1547 | if (first_token->id == TokenIdKeywordCompTime) { | | |
| 1548 | is_comptime = true; | | |
| 1549 | var_token = &pc->tokens->at(*token_index + 1); | | |
| 1550 | | | |
| 1551 | if (var_token->id == TokenIdKeywordVar) { | | |
| 1552 | is_const = false; | | |
| 1553 | } else if (var_token->id == TokenIdKeywordConst) { | | |
| 1554 | is_const = true; | | |
| 1555 | } else if (mandatory) { | | |
| 1556 | ast_invalid_token_error(pc, var_token); | | |
| 1557 | } else { | | |
| 1558 | return nullptr; | | |
| 1559 | } | | |
| 1560 | | | |
| 1561 | *token_index += 2; | | |
| 1562 | } else if (first_token->id == TokenIdKeywordVar) { | | |
| 1563 | is_comptime = false; | | |
| 1564 | is_const = false; | 1540 | is_const = false; |
| 1565 | var_token = first_token; | 1541 | var_token = first_token; |
| 1566 | *token_index += 1; | 1542 | *token_index += 1; |
| 1567 | } else if (first_token->id == TokenIdKeywordConst) { | 1543 | } else if (first_token->id == TokenIdKeywordConst) { |
| 1568 | is_comptime = false; | | |
| 1569 | is_const = true; | 1544 | is_const = true; |
| 1570 | var_token = first_token; | 1545 | var_token = first_token; |
| 1571 | *token_index += 1; | 1546 | *token_index += 1; |
| ... | @@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to | ... | @@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1577 | | 1552 | |
| 1578 | AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token); | 1553 | AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token); |
| 1579 | | 1554 | |
| 1580 | node->data.variable_declaration.is_inline = is_comptime; | 1555 | node->data.variable_declaration.is_comptime = is_comptime; |
| 1581 | node->data.variable_declaration.is_const = is_const; | 1556 | node->data.variable_declaration.is_const = is_const; |
| 1582 | node->data.variable_declaration.visib_mod = visib_mod; | 1557 | node->data.variable_declaration.visib_mod = visib_mod; |
| 1583 | | 1558 | |
| ... | @@ -1620,6 +1595,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to | ... | @@ -1620,6 +1595,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1620 | return node; | 1595 | return node; |
| 1621 | } | 1596 | } |
| 1622 | | 1597 | |
| | 1598 | /* |
| | 1599 | GlobalVarDecl = option("export") VariableDeclaration ";" |
| | 1600 | */ |
| | 1601 | static AstNode *ast_parse_global_var_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { |
| | 1602 | Token *first_token = &pc->tokens->at(*token_index); |
| | 1603 | |
| | 1604 | bool is_export = false;; |
| | 1605 | if (first_token->id == TokenIdKeywordExport) { |
| | 1606 | *token_index += 1; |
| | 1607 | is_export = true; |
| | 1608 | } |
| | 1609 | |
| | 1610 | AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, is_export); |
| | 1611 | if (node == nullptr) { |
| | 1612 | if (is_export) { |
| | 1613 | *token_index -= 1; |
| | 1614 | } |
| | 1615 | return nullptr; |
| | 1616 | } |
| | 1617 | return node; |
| | 1618 | } |
| | 1619 | |
| | 1620 | /* |
| | 1621 | LocalVarDecl = option("comptime") VariableDeclaration |
| | 1622 | */ |
| | 1623 | static AstNode *ast_parse_local_var_decl(ParseContext *pc, size_t *token_index) { |
| | 1624 | Token *first_token = &pc->tokens->at(*token_index); |
| | 1625 | |
| | 1626 | bool is_comptime = false;; |
| | 1627 | if (first_token->id == TokenIdKeywordCompTime) { |
| | 1628 | *token_index += 1; |
| | 1629 | is_comptime = true; |
| | 1630 | } |
| | 1631 | |
| | 1632 | AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate, is_comptime, false); |
| | 1633 | if (node == nullptr) { |
| | 1634 | if (is_comptime) { |
| | 1635 | *token_index -= 1; |
| | 1636 | } |
| | 1637 | return nullptr; |
| | 1638 | } |
| | 1639 | return node; |
| | 1640 | } |
| | 1641 | |
| 1623 | /* | 1642 | /* |
| 1624 | BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression | 1643 | BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression |
| 1625 | */ | 1644 | */ |
| ... | @@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2171 | for (;;) { | 2190 | for (;;) { |
| 2172 | AstNode *statement_node = ast_parse_label(pc, token_index, false); | 2191 | AstNode *statement_node = ast_parse_label(pc, token_index, false); |
| 2173 | if (!statement_node) | 2192 | if (!statement_node) |
| 2174 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); | 2193 | statement_node = ast_parse_local_var_decl(pc, token_index); |
| 2175 | if (!statement_node) | 2194 | if (!statement_node) |
| 2176 | statement_node = ast_parse_defer_expr(pc, token_index); | 2195 | statement_node = ast_parse_defer_expr(pc, token_index); |
| 2177 | if (!statement_node) | 2196 | if (!statement_node) |
| ... | @@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2213 | } | 2232 | } |
| 2214 | | 2233 | |
| 2215 | /* | 2234 | /* |
| 2216 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) | 2235 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) |
| 2217 | */ | 2236 | */ |
| 2218 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { | 2237 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2219 | Token *first_token = &pc->tokens->at(*token_index); | 2238 | Token *first_token = &pc->tokens->at(*token_index); |
| 2220 | Token *fn_token; | 2239 | Token *fn_token; |
| 2221 | | 2240 | |
| 2222 | CallingConvention cc; | 2241 | CallingConvention cc; |
| | 2242 | bool is_extern = false; |
| 2223 | if (first_token->id == TokenIdKeywordColdCC) { | 2243 | if (first_token->id == TokenIdKeywordColdCC) { |
| 2224 | *token_index += 1; | 2244 | *token_index += 1; |
| 2225 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); | 2245 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| ... | @@ -2232,8 +2252,13 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2232,8 +2252,13 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2232 | *token_index += 1; | 2252 | *token_index += 1; |
| 2233 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); | 2253 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| 2234 | cc = CallingConventionStdcall; | 2254 | cc = CallingConventionStdcall; |
| | 2255 | } else if (first_token->id == TokenIdKeywordExtern) { |
| | 2256 | *token_index += 1; |
| | 2257 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| | 2258 | cc = CallingConventionC; |
| 2235 | } else if (first_token->id == TokenIdKeywordFn) { | 2259 | } else if (first_token->id == TokenIdKeywordFn) { |
| 2236 | fn_token = first_token; | 2260 | fn_token = first_token; |
| | 2261 | is_extern = true; |
| 2237 | *token_index += 1; | 2262 | *token_index += 1; |
| 2238 | cc = CallingConventionUnspecified; | 2263 | cc = CallingConventionUnspecified; |
| 2239 | } else if (mandatory) { | 2264 | } else if (mandatory) { |
| ... | @@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2246 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); | 2271 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); |
| 2247 | node->data.fn_proto.visib_mod = visib_mod; | 2272 | node->data.fn_proto.visib_mod = visib_mod; |
| 2248 | node->data.fn_proto.cc = cc; | 2273 | node->data.fn_proto.cc = cc; |
| | 2274 | node->data.fn_proto.is_extern = is_extern; |
| 2249 | | 2275 | |
| 2250 | Token *fn_name = &pc->tokens->at(*token_index); | 2276 | Token *fn_name = &pc->tokens->at(*token_index); |
| 2251 | | 2277 | |
| ... | @@ -2286,35 +2312,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2286,35 +2312,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2286 | } | 2312 | } |
| 2287 | | 2313 | |
| 2288 | /* | 2314 | /* |
| 2289 | FnDef = option("inline" | "extern") FnProto Block | 2315 | FnDef = option("inline" | "export") FnProto Block |
| 2290 | */ | 2316 | */ |
| 2291 | static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { | 2317 | static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2292 | Token *first_token = &pc->tokens->at(*token_index); | 2318 | Token *first_token = &pc->tokens->at(*token_index); |
| 2293 | bool is_inline; | 2319 | bool is_inline; |
| 2294 | bool is_extern; | 2320 | bool is_export; |
| 2295 | if (first_token->id == TokenIdKeywordInline) { | 2321 | if (first_token->id == TokenIdKeywordInline) { |
| 2296 | *token_index += 1; | 2322 | *token_index += 1; |
| 2297 | is_inline = true; | 2323 | is_inline = true; |
| 2298 | is_extern = false; | 2324 | is_export = false; |
| 2299 | } else if (first_token->id == TokenIdKeywordExtern) { | 2325 | } else if (first_token->id == TokenIdKeywordExport) { |
| 2300 | *token_index += 1; | 2326 | *token_index += 1; |
| 2301 | is_extern = true; | 2327 | is_export = true; |
| 2302 | is_inline = false; | 2328 | is_inline = false; |
| 2303 | } else { | 2329 | } else { |
| 2304 | is_inline = false; | 2330 | is_inline = false; |
| 2305 | is_extern = false; | 2331 | is_export = false; |
| 2306 | } | 2332 | } |
| 2307 | | 2333 | |
| 2308 | AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod); | 2334 | AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod); |
| 2309 | if (!fn_proto) { | 2335 | if (!fn_proto) { |
| 2310 | if (is_inline || is_extern) { | 2336 | if (is_inline || is_export) { |
| 2311 | *token_index -= 1; | 2337 | *token_index -= 1; |
| 2312 | } | 2338 | } |
| 2313 | return nullptr; | 2339 | return nullptr; |
| 2314 | } | 2340 | } |
| 2315 | | 2341 | |
| 2316 | fn_proto->data.fn_proto.is_inline = is_inline; | 2342 | fn_proto->data.fn_proto.is_inline = is_inline; |
| 2317 | fn_proto->data.fn_proto.is_extern = is_extern; | 2343 | fn_proto->data.fn_proto.is_export = is_export; |
| 2318 | | 2344 | |
| 2319 | Token *semi_token = &pc->tokens->at(*token_index); | 2345 | Token *semi_token = &pc->tokens->at(*token_index); |
| 2320 | if (semi_token->id == TokenIdSemicolon) { | 2346 | if (semi_token->id == TokenIdSemicolon) { |
| ... | @@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo | ... | @@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo |
| 2360 | return fn_proto_node; | 2386 | return fn_proto_node; |
| 2361 | } | 2387 | } |
| 2362 | | 2388 | |
| 2363 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | 2389 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, false); |
| 2364 | if (var_decl_node) { | 2390 | if (var_decl_node) { |
| 2365 | ast_eat_token(pc, token_index, TokenIdSemicolon); | 2391 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2366 | | 2392 | |
| ... | @@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2473 | continue; | 2499 | continue; |
| 2474 | } | 2500 | } |
| 2475 | | 2501 | |
| 2476 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | 2502 | AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); |
| 2477 | if (var_decl_node) { | 2503 | if (var_decl_node) { |
| 2478 | ast_eat_token(pc, token_index, TokenIdSemicolon); | 2504 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2479 | node->data.container_decl.decls.append(var_decl_node); | 2505 | node->data.container_decl.decls.append(var_decl_node); |
| ... | @@ -2566,7 +2592,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) | ... | @@ -2566,7 +2592,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) |
| 2566 | | 2592 | |
| 2567 | /* | 2593 | /* |
| 2568 | TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl | 2594 | TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl |
| 2569 | TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | 2595 | TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) |
| 2570 | */ | 2596 | */ |
| 2571 | static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) { | 2597 | static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2572 | for (;;) { | 2598 | for (;;) { |
| ... | @@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig | ... | @@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig |
| 2615 | continue; | 2641 | continue; |
| 2616 | } | 2642 | } |
| 2617 | | 2643 | |
| 2618 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | 2644 | AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); |
| 2619 | if (var_decl_node) { | 2645 | if (var_decl_node) { |
| 2620 | ast_eat_token(pc, token_index, TokenIdSemicolon); | 2646 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2621 | top_level_decls->append(var_decl_node); | 2647 | top_level_decls->append(var_decl_node); |