1
1
import util:: interner;
2
2
import util:: interner:: intern;
3
3
import diagnostic;
4
+ import ast:: { tt_delim, tt_flat} ;
4
5
5
6
export reader, string_reader, new_string_reader, is_whitespace;
6
7
export nextch, is_eof, bump, get_str_from;
@@ -14,6 +15,26 @@ iface reader {
14
15
fn interner ( ) -> @interner:: interner < @str > ;
15
16
}
16
17
18
+ enum tt_frame_up { /* to break a circularity */
19
+ tt_frame_up( option < tt_frame > )
20
+ }
21
+
22
+ type tt_frame = @{
23
+ /* invariant: readme[idx] is always a tt_flat */
24
+ readme : [ ast:: token_tree ] ,
25
+ mut idx : uint ,
26
+ up : tt_frame_up
27
+ } ;
28
+
29
+ type tt_reader = @{
30
+ mut cur : tt_frame ,
31
+ interner : @interner:: interner < @str > ,
32
+ span_diagnostic : diagnostic:: span_handler ,
33
+ /* cached: */
34
+ mut cur_tok : token:: token ,
35
+ mut cur_chpos : uint
36
+ } ;
37
+
17
38
type string_reader = @{
18
39
span_diagnostic : diagnostic:: span_handler ,
19
40
src : @str ,
@@ -39,13 +60,56 @@ impl string_reader_as_reader of reader for string_reader {
39
60
}
40
61
fn fatal ( m : str ) -> ! {
41
62
self . span_diagnostic . span_fatal (
42
- ast_util:: mk_sp ( self . chpos , self . chpos ) ,
43
- m)
63
+ ast_util:: mk_sp ( self . chpos , self . chpos ) , m)
44
64
}
45
65
fn chpos ( ) -> uint { self . chpos }
46
66
fn interner ( ) -> @interner:: interner < @str > { self . interner }
47
67
}
48
68
69
+ impl tt_reader_as_reader of reader for tt_reader {
70
+ fn is_eof ( ) -> bool { self . cur_tok == token:: EOF }
71
+ fn next_token ( ) -> { tok : token:: token , chpos : uint } {
72
+ let ret_val = { tok: self . cur_tok , chpos: self . cur_chpos } ;
73
+ self . cur . idx += 1 u;
74
+ if self . cur . idx >= vec:: len ( self . cur . readme ) {
75
+ /* done with this set; pop */
76
+ alt self . cur . up {
77
+ tt_frame_up ( option:: none) {
78
+ self . cur_tok = token:: EOF ;
79
+ ret ret_val;
80
+ }
81
+ tt_frame_up ( option:: some ( tt_f) ) {
82
+ self . cur = tt_f;
83
+ /* the above `if` would need to be a `while` if we didn't know
84
+ that the last thing in a `tt_delim` is always a `tt_flat` */
85
+ self . cur . idx += 1 u;
86
+ }
87
+ }
88
+ }
89
+ /* if `tt_delim`s could be 0-length, we'd need to be able to switch
90
+ between popping and pushing until we got to an actual `tt_flat` */
91
+ loop { /* because it's easiest, this handles `tt_delim` not starting
92
+ with a `tt_flat`, even though it won't happen */
93
+ alt self . cur . readme [ self . cur . idx ] {
94
+ tt_delim ( tts) {
95
+ self . cur = @{ readme: tts, mut idx: 0 u,
96
+ up: tt_frame_up ( option:: some ( self . cur ) ) } ;
97
+ }
98
+ tt_flat ( chpos, tok) {
99
+ self . cur_chpos = chpos; self . cur_tok = tok;
100
+ ret ret_val;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ fn fatal ( m : str ) -> ! {
106
+ self . span_diagnostic . span_fatal (
107
+ ast_util:: mk_sp ( self . chpos ( ) , self . chpos ( ) ) , m) ;
108
+ }
109
+ fn chpos ( ) -> uint { self . cur_chpos }
110
+ fn interner ( ) -> @interner:: interner < @str > { self . interner }
111
+ }
112
+
49
113
fn get_str_from ( rdr : string_reader , start : uint ) -> str unsafe {
50
114
// I'm pretty skeptical about this subtraction. What if there's a
51
115
// multi-byte character before the mark?
0 commit comments