use print::pprust::token_to_string;
use parse::lexer::StringReader;
use parse::{token, PResult};
use tokenstream::{Delimited, TokenStream, TokenTree};
impl<'a> StringReader<'a> {
pub fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
let mut tts = Vec::new();
while self.token != token::Eof {
let tree = self.parse_token_tree()?;
let is_joint = tree.span().hi() == self.span.lo() && token::is_op(&self.token);
tts.push(if is_joint { tree.joint() } else { tree.into() });
}
Ok(TokenStream::concat(tts))
}
fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
let mut tts = vec![];
loop {
if let token::CloseDelim(..) = self.token {
return TokenStream::concat(tts);
}
let tree = match self.parse_token_tree() {
Ok(tree) => tree,
Err(mut e) => {
e.emit();
return TokenStream::concat(tts);
}
};
let is_joint = tree.span().hi() == self.span.lo() && token::is_op(&self.token);
tts.push(if is_joint { tree.joint() } else { tree.into() });
}
}
fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
match self.token {
token::Eof => {
let msg = "this file contains an un-closed delimiter";
let mut err = self.sess.span_diagnostic.struct_span_err(self.span, msg);
for &(_, sp) in &self.open_braces {
err.span_help(sp, "did you mean to close this delimiter?");
}
Err(err)
},
token::OpenDelim(delim) => {
let pre_span = self.span;
self.open_braces.push((delim, self.span));
self.real_token();
let tts = self.parse_token_trees_until_close_delim();
let span = pre_span.with_hi(self.span.hi());
match self.token {
token::CloseDelim(d) if d == delim => {
self.open_braces.pop().unwrap();
self.real_token();
}
token::CloseDelim(other) => {
let token_str = token_to_string(&self.token);
let msg = format!("incorrect close delimiter: `{}`", token_str);
let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
if let Some(&(_, sp)) = self.open_braces.last() {
err.span_note(sp, "unclosed delimiter");
};
err.emit();
self.open_braces.pop().unwrap();
if !self.open_braces.iter().any(|&(b, _)| b == other) {
self.real_token();
}
}
token::Eof => {
},
_ => {}
}
Ok(TokenTree::Delimited(span, Delimited {
delim,
tts: tts.into(),
}))
},
token::CloseDelim(_) => {
let token_str = token_to_string(&self.token);
let msg = format!("unexpected close delimiter: `{}`", token_str);
let err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
Err(err)
},
_ => {
let tt = TokenTree::Token(self.span, self.token.clone());
self.real_token();
Ok(tt)
}
}
}
}