lib/chant/src/lexer/trivia.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 
 3 const Error = @import("error.zig").Error;
 4 
 5 pub fn skip(self: anytype) Error!void {
 6     while (self.index < self.source.len) {
 7         const c = self.source[self.index];
 8         if (c == '\n') {
 9             self.index += 1;
10             self.line += 1;
11             self.line_start = self.index;
12             continue;
13         }
14         if (c == ' ' or c == '\t' or c == '\r' or c == 0x0b or c == 0x0c) {
15             self.index += 1;
16             continue;
17         }
18         if (c == '#' and self.index == self.line_start) {
19             consumeLineMarker(self);
20             continue;
21         }
22         if (c == '/' and self.index + 1 < self.source.len) {
23             const after = self.source[self.index + 1];
24             if (after == '/') {
25                 while (self.index < self.source.len and self.source[self.index] != '\n') {
26                     self.index += 1;
27                 }
28                 continue;
29             }
30             if (after == '*') {
31                 try skipBlockComment(self);
32                 continue;
33             }
34         }
35         return;
36     }
37 }
38 
39 fn skipBlockComment(self: anytype) Error!void {
40     self.index += 2;
41     while (true) {
42         if (self.index + 1 >= self.source.len) return error.UnterminatedComment;
43         if (self.source[self.index] == '\n') {
44             self.line += 1;
45             self.line_start = self.index + 1;
46         }
47         if (self.source[self.index] == '*' and self.source[self.index + 1] == '/') {
48             self.index += 2;
49             break;
50         }
51         self.index += 1;
52     }
53 }
54 
55 fn consumeLineMarker(self: anytype) void {
56     const line_end = std.mem.indexOfScalarPos(u8, self.source, self.index, '\n') orelse self.source.len;
57     const marker = self.source[self.index..line_end];
58     applyLineMarker(self, marker);
59     self.index = line_end;
60 }
61 
62 fn applyLineMarker(self: anytype, marker: []const u8) void {
63     var rest = std.mem.trimStart(u8, marker[1..], " \t");
64     if (rest.len == 0 or !std.ascii.isDigit(rest[0])) return;
65     var digits_end: usize = 0;
66     while (digits_end < rest.len and std.ascii.isDigit(rest[digits_end])) {
67         digits_end += 1;
68     }
69     const marked_line = std.fmt.parseUnsigned(u32, rest[0..digits_end], 10) catch return;
70     rest = std.mem.trimStart(u8, rest[digits_end..], " \t");
71     if (rest.len >= 2 and rest[0] == '"') {
72         if (std.mem.indexOfScalarPos(u8, rest, 1, '"')) |close| {
73             self.file = rest[1..close];
74         }
75     }
76     self.line = marked_line -| 1;
77 }