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