authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-06-12 13:17:01+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2026-07-08 11:48:57+02:00
log5c2510ba58d2c5b0b3082244ab9b9320662d1d65
treeb42d85d96a54523eb78cc8299331612b93ec2411
parent0b24b58fb24b462c85ebba53ee838e87887e4d25
signaturelock-open Commit is signed but in an unrecognized format.

grammar: match tokenizer newline handling

The tokenizer currently handles termination of comments/multiline string literal lines differently from the grammar. The tokenizer forbids e.g. tab characters at the end of comments before a newline and requires \r to be directly followed by \n. The tokenizer behavior here is intended, see c2b8afcac9e427102370dc.

2 files changed, 35 insertions(+), 41 deletions(-)

doc/langref/grammar.peg+7-4
...@@ -430,10 +430,13 @@ string_char...@@ -430,10 +430,13 @@ string_char
430 <- '\\"'430 <- '\\"'
431 / !["] non_control_utf8431 / !["] non_control_utf8
432432
433container_doc_comment <- ('//!' non_control_utf8* [ \n]* skip)+433container_doc_comment <- ('//!' non_control_utf8* newline skip)+
434doc_comment <- ('///' non_control_utf8* [ \n]* skip)+434doc_comment <- ('///' non_control_utf8* newline skip)+
435line_comment <- '//' ![!/] non_control_utf8* / '////' non_control_utf8*435line_comment
436line_string <- '\\\\' non_control_utf8* [ \n]*436 <- '//' ![!/] non_control_utf8* newline
437 / '////' non_control_utf8* newline
438line_string <- '\\\\' non_control_utf8* newline
439newline <- "\n" / "\r\n" / eof
437skip <- ([ \n\t\r] / line_comment)*440skip <- ([ \n\t\r] / line_comment)*
438441
439CHAR_LITERAL <- ['] char_char* ['] skip442CHAR_LITERAL <- ['] char_char* ['] skip
lib/std/zig/parser_generated_oracle.zig+28-37
...@@ -2194,18 +2194,7 @@ const Parser = struct {...@@ -2194,18 +2194,7 @@ const Parser = struct {
2194 } and blk_4: {2194 } and blk_4: {
2195 while (p.parsenon_control_utf8()) {}2195 while (p.parsenon_control_utf8()) {}
2196 break :blk_4 true;2196 break :blk_4 true;
2197 } and blk_4: {2197 } and p.parsenewline() and p.parseskip()) break :blk_3 true;
2198 while ((p.i < p.source.len and switch (p.source[p.i]) {
2199 ' '...' ',
2200 '\n'...'\n',
2201 => blk_5: {
2202 p.i += 1;
2203 break :blk_5 true;
2204 },
2205 else => false,
2206 })) {}
2207 break :blk_4 true;
2208 } and p.parseskip()) break :blk_3 true;
2209 p.i = pos_3;2198 p.i = pos_3;
2210 break :blk_3 false;2199 break :blk_3 false;
2211 }) {2200 }) {
...@@ -2233,18 +2222,7 @@ const Parser = struct {...@@ -2233,18 +2222,7 @@ const Parser = struct {
2233 } and blk_4: {2222 } and blk_4: {
2234 while (p.parsenon_control_utf8()) {}2223 while (p.parsenon_control_utf8()) {}
2235 break :blk_4 true;2224 break :blk_4 true;
2236 } and blk_4: {2225 } and p.parsenewline() and p.parseskip()) break :blk_3 true;
2237 while ((p.i < p.source.len and switch (p.source[p.i]) {
2238 ' '...' ',
2239 '\n'...'\n',
2240 => blk_5: {
2241 p.i += 1;
2242 break :blk_5 true;
2243 },
2244 else => false,
2245 })) {}
2246 break :blk_4 true;
2247 } and p.parseskip()) break :blk_3 true;
2248 p.i = pos_3;2226 p.i = pos_3;
2249 break :blk_3 false;2227 break :blk_3 false;
2250 }) {2228 }) {
...@@ -2281,7 +2259,7 @@ const Parser = struct {...@@ -2281,7 +2259,7 @@ const Parser = struct {
2281 } and blk_1: {2259 } and blk_1: {
2282 while (p.parsenon_control_utf8()) {}2260 while (p.parsenon_control_utf8()) {}
2283 break :blk_1 true;2261 break :blk_1 true;
2284 }) break :blk_0 true;2262 } and p.parsenewline()) break :blk_0 true;
2285 p.i = pos_0;2263 p.i = pos_0;
2286 if (blk_1: {2264 if (blk_1: {
2287 if (std.mem.startsWith(u8, p.source[p.i..], "////")) {2265 if (std.mem.startsWith(u8, p.source[p.i..], "////")) {
...@@ -2292,7 +2270,7 @@ const Parser = struct {...@@ -2292,7 +2270,7 @@ const Parser = struct {
2292 } and blk_1: {2270 } and blk_1: {
2293 while (p.parsenon_control_utf8()) {}2271 while (p.parsenon_control_utf8()) {}
2294 break :blk_1 true;2272 break :blk_1 true;
2295 }) break :blk_0 true;2273 } and p.parsenewline()) break :blk_0 true;
2296 p.i = pos_0;2274 p.i = pos_0;
2297 break :blk_0 false;2275 break :blk_0 false;
2298 };2276 };
...@@ -2309,19 +2287,32 @@ const Parser = struct {...@@ -2309,19 +2287,32 @@ const Parser = struct {
2309 } and blk_1: {2287 } and blk_1: {
2310 while (p.parsenon_control_utf8()) {}2288 while (p.parsenon_control_utf8()) {}
2311 break :blk_1 true;2289 break :blk_1 true;
2312 } and blk_1: {2290 } and p.parsenewline()) break :blk_0 true;
2313 while ((p.i < p.source.len and switch (p.source[p.i]) {2291 p.i = pos_0;
2314 ' '...' ',2292 break :blk_0 false;
2315 '\n'...'\n',2293 };
2316 => blk_2: {2294 }
2317 p.i += 1;2295 pub fn parsenewline(p: *Parser) bool {
2318 break :blk_2 true;2296 return blk_0: {
2319 },2297 const pos_0 = p.i;
2320 else => false,2298 if (blk_1: {
2321 })) {}2299 if (std.mem.startsWith(u8, p.source[p.i..], "\n")) {
2322 break :blk_1 true;2300 p.i += 1;
2301 break :blk_1 true;
2302 }
2303 break :blk_1 false;
2323 }) break :blk_0 true;2304 }) break :blk_0 true;
2324 p.i = pos_0;2305 p.i = pos_0;
2306 if (blk_1: {
2307 if (std.mem.startsWith(u8, p.source[p.i..], "\r\n")) {
2308 p.i += 2;
2309 break :blk_1 true;
2310 }
2311 break :blk_1 false;
2312 }) break :blk_0 true;
2313 p.i = pos_0;
2314 if (p.parseeof()) break :blk_0 true;
2315 p.i = pos_0;
2325 break :blk_0 false;2316 break :blk_0 false;
2326 };2317 };
2327 }2318 }