lib/chant/src/lexer/punctuator.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const chant = @import("../root.zig");
 2 const cursor = @import("cursor.zig");
 3 
 4 const Kind = chant.token.Kind;
 5 const Token = chant.token.Token;
 6 const Error = @import("error.zig").Error;
 7 
 8 pub fn lex(self: anytype, start: usize, column: u32) Error!Token {
 9     const kind = kindAt(self) orelse return error.UnexpectedCharacter;
10     return cursor.make(self, kind, start, column);
11 }
12 
13 fn kindAt(self: anytype) ?Kind {
14     const source = self.source;
15     const c = source[self.index];
16     const one = self.index + 1;
17     const two = self.index + 2;
18     const next_c: u8 = if (one < source.len) source[one] else 0;
19     const next_next: u8 = if (two < source.len) source[two] else 0;
20 
21     switch (c) {
22         '(' => return cursor.take(self, .lparen, 1),
23         ')' => return cursor.take(self, .rparen, 1),
24         '{' => return cursor.take(self, .lbrace, 1),
25         '}' => return cursor.take(self, .rbrace, 1),
26         '[' => return cursor.take(self, .lbracket, 1),
27         ']' => return cursor.take(self, .rbracket, 1),
28         ';' => return cursor.take(self, .semicolon, 1),
29         ',' => return cursor.take(self, .comma, 1),
30         '?' => return cursor.take(self, .question, 1),
31         '~' => return cursor.take(self, .tilde, 1),
32         ':' => return cursor.take(self, .colon, 1),
33         '+' => return plus(self, next_c),
34         '-' => return minus(self, next_c),
35         '*' => return assignable(self, next_c, .star, .star_assign),
36         '/' => return assignable(self, next_c, .slash, .slash_assign),
37         '%' => return assignable(self, next_c, .percent, .percent_assign),
38         '&' => return ampersand(self, next_c),
39         '|' => return pipe(self, next_c),
40         '^' => return assignable(self, next_c, .caret, .caret_assign),
41         '!' => return assignable(self, next_c, .bang, .ne),
42         '=' => return assignable(self, next_c, .assign, .eq),
43         '<' => return leftAngle(self, next_c, next_next),
44         '>' => return rightAngle(self, next_c, next_next),
45         '.' => return dot(self, next_c, next_next),
46         else => return null,
47     }
48 }
49 
50 fn plus(self: anytype, next_c: u8) Kind {
51     if (next_c == '+') return cursor.take(self, .plus_plus, 2);
52     if (next_c == '=') return cursor.take(self, .plus_assign, 2);
53     return cursor.take(self, .plus, 1);
54 }
55 
56 fn minus(self: anytype, next_c: u8) Kind {
57     if (next_c == '-') return cursor.take(self, .minus_minus, 2);
58     if (next_c == '=') return cursor.take(self, .minus_assign, 2);
59     if (next_c == '>') return cursor.take(self, .arrow, 2);
60     return cursor.take(self, .minus, 1);
61 }
62 
63 fn ampersand(self: anytype, next_c: u8) Kind {
64     if (next_c == '&') return cursor.take(self, .amp_amp, 2);
65     if (next_c == '=') return cursor.take(self, .amp_assign, 2);
66     return cursor.take(self, .amp, 1);
67 }
68 
69 fn pipe(self: anytype, next_c: u8) Kind {
70     if (next_c == '|') return cursor.take(self, .pipe_pipe, 2);
71     if (next_c == '=') return cursor.take(self, .pipe_assign, 2);
72     return cursor.take(self, .pipe, 1);
73 }
74 
75 fn assignable(self: anytype, next_c: u8, plain: Kind, assigned: Kind) Kind {
76     if (next_c == '=') return cursor.take(self, assigned, 2);
77     return cursor.take(self, plain, 1);
78 }
79 
80 fn leftAngle(self: anytype, next_c: u8, next_next: u8) Kind {
81     if (next_c == '<' and next_next == '=') return cursor.take(self, .shl_assign, 3);
82     if (next_c == '<') return cursor.take(self, .shl, 2);
83     if (next_c == '=') return cursor.take(self, .le, 2);
84     return cursor.take(self, .lt, 1);
85 }
86 
87 fn rightAngle(self: anytype, next_c: u8, next_next: u8) Kind {
88     if (next_c == '>' and next_next == '=') return cursor.take(self, .shr_assign, 3);
89     if (next_c == '>') return cursor.take(self, .shr, 2);
90     if (next_c == '=') return cursor.take(self, .ge, 2);
91     return cursor.take(self, .gt, 1);
92 }
93 
94 fn dot(self: anytype, next_c: u8, next_next: u8) Kind {
95     if (next_c == '.' and next_next == '.') return cursor.take(self, .ellipsis, 3);
96     return cursor.take(self, .dot, 1);
97 }