Skip to content

Commit d619e89

Browse files
committed
Make token trees re-lexable.
1 parent 1d25981 commit d619e89

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

src/libsyntax/parse/lexer.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import util::interner;
22
import util::interner::intern;
33
import diagnostic;
4+
import ast::{tt_delim,tt_flat};
45

56
export reader, string_reader, new_string_reader, is_whitespace;
67
export nextch, is_eof, bump, get_str_from;
@@ -14,6 +15,26 @@ iface reader {
1415
fn interner() -> @interner::interner<@str>;
1516
}
1617

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+
1738
type string_reader = @{
1839
span_diagnostic: diagnostic::span_handler,
1940
src: @str,
@@ -39,13 +60,56 @@ impl string_reader_as_reader of reader for string_reader {
3960
}
4061
fn fatal(m: str) -> ! {
4162
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)
4464
}
4565
fn chpos() -> uint { self.chpos }
4666
fn interner() -> @interner::interner<@str> { self.interner }
4767
}
4868

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 += 1u;
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 += 1u;
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: 0u,
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+
49113
fn get_str_from(rdr: string_reader, start: uint) -> str unsafe {
50114
// I'm pretty skeptical about this subtraction. What if there's a
51115
// multi-byte character before the mark?

0 commit comments

Comments
 (0)