| author | |
| committer | |
| log | b4185600466bd14e39e68cd9f07017a8dc1fcf8e |
| tree | 211f0cc7fe177f6591bf4c9ad52a5dfb6138c642 |
| parent | e488959c1f0504dc3b2aae19d79211e725916c76 |
| signature |
This is a first pass at consistency with Parse.zig on the statement
level, adding constant lookaheads to the grammar in several places
to match the behavior of Parse.zig.3 files changed, 100 insertions(+), 86 deletions(-)
doc/langref/grammar.peg+11-13| ... | ... | @@ -27,39 +27,37 @@ BlockStatement |
| 27 | 27 | <- Statement |
| 28 | 28 | / KEYWORD_defer BlockExprStatement |
| 29 | 29 | / KEYWORD_errdefer BlockExprStatement |
| 30 | / (KEYWORD_comptime)? VarAssignStatement | |
| 30 | / (KEYWORD_comptime !BlockExprPrefix)? VarAssignStatement | |
| 31 | 31 | |
| 32 | 32 | Statement |
| 33 | <- ExprStatement | |
| 34 | / KEYWORD_suspend BlockExprStatement | |
| 35 | / (KEYWORD_comptime)? AssignExpr SEMICOLON | |
| 36 | ||
| 37 | ExprStatement | |
| 38 | 33 | <- IfStatement |
| 39 | 34 | / LabeledStatement |
| 40 | 35 | / KEYWORD_nosuspend BlockExprStatement |
| 41 | 36 | / KEYWORD_comptime BlockExpr |
| 37 | / KEYWORD_suspend BlockExprStatement | |
| 38 | / (KEYWORD_comptime !BlockExprPrefix)? AssignExpr SEMICOLON | |
| 42 | 39 | |
| 43 | 40 | IfStatement |
| 44 | <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )? | |
| 45 | / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) | |
| 41 | <- IfPrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else) | |
| 42 | / IfPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement) | |
| 46 | 43 | |
| 47 | 44 | LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr) |
| 48 | 45 | |
| 49 | 46 | LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) |
| 50 | 47 | |
| 51 | 48 | ForStatement |
| 52 | <- ForPrefix BlockExpr ( KEYWORD_else Statement / !KEYWORD_else ) | |
| 53 | / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement ) | |
| 49 | <- ForPrefix BlockExpr (KEYWORD_else Statement / !KEYWORD_else) | |
| 50 | / ForPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Statement) | |
| 54 | 51 | |
| 55 | 52 | WhileStatement |
| 56 | <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? | |
| 57 | / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) | |
| 53 | <- WhilePrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else) | |
| 54 | / WhilePrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement) | |
| 58 | 55 | |
| 59 | 56 | BlockExprStatement |
| 60 | 57 | <- BlockExpr |
| 61 | / !BlockExpr AssignExpr SEMICOLON | |
| 58 | / !BlockExprPrefix AssignExpr SEMICOLON | |
| 62 | 59 | |
| 60 | BlockExprPrefix <- BlockLabel? LBRACE | |
| 63 | 61 | BlockExpr <- BlockLabel? Block |
| 64 | 62 | |
| 65 | 63 | # An assignment or a destructure whose LHS are all lvalue expressions or variable declarations. |
lib/std/zig/Parse.zig+17-40| ... | ... | @@ -864,7 +864,7 @@ fn parseGlobalVarDecl(p: *Parse) !?Node.Index { |
| 864 | 864 | return var_decl; |
| 865 | 865 | } |
| 866 | 866 | |
| 867 | /// ContainerField <- doc_comment? (KEYWORD_comptime / !KEYWORD_comptime) !KEYWORD_fn (IDENTIFIER COLON / !(IDENTIFIER COLON))? TypeExpr ByteAlign? (EQUAL Expr)? | |
| 867 | // ContainerField <- doc_comment? KEYWORD_comptime? (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)? | |
| 868 | 868 | fn expectContainerField(p: *Parse) !Node.Index { |
| 869 | 869 | _ = p.eatToken(.keyword_comptime); |
| 870 | 870 | const main_token = p.tok_i; |
| ... | ... | @@ -910,18 +910,15 @@ fn expectContainerField(p: *Parse) !Node.Index { |
| 910 | 910 | /// <- Statement |
| 911 | 911 | /// / KEYWORD_defer BlockExprStatement |
| 912 | 912 | /// / KEYWORD_errdefer BlockExprStatement |
| 913 | /// / !ExprStatement (KEYWORD_comptime !BlockExpr)? VarAssignStatement | |
| 913 | /// / (KEYWORD_comptime !BlockExprPrefix)? VarAssignStatement | |
| 914 | 914 | /// |
| 915 | 915 | /// Statement |
| 916 | /// <- ExprStatement | |
| 917 | /// / KEYWORD_suspend BlockExprStatement | |
| 918 | /// / !ExprStatement (KEYWORD_comptime !BlockExpr)? AssignExpr SEMICOLON | |
| 919 | /// | |
| 920 | /// ExprStatement | |
| 921 | 916 | /// <- IfStatement |
| 922 | 917 | /// / LabeledStatement |
| 923 | 918 | /// / KEYWORD_nosuspend BlockExprStatement |
| 924 | 919 | /// / KEYWORD_comptime BlockExpr |
| 920 | /// / KEYWORD_suspend BlockExprStatement | |
| 921 | /// / (KEYWORD_comptime !BlockExprPrefix)? AssignExpr SEMICOLON | |
| 925 | 922 | fn expectStatement(p: *Parse, is_block_level: bool) Error!Node.Index { |
| 926 | 923 | if (p.eatToken(.keyword_comptime)) |comptime_token| { |
| 927 | 924 | const opt_block_expr = try p.parseBlockExpr(); |
| ... | ... | @@ -934,7 +931,7 @@ fn expectStatement(p: *Parse, is_block_level: bool) Error!Node.Index { |
| 934 | 931 | } |
| 935 | 932 | |
| 936 | 933 | if (is_block_level) { |
| 937 | return p.expectVarDeclExprStatement(comptime_token); | |
| 934 | return p.expectVarAssignStatement(comptime_token); | |
| 938 | 935 | } else { |
| 939 | 936 | const assign = try p.expectAssignExpr(); |
| 940 | 937 | try p.expectSemicolon(.expected_semi_after_stmt, true); |
| ... | ... | @@ -995,7 +992,7 @@ fn expectStatement(p: *Parse, is_block_level: bool) Error!Node.Index { |
| 995 | 992 | if (try p.parseLabeledStatement()) |labeled_statement| return labeled_statement; |
| 996 | 993 | |
| 997 | 994 | if (is_block_level) { |
| 998 | return p.expectVarDeclExprStatement(null); | |
| 995 | return p.expectVarAssignStatement(null); | |
| 999 | 996 | } else { |
| 1000 | 997 | const assign = try p.expectAssignExpr(); |
| 1001 | 998 | try p.expectSemicolon(.expected_semi_after_stmt, true); |
| ... | ... | @@ -1003,30 +1000,8 @@ fn expectStatement(p: *Parse, is_block_level: bool) Error!Node.Index { |
| 1003 | 1000 | } |
| 1004 | 1001 | } |
| 1005 | 1002 | |
| 1006 | /// ComptimeStatement | |
| 1007 | /// <- BlockExpr | |
| 1008 | /// / VarDeclExprStatement | |
| 1009 | fn expectComptimeStatement(p: *Parse, comptime_token: TokenIndex) !Node.Index { | |
| 1010 | const maybe_block_expr = try p.parseBlockExpr(); | |
| 1011 | if (maybe_block_expr) |block_expr| { | |
| 1012 | return p.addNode(.{ | |
| 1013 | .tag = .@"comptime", | |
| 1014 | .main_token = comptime_token, | |
| 1015 | .data = .{ | |
| 1016 | .lhs = .{ .node = block_expr }, | |
| 1017 | .rhs = undefined, | |
| 1018 | }, | |
| 1019 | }); | |
| 1020 | } | |
| 1021 | return p.expectVarDeclExprStatement(comptime_token); | |
| 1022 | } | |
| 1023 | ||
| 1024 | /// VarDeclExprStatement | |
| 1025 | /// <- Expr | |
| 1026 | /// / VarAssignStatement | |
| 1027 | /// | |
| 1028 | 1003 | /// VarAssignStatement <- (VarDeclProto / Expr) (COMMA (VarDeclProto / Expr))* EQUAL Expr SEMICOLON |
| 1029 | fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Index { | |
| 1004 | fn expectVarAssignStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Index { | |
| 1030 | 1005 | const scratch_top = p.scratch.items.len; |
| 1031 | 1006 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 1032 | 1007 | |
| ... | ... | @@ -1138,7 +1113,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1138 | 1113 | |
| 1139 | 1114 | /// If a parse error occurs, reports an error, but then finds the next statement |
| 1140 | 1115 | /// and returns that one instead. If a parse error occurs but there is no following |
| 1141 | /// statement, returns 0. | |
| 1116 | /// statement, returns null. | |
| 1142 | 1117 | fn expectStatementRecoverable(p: *Parse) Error!?Node.Index { |
| 1143 | 1118 | while (true) { |
| 1144 | 1119 | return p.expectStatement(true) catch |err| switch (err) { |
| ... | ... | @@ -1156,8 +1131,10 @@ fn expectStatementRecoverable(p: *Parse) Error!?Node.Index { |
| 1156 | 1131 | } |
| 1157 | 1132 | |
| 1158 | 1133 | /// IfStatement |
| 1159 | /// <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )? | |
| 1160 | /// / IfPrefix !BlockExpr AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) | |
| 1134 | /// <- IfPrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else) | |
| 1135 | /// / IfPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement) | |
| 1136 | /// | |
| 1137 | /// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? | |
| 1161 | 1138 | fn expectIfStatement(p: *Parse) !Node.Index { |
| 1162 | 1139 | const if_token = p.assertToken(.keyword_if); |
| 1163 | 1140 | _ = try p.expectToken(.l_paren); |
| ... | ... | @@ -1252,8 +1229,8 @@ fn parseLoopStatement(p: *Parse) !?Node.Index { |
| 1252 | 1229 | } |
| 1253 | 1230 | |
| 1254 | 1231 | /// ForStatement |
| 1255 | /// <- ForPrefix BlockExpr ( KEYWORD_else Statement / !KEYWORD_else ) | |
| 1256 | /// / ForPrefix !BlockExpr AssignExpr ( SEMICOLON / KEYWORD_else Statement ) | |
| 1232 | /// <- ForPrefix BlockExpr (KEYWORD_else Statement / !KEYWORD_else) | |
| 1233 | /// / ForPrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Statement) | |
| 1257 | 1234 | fn parseForStatement(p: *Parse) !?Node.Index { |
| 1258 | 1235 | const for_token = p.eatToken(.keyword_for) orelse return null; |
| 1259 | 1236 | |
| ... | ... | @@ -1309,8 +1286,8 @@ fn parseForStatement(p: *Parse) !?Node.Index { |
| 1309 | 1286 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 1310 | 1287 | /// |
| 1311 | 1288 | /// WhileStatement |
| 1312 | /// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? | |
| 1313 | /// / WhilePrefix !BlockExpr AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) | |
| 1289 | /// <- WhilePrefix BlockExpr (KEYWORD_else Payload? Statement / !KEYWORD_else) | |
| 1290 | /// / WhilePrefix !BlockExprPrefix AssignExpr (SEMICOLON / KEYWORD_else Payload? Statement) | |
| 1314 | 1291 | fn parseWhileStatement(p: *Parse) !?Node.Index { |
| 1315 | 1292 | const while_token = p.eatToken(.keyword_while) orelse return null; |
| 1316 | 1293 | _ = try p.expectToken(.l_paren); |
| ... | ... | @@ -1400,7 +1377,7 @@ fn parseWhileStatement(p: *Parse) !?Node.Index { |
| 1400 | 1377 | |
| 1401 | 1378 | /// BlockExprStatement |
| 1402 | 1379 | /// <- BlockExpr |
| 1403 | /// / !BlockExpr AssignExpr SEMICOLON | |
| 1380 | /// / !BlockExprPrefix AssignExpr SEMICOLON | |
| 1404 | 1381 | fn parseBlockExprStatement(p: *Parse) !?Node.Index { |
| 1405 | 1382 | const block_expr = try p.parseBlockExpr(); |
| 1406 | 1383 | if (block_expr) |expr| return expr; |
lib/std/zig/parser_generated_oracle.zig+72-33| ... | ... | @@ -190,7 +190,12 @@ const Parser = struct { |
| 190 | 190 | p.i = pos_0; |
| 191 | 191 | if ((blk_3: { |
| 192 | 192 | const pos_3 = p.i; |
| 193 | if (p.parseKEYWORD_comptime()) break :blk_3 true; | |
| 193 | if (p.parseKEYWORD_comptime() and blk_4: { | |
| 194 | const pos_4 = p.i; | |
| 195 | const match_4 = p.parseBlockExprPrefix(); | |
| 196 | p.i = pos_4; | |
| 197 | break :blk_4 !match_4; | |
| 198 | }) break :blk_3 true; | |
| 194 | 199 | p.i = pos_3; |
| 195 | 200 | break :blk_3 false; |
| 196 | 201 | } or true) and p.parseVarAssignStatement()) break :blk_0 true; |
| ... | ... | @@ -201,13 +206,24 @@ const Parser = struct { |
| 201 | 206 | pub fn parseStatement(p: *Parser) bool { |
| 202 | 207 | return blk_0: { |
| 203 | 208 | const pos_0 = p.i; |
| 204 | if (p.parseExprStatement()) break :blk_0 true; | |
| 209 | if (p.parseIfStatement()) break :blk_0 true; | |
| 210 | p.i = pos_0; | |
| 211 | if (p.parseLabeledStatement()) break :blk_0 true; | |
| 212 | p.i = pos_0; | |
| 213 | if (p.parseKEYWORD_nosuspend() and p.parseBlockExprStatement()) break :blk_0 true; | |
| 214 | p.i = pos_0; | |
| 215 | if (p.parseKEYWORD_comptime() and p.parseBlockExpr()) break :blk_0 true; | |
| 205 | 216 | p.i = pos_0; |
| 206 | 217 | if (p.parseKEYWORD_suspend() and p.parseBlockExprStatement()) break :blk_0 true; |
| 207 | 218 | p.i = pos_0; |
| 208 | 219 | if ((blk_3: { |
| 209 | 220 | const pos_3 = p.i; |
| 210 | if (p.parseKEYWORD_comptime()) break :blk_3 true; | |
| 221 | if (p.parseKEYWORD_comptime() and blk_4: { | |
| 222 | const pos_4 = p.i; | |
| 223 | const match_4 = p.parseBlockExprPrefix(); | |
| 224 | p.i = pos_4; | |
| 225 | break :blk_4 !match_4; | |
| 226 | }) break :blk_3 true; | |
| 211 | 227 | p.i = pos_3; |
| 212 | 228 | break :blk_3 false; |
| 213 | 229 | } or true) and p.parseAssignExpr() and p.parseSEMICOLON()) break :blk_0 true; |
| ... | ... | @@ -215,31 +231,29 @@ const Parser = struct { |
| 215 | 231 | break :blk_0 false; |
| 216 | 232 | }; |
| 217 | 233 | } |
| 218 | pub fn parseExprStatement(p: *Parser) bool { | |
| 219 | return blk_0: { | |
| 220 | const pos_0 = p.i; | |
| 221 | if (p.parseIfStatement()) break :blk_0 true; | |
| 222 | p.i = pos_0; | |
| 223 | if (p.parseLabeledStatement()) break :blk_0 true; | |
| 224 | p.i = pos_0; | |
| 225 | if (p.parseKEYWORD_nosuspend() and p.parseBlockExprStatement()) break :blk_0 true; | |
| 226 | p.i = pos_0; | |
| 227 | if (p.parseKEYWORD_comptime() and p.parseBlockExpr()) break :blk_0 true; | |
| 228 | p.i = pos_0; | |
| 229 | break :blk_0 false; | |
| 230 | }; | |
| 231 | } | |
| 232 | 234 | pub fn parseIfStatement(p: *Parser) bool { |
| 233 | 235 | return blk_0: { |
| 234 | 236 | const pos_0 = p.i; |
| 235 | if (p.parseIfPrefix() and p.parseBlockExpr() and (blk_3: { | |
| 236 | const pos_3 = p.i; | |
| 237 | if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseStatement()) break :blk_3 true; | |
| 238 | p.i = pos_3; | |
| 239 | break :blk_3 false; | |
| 240 | } or true)) break :blk_0 true; | |
| 237 | if (p.parseIfPrefix() and p.parseBlockExpr() and blk_2: { | |
| 238 | const pos_2 = p.i; | |
| 239 | if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseStatement()) break :blk_2 true; | |
| 240 | p.i = pos_2; | |
| 241 | if (blk_3: { | |
| 242 | const pos_3 = p.i; | |
| 243 | const match_3 = p.parseKEYWORD_else(); | |
| 244 | p.i = pos_3; | |
| 245 | break :blk_3 !match_3; | |
| 246 | }) break :blk_2 true; | |
| 247 | p.i = pos_2; | |
| 248 | break :blk_2 false; | |
| 249 | }) break :blk_0 true; | |
| 241 | 250 | p.i = pos_0; |
| 242 | if (p.parseIfPrefix() and p.parseAssignExpr() and blk_2: { | |
| 251 | if (p.parseIfPrefix() and blk_1: { | |
| 252 | const pos_1 = p.i; | |
| 253 | const match_1 = p.parseBlockExprPrefix(); | |
| 254 | p.i = pos_1; | |
| 255 | break :blk_1 !match_1; | |
| 256 | } and p.parseAssignExpr() and blk_2: { | |
| 243 | 257 | const pos_2 = p.i; |
| 244 | 258 | if (p.parseSEMICOLON()) break :blk_2 true; |
| 245 | 259 | p.i = pos_2; |
| ... | ... | @@ -300,7 +314,12 @@ const Parser = struct { |
| 300 | 314 | break :blk_2 false; |
| 301 | 315 | }) break :blk_0 true; |
| 302 | 316 | p.i = pos_0; |
| 303 | if (p.parseForPrefix() and p.parseAssignExpr() and blk_2: { | |
| 317 | if (p.parseForPrefix() and blk_1: { | |
| 318 | const pos_1 = p.i; | |
| 319 | const match_1 = p.parseBlockExprPrefix(); | |
| 320 | p.i = pos_1; | |
| 321 | break :blk_1 !match_1; | |
| 322 | } and p.parseAssignExpr() and blk_2: { | |
| 304 | 323 | const pos_2 = p.i; |
| 305 | 324 | if (p.parseSEMICOLON()) break :blk_2 true; |
| 306 | 325 | p.i = pos_2; |
| ... | ... | @@ -315,14 +334,26 @@ const Parser = struct { |
| 315 | 334 | pub fn parseWhileStatement(p: *Parser) bool { |
| 316 | 335 | return blk_0: { |
| 317 | 336 | const pos_0 = p.i; |
| 318 | if (p.parseWhilePrefix() and p.parseBlockExpr() and (blk_3: { | |
| 319 | const pos_3 = p.i; | |
| 320 | if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseStatement()) break :blk_3 true; | |
| 321 | p.i = pos_3; | |
| 322 | break :blk_3 false; | |
| 323 | } or true)) break :blk_0 true; | |
| 337 | if (p.parseWhilePrefix() and p.parseBlockExpr() and blk_2: { | |
| 338 | const pos_2 = p.i; | |
| 339 | if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseStatement()) break :blk_2 true; | |
| 340 | p.i = pos_2; | |
| 341 | if (blk_3: { | |
| 342 | const pos_3 = p.i; | |
| 343 | const match_3 = p.parseKEYWORD_else(); | |
| 344 | p.i = pos_3; | |
| 345 | break :blk_3 !match_3; | |
| 346 | }) break :blk_2 true; | |
| 347 | p.i = pos_2; | |
| 348 | break :blk_2 false; | |
| 349 | }) break :blk_0 true; | |
| 324 | 350 | p.i = pos_0; |
| 325 | if (p.parseWhilePrefix() and p.parseAssignExpr() and blk_2: { | |
| 351 | if (p.parseWhilePrefix() and blk_1: { | |
| 352 | const pos_1 = p.i; | |
| 353 | const match_1 = p.parseBlockExprPrefix(); | |
| 354 | p.i = pos_1; | |
| 355 | break :blk_1 !match_1; | |
| 356 | } and p.parseAssignExpr() and blk_2: { | |
| 326 | 357 | const pos_2 = p.i; |
| 327 | 358 | if (p.parseSEMICOLON()) break :blk_2 true; |
| 328 | 359 | p.i = pos_2; |
| ... | ... | @@ -341,7 +372,7 @@ const Parser = struct { |
| 341 | 372 | p.i = pos_0; |
| 342 | 373 | if (blk_1: { |
| 343 | 374 | const pos_1 = p.i; |
| 344 | const match_1 = p.parseBlockExpr(); | |
| 375 | const match_1 = p.parseBlockExprPrefix(); | |
| 345 | 376 | p.i = pos_1; |
| 346 | 377 | break :blk_1 !match_1; |
| 347 | 378 | } and p.parseAssignExpr() and p.parseSEMICOLON()) break :blk_0 true; |
| ... | ... | @@ -349,6 +380,14 @@ const Parser = struct { |
| 349 | 380 | break :blk_0 false; |
| 350 | 381 | }; |
| 351 | 382 | } |
| 383 | pub fn parseBlockExprPrefix(p: *Parser) bool { | |
| 384 | return blk_0: { | |
| 385 | const pos_0 = p.i; | |
| 386 | if ((p.parseBlockLabel() or true) and p.parseLBRACE()) break :blk_0 true; | |
| 387 | p.i = pos_0; | |
| 388 | break :blk_0 false; | |
| 389 | }; | |
| 390 | } | |
| 352 | 391 | pub fn parseBlockExpr(p: *Parser) bool { |
| 353 | 392 | return blk_0: { |
| 354 | 393 | const pos_0 = p.i; |