1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! <ost generic stream of symbols
/// `IntStream::la` must return EOF in the end of stream
pub const EOF: isize = -1;
/// A simple stream of symbols whose values are represented as integers. This
/// interface provides *marked ranges* with support for a minimum level
/// of buffering necessary to implement arbitrary lookahead during prediction.
pub trait IntStream {
/// Consumes the current symbol in the stream.
/// Advances this stream to the next element.
///
/// This method has the following
/// effects:
///
/// - Forward movement: The value of `index`
/// before calling this method is less than the value of `index`
/// after calling this method.
/// - Ordered lookahead: The value of {@code LA(1)} before
/// calling this method becomes the value of {@code LA(-1)} after calling
/// this method.
///
/// Note that calling this method does not guarantee that `index()` is
/// incremented by exactly 1.
///
/// Allowed to panic if trying to consume EOF
fn consume(&mut self);
/// Lookaheads (or loopbacks if `i` is negative)
///
/// Gets the value of the symbol at offset {@code i} from the current
/// position. When {@code i==1}, this method returns the value of the current
/// symbol in the stream (which is the next symbol to be consumed). When
/// {@code i==-1}, this method returns the value of the previously read
/// symbol in the stream. It is not valid to call this method with
/// {@code i==0}, but the specific behavior is unspecified because this
/// method is frequently called from performance-critical code.
///
/// Note that default Lexer does not call this method with anything other than `-1`
/// so it can be used for optimizations in downstream implementations.
///
/// Must return `EOF` if `i` points to position at or beyond the end of the stream
fn la(&mut self, i: isize) -> isize;
/// After this call subsequent calls to seek must succeed if seek index is greater than mark index
///
/// Returns marker that should be used later by `release` call to release this stream from
fn mark(&mut self) -> isize;
/// Releases `marker`
fn release(&mut self, marker: isize);
/// Returns current position of the input stream
///
/// If there is active marker from `mark` then calling `seek` later with result of this call
/// should put stream in same state it is currently in.
fn index(&self) -> isize;
/// Put stream back in state it was when it was in `index` position
///
/// Allowed to panic if `index` does not belong to marked region(via `mark`-`release` calls)
fn seek(&mut self, index: isize);
/// Returns the total number of symbols in the stream.
fn size(&self) -> isize;
/// Returns name of the source this stream operates over if any
fn get_source_name(&self) -> String;
}
/// Iterator over `IntStream`
#[derive(Debug)]
pub struct IterWrapper<'a, T: IntStream>(pub &'a mut T);
impl<'a, T: IntStream> Iterator for IterWrapper<'a, T> {
type Item = isize;
fn next(&mut self) -> Option<Self::Item> {
let result = self.0.la(1);
self.0.consume();
match result {
EOF => None,
x => Some(x),
}
}
}