| ... | ... | @@ -50,22 +50,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8) Allocator.Error!Ast { |
| 50 | 50 | const estimated_node_count = (tokens.len + 2) / 2; |
| 51 | 51 | try parser.nodes.ensureTotalCapacity(gpa, estimated_node_count); |
| 52 | 52 | |
| 53 | | // Root node must be index 0. |
| 54 | | // Root <- skip ContainerMembers eof |
| 55 | | parser.nodes.appendAssumeCapacity(.{ |
| 56 | | .tag = .root, |
| 57 | | .main_token = 0, |
| 58 | | .data = undefined, |
| 59 | | }); |
| 60 | | const root_members = try parser.parseContainerMembers(); |
| 61 | | const root_decls = try root_members.toSpan(&parser); |
| 62 | | if (parser.token_tags[parser.tok_i] != .eof) { |
| 63 | | try parser.warnExpected(.eof); |
| 64 | | } |
| 65 | | parser.nodes.items(.data)[0] = .{ |
| 66 | | .lhs = root_decls.start, |
| 67 | | .rhs = root_decls.end, |
| 68 | | }; |
| 53 | try parser.parseRoot(); |
| 69 | 54 | |
| 70 | 55 | // TODO experiment with compacting the MultiArrayList slices here |
| 71 | 56 | return Ast{ |
| ... | ... | @@ -237,12 +222,33 @@ const Parser = struct { |
| 237 | 222 | return error.ParseError; |
| 238 | 223 | } |
| 239 | 224 | |
| 225 | /// Root <- skip container_doc_comment? ContainerMembers eof |
| 226 | fn parseRoot(p: *Parser) !void { |
| 227 | // Root node must be index 0. |
| 228 | p.nodes.appendAssumeCapacity(.{ |
| 229 | .tag = .root, |
| 230 | .main_token = 0, |
| 231 | .data = undefined, |
| 232 | }); |
| 233 | const root_members = try p.parseContainerMembers(); |
| 234 | const root_decls = try root_members.toSpan(p); |
| 235 | if (p.token_tags[p.tok_i] != .eof) { |
| 236 | try p.warnExpected(.eof); |
| 237 | } |
| 238 | p.nodes.items(.data)[0] = .{ |
| 239 | .lhs = root_decls.start, |
| 240 | .rhs = root_decls.end, |
| 241 | }; |
| 242 | } |
| 243 | |
| 240 | 244 | /// ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations) |
| 245 | /// |
| 241 | 246 | /// ContainerDeclarations |
| 242 | 247 | /// <- TestDecl ContainerDeclarations |
| 243 | 248 | /// / ComptimeDecl ContainerDeclarations |
| 244 | 249 | /// / doc_comment? KEYWORD_pub? Decl ContainerDeclarations |
| 245 | 250 | /// / |
| 251 | /// |
| 246 | 252 | /// ComptimeDecl <- KEYWORD_comptime Block |
| 247 | 253 | fn parseContainerMembers(p: *Parser) !Members { |
| 248 | 254 | const scratch_top = p.scratch.items.len; |
| ... | ... | @@ -887,7 +893,9 @@ const Parser = struct { |
| 887 | 893 | } |
| 888 | 894 | } |
| 889 | 895 | |
| 890 | | /// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 896 | /// ContainerField |
| 897 | /// <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON TypeExpr)? ByteAlign? (EQUAL Expr)? |
| 898 | /// / doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? !KEYWORD_fn TypeExpr ByteAlign? (EQUAL Expr)? |
| 891 | 899 | fn expectContainerField(p: *Parser) !Node.Index { |
| 892 | 900 | var main_token = p.tok_i; |
| 893 | 901 | _ = p.eatToken(.keyword_comptime); |
| ... | ... | @@ -1173,6 +1181,7 @@ const Parser = struct { |
| 1173 | 1181 | } |
| 1174 | 1182 | |
| 1175 | 1183 | /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload |
| 1184 | /// |
| 1176 | 1185 | /// ForStatement |
| 1177 | 1186 | /// <- ForPrefix BlockExpr ( KEYWORD_else Statement )? |
| 1178 | 1187 | /// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement ) |
| ... | ... | @@ -1234,6 +1243,7 @@ const Parser = struct { |
| 1234 | 1243 | } |
| 1235 | 1244 | |
| 1236 | 1245 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 1246 | /// |
| 1237 | 1247 | /// WhileStatement |
| 1238 | 1248 | /// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? |
| 1239 | 1249 | /// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) |
| ... | ... | @@ -1368,13 +1378,18 @@ const Parser = struct { |
| 1368 | 1378 | } |
| 1369 | 1379 | |
| 1370 | 1380 | /// AssignExpr <- Expr (AssignOp Expr)? |
| 1381 | /// |
| 1371 | 1382 | /// AssignOp |
| 1372 | 1383 | /// <- ASTERISKEQUAL |
| 1384 | /// / ASTERISKPIPEEQUAL |
| 1373 | 1385 | /// / SLASHEQUAL |
| 1374 | 1386 | /// / PERCENTEQUAL |
| 1375 | 1387 | /// / PLUSEQUAL |
| 1388 | /// / PLUSPIPEEQUAL |
| 1376 | 1389 | /// / MINUSEQUAL |
| 1390 | /// / MINUSPIPEEQUAL |
| 1377 | 1391 | /// / LARROW2EQUAL |
| 1392 | /// / LARROW2PIPEEQUAL |
| 1378 | 1393 | /// / RARROW2EQUAL |
| 1379 | 1394 | /// / AMPERSANDEQUAL |
| 1380 | 1395 | /// / CARETEQUAL |
| ... | ... | @@ -1553,6 +1568,7 @@ const Parser = struct { |
| 1553 | 1568 | } |
| 1554 | 1569 | |
| 1555 | 1570 | /// PrefixExpr <- PrefixOp* PrimaryExpr |
| 1571 | /// |
| 1556 | 1572 | /// PrefixOp |
| 1557 | 1573 | /// <- EXCLAMATIONMARK |
| 1558 | 1574 | /// / MINUS |
| ... | ... | @@ -1591,17 +1607,21 @@ const Parser = struct { |
| 1591 | 1607 | } |
| 1592 | 1608 | |
| 1593 | 1609 | /// TypeExpr <- PrefixTypeOp* ErrorUnionExpr |
| 1610 | /// |
| 1594 | 1611 | /// PrefixTypeOp |
| 1595 | 1612 | /// <- QUESTIONMARK |
| 1596 | 1613 | /// / KEYWORD_anyframe MINUSRARROW |
| 1597 | 1614 | /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 1598 | 1615 | /// / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 1599 | 1616 | /// / ArrayTypeStart |
| 1617 | /// |
| 1600 | 1618 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET |
| 1619 | /// |
| 1601 | 1620 | /// PtrTypeStart |
| 1602 | 1621 | /// <- ASTERISK |
| 1603 | 1622 | /// / ASTERISK2 |
| 1604 | 1623 | /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET |
| 1624 | /// |
| 1605 | 1625 | /// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET |
| 1606 | 1626 | fn parseTypeExpr(p: *Parser) Error!Node.Index { |
| 1607 | 1627 | switch (p.token_tags[p.tok_i]) { |
| ... | ... | @@ -2068,6 +2088,7 @@ const Parser = struct { |
| 2068 | 2088 | } |
| 2069 | 2089 | |
| 2070 | 2090 | /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload |
| 2091 | /// |
| 2071 | 2092 | /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? |
| 2072 | 2093 | fn parseForExpr(p: *Parser) !Node.Index { |
| 2073 | 2094 | const for_token = p.eatToken(.keyword_for) orelse return null_node; |
| ... | ... | @@ -2103,6 +2124,7 @@ const Parser = struct { |
| 2103 | 2124 | } |
| 2104 | 2125 | |
| 2105 | 2126 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2127 | /// |
| 2106 | 2128 | /// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? |
| 2107 | 2129 | fn parseWhileExpr(p: *Parser) !Node.Index { |
| 2108 | 2130 | const while_token = p.eatToken(.keyword_while) orelse return null_node; |
| ... | ... | @@ -2154,6 +2176,7 @@ const Parser = struct { |
| 2154 | 2176 | } |
| 2155 | 2177 | |
| 2156 | 2178 | /// CurlySuffixExpr <- TypeExpr InitList? |
| 2179 | /// |
| 2157 | 2180 | /// InitList |
| 2158 | 2181 | /// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE |
| 2159 | 2182 | /// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| ... | ... | @@ -2272,7 +2295,9 @@ const Parser = struct { |
| 2272 | 2295 | /// SuffixExpr |
| 2273 | 2296 | /// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments |
| 2274 | 2297 | /// / PrimaryTypeExpr (SuffixOp / FnCallArguments)* |
| 2298 | /// |
| 2275 | 2299 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 2300 | /// |
| 2276 | 2301 | /// ExprList <- (Expr COMMA)* Expr? |
| 2277 | 2302 | fn parseSuffixExpr(p: *Parser) !Node.Index { |
| 2278 | 2303 | if (p.eatToken(.keyword_async)) |_| { |
| ... | ... | @@ -2410,18 +2435,26 @@ const Parser = struct { |
| 2410 | 2435 | /// / KEYWORD_unreachable |
| 2411 | 2436 | /// / STRINGLITERAL |
| 2412 | 2437 | /// / SwitchExpr |
| 2438 | /// |
| 2413 | 2439 | /// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto |
| 2414 | | /// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE |
| 2440 | /// |
| 2441 | /// ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE |
| 2442 | /// |
| 2415 | 2443 | /// InitList |
| 2416 | 2444 | /// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE |
| 2417 | 2445 | /// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| 2418 | 2446 | /// / LBRACE RBRACE |
| 2447 | /// |
| 2419 | 2448 | /// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE |
| 2449 | /// |
| 2420 | 2450 | /// GroupedExpr <- LPAREN Expr RPAREN |
| 2451 | /// |
| 2421 | 2452 | /// IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? |
| 2453 | /// |
| 2422 | 2454 | /// LabeledTypeExpr |
| 2423 | 2455 | /// <- BlockLabel Block |
| 2424 | 2456 | /// / BlockLabel? LoopTypeExpr |
| 2457 | /// |
| 2425 | 2458 | /// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) |
| 2426 | 2459 | fn parsePrimaryTypeExpr(p: *Parser) !Node.Index { |
| 2427 | 2460 | switch (p.token_tags[p.tok_i]) { |
| ... | ... | @@ -2751,6 +2784,7 @@ const Parser = struct { |
| 2751 | 2784 | } |
| 2752 | 2785 | |
| 2753 | 2786 | /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload |
| 2787 | /// |
| 2754 | 2788 | /// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? |
| 2755 | 2789 | fn parseForTypeExpr(p: *Parser) !Node.Index { |
| 2756 | 2790 | const for_token = p.eatToken(.keyword_for) orelse return null_node; |
| ... | ... | @@ -2786,6 +2820,7 @@ const Parser = struct { |
| 2786 | 2820 | } |
| 2787 | 2821 | |
| 2788 | 2822 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2823 | /// |
| 2789 | 2824 | /// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? |
| 2790 | 2825 | fn parseWhileTypeExpr(p: *Parser) !Node.Index { |
| 2791 | 2826 | const while_token = p.eatToken(.keyword_while) orelse return null_node; |
| ... | ... | @@ -2861,11 +2896,17 @@ const Parser = struct { |
| 2861 | 2896 | } |
| 2862 | 2897 | |
| 2863 | 2898 | /// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN |
| 2899 | /// |
| 2864 | 2900 | /// AsmOutput <- COLON AsmOutputList AsmInput? |
| 2901 | /// |
| 2865 | 2902 | /// AsmInput <- COLON AsmInputList AsmClobbers? |
| 2903 | /// |
| 2866 | 2904 | /// AsmClobbers <- COLON StringList |
| 2905 | /// |
| 2867 | 2906 | /// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? |
| 2907 | /// |
| 2868 | 2908 | /// AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem? |
| 2909 | /// |
| 2869 | 2910 | /// AsmInputList <- (AsmInputItem COMMA)* AsmInputItem? |
| 2870 | 2911 | fn expectAsmExpr(p: *Parser) !Node.Index { |
| 2871 | 2912 | const asm_token = p.assertToken(.keyword_asm); |
| ... | ... | @@ -3069,15 +3110,17 @@ const Parser = struct { |
| 3069 | 3110 | return expr_node; |
| 3070 | 3111 | } |
| 3071 | 3112 | |
| 3072 | | /// ParamDecl |
| 3073 | | /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 3074 | | /// / DOT3 |
| 3075 | | /// ParamType |
| 3076 | | /// <- Keyword_anytype |
| 3077 | | /// / TypeExpr |
| 3078 | 3113 | /// This function can return null nodes and then still return nodes afterwards, |
| 3079 | 3114 | /// such as in the case of anytype and `...`. Caller must look for rparen to find |
| 3080 | 3115 | /// out when there are no more param decls left. |
| 3116 | /// |
| 3117 | /// ParamDecl |
| 3118 | /// <- doc_comment? (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 3119 | /// / DOT3 |
| 3120 | /// |
| 3121 | /// ParamType |
| 3122 | /// <- KEYWORD_anytype |
| 3123 | /// / TypeExpr |
| 3081 | 3124 | fn expectParamDecl(p: *Parser) !Node.Index { |
| 3082 | 3125 | _ = try p.eatDocComments(); |
| 3083 | 3126 | switch (p.token_tags[p.tok_i]) { |
| ... | ... | @@ -3119,8 +3162,9 @@ const Parser = struct { |
| 3119 | 3162 | return identifier; |
| 3120 | 3163 | } |
| 3121 | 3164 | |
| 3122 | | /// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 3123 | 3165 | /// Returns the first identifier token, if any. |
| 3166 | /// |
| 3167 | /// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 3124 | 3168 | fn parsePtrIndexPayload(p: *Parser) !TokenIndex { |
| 3125 | 3169 | _ = p.eatToken(.pipe) orelse return @as(TokenIndex, 0); |
| 3126 | 3170 | _ = p.eatToken(.asterisk); |
| ... | ... | @@ -3133,6 +3177,7 @@ const Parser = struct { |
| 3133 | 3177 | } |
| 3134 | 3178 | |
| 3135 | 3179 | /// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr |
| 3180 | /// |
| 3136 | 3181 | /// SwitchCase |
| 3137 | 3182 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 3138 | 3183 | /// / KEYWORD_else |
| ... | ... | @@ -3385,6 +3430,7 @@ const Parser = struct { |
| 3385 | 3430 | } |
| 3386 | 3431 | |
| 3387 | 3432 | /// Caller must have already verified the first token. |
| 3433 | /// |
| 3388 | 3434 | /// ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE |
| 3389 | 3435 | /// |
| 3390 | 3436 | /// ContainerDeclType |
| ... | ... | @@ -3556,6 +3602,7 @@ const Parser = struct { |
| 3556 | 3602 | } |
| 3557 | 3603 | |
| 3558 | 3604 | /// Holds temporary data until we are ready to construct the full ContainerDecl AST node. |
| 3605 | /// |
| 3559 | 3606 | /// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN |
| 3560 | 3607 | fn parseByteAlign(p: *Parser) !Node.Index { |
| 3561 | 3608 | _ = p.eatToken(.keyword_align) orelse return null_node; |
| ... | ... | @@ -3625,6 +3672,7 @@ const Parser = struct { |
| 3625 | 3672 | } |
| 3626 | 3673 | |
| 3627 | 3674 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 3675 | /// |
| 3628 | 3676 | /// ExprList <- (Expr COMMA)* Expr? |
| 3629 | 3677 | fn parseBuiltinCall(p: *Parser) !Node.Index { |
| 3630 | 3678 | const builtin_token = p.assertToken(.builtin); |
| ... | ... | @@ -3698,7 +3746,7 @@ const Parser = struct { |
| 3698 | 3746 | } |
| 3699 | 3747 | } |
| 3700 | 3748 | |
| 3701 | | /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)? |
| 3749 | /// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? |
| 3702 | 3750 | fn parseIf(p: *Parser, comptime bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index { |
| 3703 | 3751 | const if_token = p.eatToken(.keyword_if) orelse return null_node; |
| 3704 | 3752 | _ = try p.expectToken(.l_paren); |