Skip to content
← Back

src/lexical/token_queue.ghul

1
namespace Lexical is
2
use Collections;
3
4
use Logging;
5
6
class TOKEN_QUEUE is
7
_buffer: LIST[TOKEN_PAIR];
8
_speculate_index: int;
9
_read_index: int; // points at the last token read
10
_write_index: int; // points at the last token written
11
_size: int;
12
13
count: int => (_write_index - _read_index + _size) & (_size - 1);
14
15
avail: bool => count > 0;
16
17
is_speculating: bool => _speculate_index != -1;
18
19
_peek_offset(index: int) -> int =>
20
(_read_index + index) & (_size - 1);
21
22
_next_index(index: int) -> int =>
23
(index + 1) & (_size - 1);
24
25
_prev_index(index: int) -> int =>
26
(index - 1) & (_size - 1);
27
28
init(size: int) is
29
assert size > 0 else "token queue size must be greater than 0";
30
assert (size & (size - 1)) == 0 else "token queue size must be a power of 2";
31
32
_size = size;
33
_read_index = 0;
34
_write_index = 0;
35
_speculate_index = -1;
36
37
_buffer = LIST[TOKEN_PAIR](_size);
38
39
// .NET can be very annoying sometimes...
40
41
for i in 0.._size do
42
_buffer.add(null);
43
od
44
si
45
46
speculate_enter() is
47
assert _speculate_index == -1 else "already speculating";
48
_speculate_index = _read_index;
49
si
50
51
speculate_exit() is
52
assert _speculate_index != -1 else "not speculating";
53
_speculate_index = -1;
54
si
55
56
get_read_index() -> int => _read_index;
57
58
mark() -> int is
59
assert _speculate_index != -1 else "not speculating";
60
61
return _read_index;
62
si
63
64
release(index: int) is
65
assert _speculate_index != -1 else "not speculating";
66
_read_index = index;
67
si
68
69
last() -> TOKEN_PAIR => _buffer[_read_index];
70
71
enqueue(token: TOKEN_PAIR) is
72
let new_write_index = _next_index(_write_index);
73
74
assert new_write_index != _read_index /\ new_write_index != _speculate_index else "token queue overflow";
75
76
_write_index = new_write_index;
77
78
_buffer[_write_index] = token;
79
si
80
81
dequeue() -> TOKEN_PAIR is
82
assert _read_index != _write_index else "token queue underflow";
83
84
_read_index = _next_index(_read_index);
85
86
let result = _buffer[_read_index];
87
88
return result;
89
si
90
si
91
si