diff --git a/doc/langref/grammar.peg b/doc/langref/grammar.peg index a778dc7e60bb75695df06efe73f9608c222baf35..b061d3eb5084d630ddd34c18cc49fa033f1ff995 100644 --- a/doc/langref/grammar.peg +++ b/doc/langref/grammar.peg @@ -14,7 +14,7 @@ Decl / KEYWORD_extern STRINGLITERALSINGLE? FnProto SEMICOLON / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? GlobalVarDecl -FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr !ExprSuffix +FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? @@ -93,25 +93,25 @@ PrefixExpr <- PrefixOp* PrimaryExpr PrimaryExpr <- AsmExpr / IfExpr - / KEYWORD_break BreakLabel? (Expr !ExprSuffix / !SinglePtrTypeStart) - / KEYWORD_comptime Expr !ExprSuffix - / KEYWORD_nosuspend Expr !ExprSuffix - / KEYWORD_continue BreakLabel? (Expr !ExprSuffix / !SinglePtrTypeStart) - / KEYWORD_resume Expr !ExprSuffix - / KEYWORD_return (Expr !ExprSuffix / !SinglePtrTypeStart) + / KEYWORD_break BreakLabel? Expr? + / KEYWORD_comptime Expr + / KEYWORD_nosuspend Expr + / KEYWORD_continue BreakLabel? Expr? + / KEYWORD_resume Expr + / KEYWORD_return Expr? / BlockLabel? LoopExpr / Block / CurlySuffixExpr -IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? !ExprSuffix +IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? Block <- LBRACE BlockStatement* RBRACE LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr) -ForExpr <- ForPrefix Expr (KEYWORD_else Expr / !KEYWORD_else) !ExprSuffix +ForExpr <- ForPrefix Expr (KEYWORD_else Expr / !KEYWORD_else) -WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? !ExprSuffix +WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? CurlySuffixExpr <- TypeExpr InitList? @@ -139,7 +139,7 @@ PrimaryTypeExpr / LabeledTypeExpr / IDENTIFIER / IfTypeExpr - / KEYWORD_comptime TypeExpr !ExprSuffix + / KEYWORD_comptime TypeExpr / KEYWORD_error DOT IDENTIFIER / KEYWORD_anyframe / KEYWORD_unreachable @@ -152,7 +152,7 @@ ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE GroupedExpr <- LPAREN Expr RPAREN -IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? !ExprSuffix +IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? LabeledTypeExpr <- BlockLabel Block @@ -161,9 +161,9 @@ LabeledTypeExpr LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) -ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr / !KEYWORD_else) !ExprSuffix +ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr / !KEYWORD_else) -WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? !ExprSuffix +WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE @@ -329,23 +329,6 @@ SuffixOp FnCallArguments <- LPAREN ExprList RPAREN -ExprSuffix - <- KEYWORD_or - / KEYWORD_and - / CompareOp - / BitwiseOp - / BitShiftOp - / AdditionOp - / MultiplyOp - / EXCLAMATIONMARK - / SuffixOp - / FnCallArguments - -LabelableExpr - <- Block - / SwitchExpr - / LoopExpr - # Ptr specific SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET diff --git a/lib/std/zig/parser_fuzz.zig b/lib/std/zig/parser_fuzz.zig index 62e6d18e264842c474870bd6a8d60bf5992193cf..8adb5f225c004414a464f1cd75eba163bbf527b8 100644 --- a/lib/std/zig/parser_fuzz.zig +++ b/lib/std/zig/parser_fuzz.zig @@ -57,6 +57,11 @@ test "extra capture in for loop" { try checkAgainstOracle("for(0)|t,r|0"); } +// Found using AFL++ +test "expression nesting" { + try checkAgainstOracle("test{*comptime 0 == 0;}"); +} + fn checkAgainstOracle(source: [:0]const u8) !void { var fba_buf: [1 << 18]u8 = undefined; var fba: std.heap.FixedBufferAllocator = .init(&fba_buf); diff --git a/lib/std/zig/parser_generated_oracle.zig b/lib/std/zig/parser_generated_oracle.zig index 675d5231269c557ace96022f11abf26cda1884a0..0e3d078372a87e7569f3335dd45fb8ae5a4dd22b 100644 --- a/lib/std/zig/parser_generated_oracle.zig +++ b/lib/std/zig/parser_generated_oracle.zig @@ -123,12 +123,7 @@ const Parser = struct { pub fn parseFnProto(p: *Parser) bool { return blk_0: { const pos_0 = p.i; - if (p.parseKEYWORD_fn() and (p.parseIDENTIFIER() or true) and p.parseLPAREN() and p.parseParamDeclList() and p.parseRPAREN() and (p.parseByteAlign() or true) and (p.parseAddrSpace() or true) and (p.parseLinkSection() or true) and (p.parseCallConv() or true) and (p.parseEXCLAMATIONMARK() or true) and p.parseTypeExpr() and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + if (p.parseKEYWORD_fn() and (p.parseIDENTIFIER() or true) and p.parseLPAREN() and p.parseParamDeclList() and p.parseRPAREN() and (p.parseByteAlign() or true) and (p.parseAddrSpace() or true) and (p.parseLinkSection() or true) and (p.parseCallConv() or true) and (p.parseEXCLAMATIONMARK() or true) and p.parseTypeExpr()) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -571,83 +566,17 @@ const Parser = struct { p.i = pos_0; if (p.parseIfExpr()) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_break() and (p.parseBreakLabel() or true) and blk_2: { - const pos_2 = p.i; - if (p.parseExpr() and blk_3: { - const pos_3 = p.i; - const match_3 = p.parseExprSuffix(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - if (blk_3: { - const pos_3 = p.i; - const match_3 = p.parseSinglePtrTypeStart(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - break :blk_2 false; - }) break :blk_0 true; + if (p.parseKEYWORD_break() and (p.parseBreakLabel() or true) and (p.parseExpr() or true)) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_comptime() and p.parseExpr() and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + if (p.parseKEYWORD_comptime() and p.parseExpr()) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_nosuspend() and p.parseExpr() and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + if (p.parseKEYWORD_nosuspend() and p.parseExpr()) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_continue() and (p.parseBreakLabel() or true) and blk_2: { - const pos_2 = p.i; - if (p.parseExpr() and blk_3: { - const pos_3 = p.i; - const match_3 = p.parseExprSuffix(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - if (blk_3: { - const pos_3 = p.i; - const match_3 = p.parseSinglePtrTypeStart(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - break :blk_2 false; - }) break :blk_0 true; + if (p.parseKEYWORD_continue() and (p.parseBreakLabel() or true) and (p.parseExpr() or true)) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_resume() and p.parseExpr() and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + if (p.parseKEYWORD_resume() and p.parseExpr()) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_return() and blk_2: { - const pos_2 = p.i; - if (p.parseExpr() and blk_3: { - const pos_3 = p.i; - const match_3 = p.parseExprSuffix(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - if (blk_3: { - const pos_3 = p.i; - const match_3 = p.parseSinglePtrTypeStart(); - p.i = pos_3; - break :blk_3 !match_3; - }) break :blk_2 true; - p.i = pos_2; - break :blk_2 false; - }) break :blk_0 true; + if (p.parseKEYWORD_return() and (p.parseExpr() or true)) break :blk_0 true; p.i = pos_0; if ((p.parseBlockLabel() or true) and p.parseLoopExpr()) break :blk_0 true; p.i = pos_0; @@ -666,12 +595,7 @@ const Parser = struct { if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; - } or true) and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + } or true)) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -717,11 +641,6 @@ const Parser = struct { }) break :blk_2 true; p.i = pos_2; break :blk_2 false; - } and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; break :blk_0 false; @@ -735,12 +654,7 @@ const Parser = struct { if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; - } or true) and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + } or true)) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -848,12 +762,7 @@ const Parser = struct { p.i = pos_0; if (p.parseIfTypeExpr()) break :blk_0 true; p.i = pos_0; - if (p.parseKEYWORD_comptime() and p.parseTypeExpr() and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + if (p.parseKEYWORD_comptime() and p.parseTypeExpr()) break :blk_0 true; p.i = pos_0; if (p.parseKEYWORD_error() and p.parseDOT() and p.parseIDENTIFIER()) break :blk_0 true; p.i = pos_0; @@ -907,12 +816,7 @@ const Parser = struct { if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseTypeExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; - } or true) and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + } or true)) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -959,11 +863,6 @@ const Parser = struct { }) break :blk_2 true; p.i = pos_2; break :blk_2 false; - } and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; break :blk_0 false; @@ -977,12 +876,7 @@ const Parser = struct { if (p.parseKEYWORD_else() and (p.parsePayload() or true) and p.parseTypeExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; - } or true) and blk_1: { - const pos_1 = p.i; - const match_1 = p.parseExprSuffix(); - p.i = pos_1; - break :blk_1 !match_1; - }) break :blk_0 true; + } or true)) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -1643,44 +1537,6 @@ const Parser = struct { break :blk_0 false; }; } - pub fn parseExprSuffix(p: *Parser) bool { - return blk_0: { - const pos_0 = p.i; - if (p.parseKEYWORD_or()) break :blk_0 true; - p.i = pos_0; - if (p.parseKEYWORD_and()) break :blk_0 true; - p.i = pos_0; - if (p.parseCompareOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseBitwiseOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseBitShiftOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseAdditionOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseMultiplyOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseEXCLAMATIONMARK()) break :blk_0 true; - p.i = pos_0; - if (p.parseSuffixOp()) break :blk_0 true; - p.i = pos_0; - if (p.parseFnCallArguments()) break :blk_0 true; - p.i = pos_0; - break :blk_0 false; - }; - } - pub fn parseLabelableExpr(p: *Parser) bool { - return blk_0: { - const pos_0 = p.i; - if (p.parseBlock()) break :blk_0 true; - p.i = pos_0; - if (p.parseSwitchExpr()) break :blk_0 true; - p.i = pos_0; - if (p.parseLoopExpr()) break :blk_0 true; - p.i = pos_0; - break :blk_0 false; - }; - } pub fn parseSliceTypeStart(p: *Parser) bool { return blk_0: { const pos_0 = p.i;