Skip to content

Commit 5d93522

Browse files
committed
added parse_token_trees.rs
1 parent 828fa46 commit 5d93522

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
use parse::lexer;
2+
use parse::lexer::StringReader;
3+
use parse::token;
4+
use ast::token_tree;
5+
6+
fn parse_sep_and_zerok(rdr: @mut StringReader) -> (Option<token::Token>, bool) {
7+
if *rdr.token == token::BINOP(token::STAR)
8+
|| *rdr.token == token::BINOP(token::PLUS) {
9+
let zerok = *rdr.token == token::BINOP(token::STAR);
10+
rdr.bump();
11+
(None, zerok)
12+
} else {
13+
let sep = copy *rdr.token;
14+
rdr.bump();
15+
if *rdr.token == token::BINOP(token::STAR)
16+
|| *rdr.token == token::BINOP(token::PLUS) {
17+
let zerok = *rdr.token == token::BINOP(token::STAR);
18+
rdr.bump();
19+
(Some(sep), zerok)
20+
} else {
21+
rdr.fatal("expected `*` or `+`");
22+
}
23+
}
24+
}
25+
26+
// parse a single token tree from the input.
27+
fn parse_token_tree(rdr: @mut StringReader) -> token_tree {
28+
// should be unnecessary now...
29+
//maybe_whole!(deref self, nt_tt);
30+
31+
// this is the fall-through for the 'match' below.
32+
// invariants: the current token is not a left-delimiter,
33+
// not an EOF, and not the desired right-delimiter (if
34+
// it were, parse_seq_to_before_end would have prevented
35+
// reaching this point.
36+
fn parse_non_delim_tt_tok(p: &Parser) -> token_tree {
37+
// should be unnecessary now...
38+
//maybe_whole!(deref p, nt_tt);
39+
match *p.token {
40+
token::RPAREN | token::RBRACE | token::RBRACKET =>
41+
{
42+
p.fatal(
43+
fmt!(
44+
"incorrect close delimiter: `%s`",
45+
p.this_token_to_str()
46+
)
47+
);
48+
}
49+
/* we ought to allow different depths of unquotation */
50+
token::DOLLAR if *p.quote_depth > 0u => {
51+
p.bump();
52+
let sp = *p.span;
53+
54+
if *p.token == token::LPAREN {
55+
let seq = p.parse_seq(
56+
&token::LPAREN,
57+
&token::RPAREN,
58+
seq_sep_none(),
59+
|p| p.parse_token_tree()
60+
);
61+
let (s, z) = p.parse_sep_and_zerok();
62+
let seq = match seq {
63+
spanned { node, _ } => node,
64+
};
65+
tt_seq(
66+
mk_sp(sp.lo, p.span.hi),
67+
seq,
68+
s,
69+
z
70+
)
71+
} else {
72+
tt_nonterminal(sp, p.parse_ident())
73+
}
74+
}
75+
_ => {
76+
parse_any_tt_tok(p)
77+
}
78+
}
79+
}
80+
81+
// turn the next token into a tt_tok:
82+
fn parse_any_tt_tok(p: &Parser) -> token_tree{
83+
let res = tt_tok(*p.span, copy *p.token);
84+
p.bump();
85+
res
86+
}
87+
88+
match *rdr.token {
89+
token::EOF => {
90+
rdr.fatal("file ended with unbalanced delimiters");
91+
}
92+
token::LPAREN | token::LBRACE | token::LBRACKET => {
93+
let close_delim = token::flip_delimiter(&*rdr.token);
94+
tt_delim(
95+
vec::append(
96+
// the open delimiter:
97+
~[parse_any_tt_tok(self)],
98+
vec::append(
99+
rdr.parse_seq_to_before_end(
100+
&close_delim,
101+
seq_sep_none(),
102+
|p| p.parse_token_tree()
103+
),
104+
// the close delimiter:
105+
[parse_any_tt_tok(self)]
106+
)
107+
)
108+
)
109+
}
110+
_ => parse_non_delim_tt_tok(self)
111+
}
112+
}
113+
114+
// parse a stream of tokens into a list of token_trees,
115+
// up to EOF.
116+
fn parse_all_token_trees(rdr: @mut StringReader) -> ~[token_tree] {
117+
let mut tts = ~[];
118+
while *rdr.token != token::EOF {
119+
tts.push(parse_token_tree(rdr));
120+
}
121+
tts
122+
}
123+
124+
fn parse_matchers(rdr: @mut StringReader) -> ~[matcher] {
125+
// unification of matchers and token_trees would vastly improve
126+
// the interpolation of matchers
127+
maybe_whole!(self, nt_matchers);
128+
let name_idx = @mut 0u;
129+
match *rdr.token {
130+
token::LBRACE | token::LPAREN | token::LBRACKET => {
131+
parse_matcher_subseq(
132+
rdr,
133+
name_idx,
134+
copy *rdr.token,
135+
// tjc: not sure why we need a copy
136+
token::flip_delimiter(rdr.token)
137+
)
138+
}
139+
_ => rdr.fatal("expected open delimiter")
140+
}
141+
}
142+
143+
144+
// This goofy function is necessary to correctly match parens in matchers.
145+
// Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
146+
// invalid. It's similar to common::parse_seq.
147+
fn parse_matcher_subseq(
148+
rdr: @mut StringReader,
149+
name_idx: @mut uint,
150+
bra: token::Token,
151+
ket: token::Token
152+
) -> ~[matcher] {
153+
let mut ret_val = ~[];
154+
let mut lparens = 0u;
155+
156+
// oops... got to fix this:
157+
expect(rdr,&bra);
158+
159+
while *rdr.token != ket || lparens > 0u {
160+
if *rdr.token == token::LPAREN { lparens += 1u; }
161+
if *rdr.token == token::RPAREN { lparens -= 1u; }
162+
ret_val.push(parse_matcher(rdr,name_idx));
163+
}
164+
165+
rdr.bump();
166+
167+
return ret_val;
168+
}
169+
170+
fn parse_matcher(rdr: @mut StringReader, name_idx: @mut uint) -> matcher {
171+
let lo = rdr.span.lo;
172+
173+
let m = if *rdr.token == token::DOLLAR {
174+
rdr.bump();
175+
if *rdr.token == token::LPAREN {
176+
let name_idx_lo = *name_idx;
177+
let ms = parse_matcher_subseq(
178+
rdr,
179+
name_idx,
180+
token::LPAREN,
181+
token::RPAREN
182+
);
183+
if ms.len() == 0u {
184+
rdr.fatal("repetition body must be nonempty");
185+
}
186+
let (sep, zerok) = parse_sep_and_zerok(rdr);
187+
match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
188+
} else {
189+
// problem here:
190+
let bound_to = parse_ident(rdr);
191+
// problem here:
192+
expect(rdr,&token::COLON);
193+
// and here:
194+
let nt_name = parse_ident(rdr);
195+
let m = match_nonterminal(bound_to, nt_name, *name_idx);
196+
*name_idx += 1u;
197+
m
198+
}
199+
} else {
200+
let m = match_tok(copy *rdr.token);
201+
rdr.bump();
202+
m
203+
};
204+
205+
return spanned(lo, rdr.span.hi, m);
206+
}
207+

0 commit comments

Comments
 (0)