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 }