Appearance
| 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 |