authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-07 15:01:01+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 15:49:10+02:00
log64d5ee389912ea3e89eae18c0993a5728bc902dc
treef48cbd19e7851a18f01199a881446fbe65a6c63e
parentfe44dffa12470397146d079445ea4409961e734b
signaturelock-open Commit is signed but in an unrecognized format.

grammar: eliminate backtracking in "lists"

Currently these definitions do not result in an LL(k) generated parser. For in depth reasoning, see commit 296b39c32324 (grammar: fix ParamDeclList worst-case exponential time)

2 files changed, 56 insertions(+), 81 deletions(-)

doc/langref/grammar.peg+5-5
......@@ -441,13 +441,13 @@ ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
441441BitAlign <- KEYWORD_align LPAREN Expr (COLON Expr COLON Expr)? RPAREN
442442
443443# Lists
444IdentifierList <- (doc_comment? IDENTIFIER COMMA)* (doc_comment? IDENTIFIER)?
444IdentifierList <- (doc_comment? IDENTIFIER (COMMA IdentifierList)?)?
445445
446SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
446SwitchProngList <- (SwitchProng (COMMA SwitchProngList)?)?
447447
448AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem?
448AsmOutputList <- (AsmOutputItem (COMMA AsmOutputList)?)?
449449
450AsmInputList <- (AsmInputItem COMMA)* AsmInputItem?
450AsmInputList <- (AsmInputItem (COMMA AsmInputList)?)?
451451
452452ParamDeclList <- LPAREN ParamDeclListRest
453453ParamDeclListRest
......@@ -455,7 +455,7 @@ ParamDeclListRest
455455 / DOT3 COMMA? RPAREN
456456 / ParamDecl (COMMA ParamDeclListRest / RPAREN)
457457
458ExprList <- (Expr COMMA)* (Expr / !ExprPrefix)
458ExprList <- Expr (COMMA ExprList)? / !ExprPrefix
459459
460460ExprPrefix <- ASTERISK
461461
lib/std/zig/parser_generated_oracle.zig+51-76
......@@ -2913,21 +2913,14 @@ const Parser = struct {
29132913 defer p.depths[def_index] -= 1;
29142914 return blk_0: {
29152915 const pos_0 = p.i;
2916 if (blk_1: {
2917 var i_1: usize = 0;
2918 while (blk_3: {
2919 const pos_3 = p.i;
2920 if ((try p.parsedoc_comment() or true) and try p.parseIDENTIFIER() and try p.parseCOMMA()) break :blk_3 true;
2921 p.i = pos_3;
2922 break :blk_3 false;
2923 }) {
2924 if (i_1 > max_depth) return error.MaxDepth;
2925 i_1 += 1;
2926 }
2927 break :blk_1 true;
2928 } and (blk_3: {
2916 if ((blk_3: {
29292917 const pos_3 = p.i;
2930 if ((try p.parsedoc_comment() or true) and try p.parseIDENTIFIER()) break :blk_3 true;
2918 if ((try p.parsedoc_comment() or true) and try p.parseIDENTIFIER() and (blk_6: {
2919 const pos_6 = p.i;
2920 if (try p.parseCOMMA() and try p.parseIdentifierList()) break :blk_6 true;
2921 p.i = pos_6;
2922 break :blk_6 false;
2923 } or true)) break :blk_3 true;
29312924 p.i = pos_3;
29322925 break :blk_3 false;
29332926 } or true)) break :blk_0 true;
......@@ -2942,19 +2935,17 @@ const Parser = struct {
29422935 defer p.depths[def_index] -= 1;
29432936 return blk_0: {
29442937 const pos_0 = p.i;
2945 if (blk_1: {
2946 var i_1: usize = 0;
2947 while (blk_3: {
2948 const pos_3 = p.i;
2949 if (try p.parseSwitchProng() and try p.parseCOMMA()) break :blk_3 true;
2950 p.i = pos_3;
2951 break :blk_3 false;
2952 }) {
2953 if (i_1 > max_depth) return error.MaxDepth;
2954 i_1 += 1;
2955 }
2956 break :blk_1 true;
2957 } and (try p.parseSwitchProng() or true)) break :blk_0 true;
2938 if ((blk_3: {
2939 const pos_3 = p.i;
2940 if (try p.parseSwitchProng() and (blk_6: {
2941 const pos_6 = p.i;
2942 if (try p.parseCOMMA() and try p.parseSwitchProngList()) break :blk_6 true;
2943 p.i = pos_6;
2944 break :blk_6 false;
2945 } or true)) break :blk_3 true;
2946 p.i = pos_3;
2947 break :blk_3 false;
2948 } or true)) break :blk_0 true;
29582949 p.i = pos_0;
29592950 break :blk_0 false;
29602951 };
......@@ -2966,19 +2957,17 @@ const Parser = struct {
29662957 defer p.depths[def_index] -= 1;
29672958 return blk_0: {
29682959 const pos_0 = p.i;
2969 if (blk_1: {
2970 var i_1: usize = 0;
2971 while (blk_3: {
2972 const pos_3 = p.i;
2973 if (try p.parseAsmOutputItem() and try p.parseCOMMA()) break :blk_3 true;
2974 p.i = pos_3;
2975 break :blk_3 false;
2976 }) {
2977 if (i_1 > max_depth) return error.MaxDepth;
2978 i_1 += 1;
2979 }
2980 break :blk_1 true;
2981 } and (try p.parseAsmOutputItem() or true)) break :blk_0 true;
2960 if ((blk_3: {
2961 const pos_3 = p.i;
2962 if (try p.parseAsmOutputItem() and (blk_6: {
2963 const pos_6 = p.i;
2964 if (try p.parseCOMMA() and try p.parseAsmOutputList()) break :blk_6 true;
2965 p.i = pos_6;
2966 break :blk_6 false;
2967 } or true)) break :blk_3 true;
2968 p.i = pos_3;
2969 break :blk_3 false;
2970 } or true)) break :blk_0 true;
29822971 p.i = pos_0;
29832972 break :blk_0 false;
29842973 };
......@@ -2990,19 +2979,17 @@ const Parser = struct {
29902979 defer p.depths[def_index] -= 1;
29912980 return blk_0: {
29922981 const pos_0 = p.i;
2993 if (blk_1: {
2994 var i_1: usize = 0;
2995 while (blk_3: {
2996 const pos_3 = p.i;
2997 if (try p.parseAsmInputItem() and try p.parseCOMMA()) break :blk_3 true;
2998 p.i = pos_3;
2999 break :blk_3 false;
3000 }) {
3001 if (i_1 > max_depth) return error.MaxDepth;
3002 i_1 += 1;
3003 }
3004 break :blk_1 true;
3005 } and (try p.parseAsmInputItem() or true)) break :blk_0 true;
2982 if ((blk_3: {
2983 const pos_3 = p.i;
2984 if (try p.parseAsmInputItem() and (blk_6: {
2985 const pos_6 = p.i;
2986 if (try p.parseCOMMA() and try p.parseAsmInputList()) break :blk_6 true;
2987 p.i = pos_6;
2988 break :blk_6 false;
2989 } or true)) break :blk_3 true;
2990 p.i = pos_3;
2991 break :blk_3 false;
2992 } or true)) break :blk_0 true;
30062993 p.i = pos_0;
30072994 break :blk_0 false;
30082995 };
......@@ -3049,30 +3036,18 @@ const Parser = struct {
30493036 defer p.depths[def_index] -= 1;
30503037 return blk_0: {
30513038 const pos_0 = p.i;
3039 if (try p.parseExpr() and (blk_3: {
3040 const pos_3 = p.i;
3041 if (try p.parseCOMMA() and try p.parseExprList()) break :blk_3 true;
3042 p.i = pos_3;
3043 break :blk_3 false;
3044 } or true)) break :blk_0 true;
3045 p.i = pos_0;
30523046 if (blk_1: {
3053 var i_1: usize = 0;
3054 while (blk_3: {
3055 const pos_3 = p.i;
3056 if (try p.parseExpr() and try p.parseCOMMA()) break :blk_3 true;
3057 p.i = pos_3;
3058 break :blk_3 false;
3059 }) {
3060 if (i_1 > max_depth) return error.MaxDepth;
3061 i_1 += 1;
3062 }
3063 break :blk_1 true;
3064 } and blk_2: {
3065 const pos_2 = p.i;
3066 if (try p.parseExpr()) break :blk_2 true;
3067 p.i = pos_2;
3068 if (blk_3: {
3069 const pos_3 = p.i;
3070 const match_3 = try p.parseExprPrefix();
3071 p.i = pos_3;
3072 break :blk_3 !match_3;
3073 }) break :blk_2 true;
3074 p.i = pos_2;
3075 break :blk_2 false;
3047 const pos_1 = p.i;
3048 const match_1 = try p.parseExprPrefix();
3049 p.i = pos_1;
3050 break :blk_1 !match_1;
30763051 }) break :blk_0 true;
30773052 p.i = pos_0;
30783053 break :blk_0 false;