2019-07-03 12:07:41 +00:00
|
|
|
use syntax_pos::Span;
|
2019-05-12 16:55:16 +00:00
|
|
|
|
2019-02-06 17:33:01 +00:00
|
|
|
use crate::print::pprust::token_to_string;
|
2019-01-28 05:04:50 +00:00
|
|
|
use crate::parse::lexer::{StringReader, UnmatchedBrace};
|
2019-06-04 21:02:59 +00:00
|
|
|
use crate::parse::token::{self, Token};
|
|
|
|
use crate::parse::PResult;
|
2019-07-03 12:07:41 +00:00
|
|
|
use crate::tokenstream::{DelimSpan, IsJoint::{self, *}, TokenStream, TokenTree, TreeAndJoint};
|
2017-01-12 23:32:00 +00:00
|
|
|
|
|
|
|
impl<'a> StringReader<'a> {
|
2019-05-12 16:55:16 +00:00
|
|
|
crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
|
|
|
|
let mut tt_reader = TokenTreesReader {
|
|
|
|
string_reader: self,
|
2019-06-05 06:39:34 +00:00
|
|
|
token: Token::dummy(),
|
2019-07-03 12:07:41 +00:00
|
|
|
joint_to_prev: Joint,
|
2019-05-12 16:55:16 +00:00
|
|
|
open_braces: Vec::new(),
|
|
|
|
unmatched_braces: Vec::new(),
|
|
|
|
matching_delim_spans: Vec::new(),
|
|
|
|
last_unclosed_found_span: None,
|
|
|
|
};
|
|
|
|
let res = tt_reader.parse_all_token_trees();
|
|
|
|
(res, tt_reader.unmatched_braces)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct TokenTreesReader<'a> {
|
|
|
|
string_reader: StringReader<'a>,
|
2019-06-04 21:02:59 +00:00
|
|
|
token: Token,
|
2019-07-03 12:07:41 +00:00
|
|
|
joint_to_prev: IsJoint,
|
2019-05-12 16:55:16 +00:00
|
|
|
/// Stack of open delimiters and their spans. Used for error message.
|
|
|
|
open_braces: Vec<(token::DelimToken, Span)>,
|
|
|
|
unmatched_braces: Vec<UnmatchedBrace>,
|
|
|
|
/// The type and spans for all braces
|
|
|
|
///
|
|
|
|
/// Used only for error recovery when arriving to EOF with mismatched braces.
|
|
|
|
matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
|
|
|
|
last_unclosed_found_span: Option<Span>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> TokenTreesReader<'a> {
|
2017-01-12 23:32:00 +00:00
|
|
|
// Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
|
2019-05-12 16:55:16 +00:00
|
|
|
fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
|
2019-08-19 16:30:44 +00:00
|
|
|
let mut buf = TokenStreamBuilder::default();
|
2018-08-12 13:43:51 +00:00
|
|
|
|
2019-05-13 09:06:37 +00:00
|
|
|
self.real_token();
|
|
|
|
while self.token != token::Eof {
|
2019-08-19 16:30:44 +00:00
|
|
|
buf.push(self.parse_token_tree()?);
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
2018-08-12 13:43:51 +00:00
|
|
|
|
2019-08-19 16:30:44 +00:00
|
|
|
Ok(buf.into_token_stream())
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
|
2017-02-21 05:05:59 +00:00
|
|
|
fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
|
2019-08-19 16:30:44 +00:00
|
|
|
let mut buf = TokenStreamBuilder::default();
|
2017-01-12 23:32:00 +00:00
|
|
|
loop {
|
2019-06-04 21:02:59 +00:00
|
|
|
if let token::CloseDelim(..) = self.token.kind {
|
2019-08-19 16:30:44 +00:00
|
|
|
return buf.into_token_stream();
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
2018-08-12 13:43:51 +00:00
|
|
|
|
2018-05-17 16:30:43 +00:00
|
|
|
match self.parse_token_tree() {
|
2019-08-19 16:30:44 +00:00
|
|
|
Ok(tree) => buf.push(tree),
|
2017-01-12 23:32:00 +00:00
|
|
|
Err(mut e) => {
|
|
|
|
e.emit();
|
2019-08-19 16:30:44 +00:00
|
|
|
return buf.into_token_stream();
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
2018-05-17 16:30:43 +00:00
|
|
|
}
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-19 03:53:52 +00:00
|
|
|
fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
|
2019-05-12 16:55:16 +00:00
|
|
|
let sm = self.string_reader.sess.source_map();
|
2019-06-04 21:02:59 +00:00
|
|
|
match self.token.kind {
|
2017-01-12 23:32:00 +00:00
|
|
|
token::Eof => {
|
|
|
|
let msg = "this file contains an un-closed delimiter";
|
2019-05-12 16:55:16 +00:00
|
|
|
let mut err = self.string_reader.sess.span_diagnostic
|
2019-06-04 21:02:59 +00:00
|
|
|
.struct_span_err(self.token.span, msg);
|
2017-01-12 23:32:00 +00:00
|
|
|
for &(_, sp) in &self.open_braces {
|
2018-08-27 00:22:36 +00:00
|
|
|
err.span_label(sp, "un-closed delimiter");
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
2018-08-12 13:43:51 +00:00
|
|
|
|
2018-09-04 15:09:49 +00:00
|
|
|
if let Some((delim, _)) = self.open_braces.last() {
|
2018-09-09 21:55:46 +00:00
|
|
|
if let Some((_, open_sp, close_sp)) = self.matching_delim_spans.iter()
|
|
|
|
.filter(|(d, open_sp, close_sp)| {
|
2019-05-12 16:55:16 +00:00
|
|
|
if let Some(close_padding) = sm.span_to_margin(*close_sp) {
|
|
|
|
if let Some(open_padding) = sm.span_to_margin(*open_sp) {
|
|
|
|
return delim == d && close_padding != open_padding;
|
|
|
|
}
|
2018-09-09 21:55:46 +00:00
|
|
|
}
|
2019-05-12 16:55:16 +00:00
|
|
|
false
|
2018-09-09 21:55:46 +00:00
|
|
|
}).next() // these are in reverse order as they get inserted on close, but
|
|
|
|
{ // we want the last open/first close
|
|
|
|
err.span_label(
|
|
|
|
*open_sp,
|
|
|
|
"this delimiter might not be properly closed...",
|
|
|
|
);
|
|
|
|
err.span_label(
|
|
|
|
*close_sp,
|
|
|
|
"...as it matches this but it has different indentation",
|
|
|
|
);
|
2018-09-04 15:09:49 +00:00
|
|
|
}
|
|
|
|
}
|
2017-01-12 23:32:00 +00:00
|
|
|
Err(err)
|
|
|
|
},
|
|
|
|
token::OpenDelim(delim) => {
|
|
|
|
// The span for beginning of the delimited section
|
2019-06-04 21:02:59 +00:00
|
|
|
let pre_span = self.token.span;
|
2017-01-12 23:32:00 +00:00
|
|
|
|
|
|
|
// Parse the open delimiter.
|
2019-06-04 21:02:59 +00:00
|
|
|
self.open_braces.push((delim, self.token.span));
|
2019-05-13 09:06:37 +00:00
|
|
|
self.real_token();
|
2017-01-12 23:32:00 +00:00
|
|
|
|
|
|
|
// Parse the token trees within the delimiters.
|
|
|
|
// We stop at any delimiter so we can try to recover if the user
|
|
|
|
// uses an incorrect delimiter.
|
|
|
|
let tts = self.parse_token_trees_until_close_delim();
|
|
|
|
|
|
|
|
// Expand to cover the entire delimited token tree
|
2019-06-04 21:02:59 +00:00
|
|
|
let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
|
2017-01-12 23:32:00 +00:00
|
|
|
|
2019-06-04 21:02:59 +00:00
|
|
|
match self.token.kind {
|
2017-01-12 23:32:00 +00:00
|
|
|
// Correct delimiter.
|
|
|
|
token::CloseDelim(d) if d == delim => {
|
2018-09-04 15:09:49 +00:00
|
|
|
let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
|
2018-12-17 04:00:17 +00:00
|
|
|
if self.open_braces.len() == 0 {
|
|
|
|
// Clear up these spans to avoid suggesting them as we've found
|
|
|
|
// properly matched delimiters so far for an entire block.
|
|
|
|
self.matching_delim_spans.clear();
|
|
|
|
} else {
|
|
|
|
self.matching_delim_spans.push(
|
2019-06-04 21:02:59 +00:00
|
|
|
(open_brace, open_brace_span, self.token.span),
|
2018-12-17 04:00:17 +00:00
|
|
|
);
|
|
|
|
}
|
2017-01-12 23:32:00 +00:00
|
|
|
// Parse the close delimiter.
|
2019-05-13 09:06:37 +00:00
|
|
|
self.real_token();
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
|
|
|
// Incorrect delimiter.
|
|
|
|
token::CloseDelim(other) => {
|
2019-01-28 05:04:50 +00:00
|
|
|
let mut unclosed_delimiter = None;
|
|
|
|
let mut candidate = None;
|
2019-06-04 21:02:59 +00:00
|
|
|
if self.last_unclosed_found_span != Some(self.token.span) {
|
2018-08-15 21:26:03 +00:00
|
|
|
// do not complain about the same unclosed delimiter multiple times
|
2019-06-04 21:02:59 +00:00
|
|
|
self.last_unclosed_found_span = Some(self.token.span);
|
2018-08-15 21:26:03 +00:00
|
|
|
// This is a conservative error: only report the last unclosed
|
|
|
|
// delimiter. The previous unclosed delimiters could actually be
|
|
|
|
// closed! The parser just hasn't gotten to them yet.
|
|
|
|
if let Some(&(_, sp)) = self.open_braces.last() {
|
2019-01-28 05:04:50 +00:00
|
|
|
unclosed_delimiter = Some(sp);
|
2018-08-15 21:26:03 +00:00
|
|
|
};
|
2019-06-04 21:02:59 +00:00
|
|
|
if let Some(current_padding) = sm.span_to_margin(self.token.span) {
|
2018-09-04 15:09:49 +00:00
|
|
|
for (brace, brace_span) in &self.open_braces {
|
|
|
|
if let Some(padding) = sm.span_to_margin(*brace_span) {
|
|
|
|
// high likelihood of these two corresponding
|
|
|
|
if current_padding == padding && brace == &other {
|
2019-01-28 05:04:50 +00:00
|
|
|
candidate = Some(*brace_span);
|
2018-09-04 15:09:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-01-28 05:04:50 +00:00
|
|
|
let (tok, _) = self.open_braces.pop().unwrap();
|
|
|
|
self.unmatched_braces.push(UnmatchedBrace {
|
|
|
|
expected_delim: tok,
|
|
|
|
found_delim: other,
|
2019-06-04 21:02:59 +00:00
|
|
|
found_span: self.token.span,
|
2019-01-28 05:04:50 +00:00
|
|
|
unclosed_span: unclosed_delimiter,
|
|
|
|
candidate_span: candidate,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
self.open_braces.pop();
|
2018-08-15 21:26:03 +00:00
|
|
|
}
|
2017-01-12 23:32:00 +00:00
|
|
|
|
|
|
|
// If the incorrect delimiter matches an earlier opening
|
|
|
|
// delimiter, then don't consume it (it can be used to
|
|
|
|
// close the earlier one). Otherwise, consume it.
|
|
|
|
// E.g., we try to recover from:
|
|
|
|
// fn foo() {
|
|
|
|
// bar(baz(
|
|
|
|
// } // Incorrect delimiter but matches the earlier `{`
|
|
|
|
if !self.open_braces.iter().any(|&(b, _)| b == other) {
|
2019-05-13 09:06:37 +00:00
|
|
|
self.real_token();
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
token::Eof => {
|
|
|
|
// Silently recover, the EOF token will be seen again
|
|
|
|
// and an error emitted then. Thus we don't pop from
|
|
|
|
// self.open_braces here.
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2018-11-29 23:02:04 +00:00
|
|
|
Ok(TokenTree::Delimited(
|
|
|
|
delim_span,
|
2017-08-07 05:54:09 +00:00
|
|
|
delim,
|
2018-12-19 03:53:52 +00:00
|
|
|
tts.into()
|
2018-11-29 23:02:04 +00:00
|
|
|
).into())
|
2017-01-12 23:32:00 +00:00
|
|
|
},
|
|
|
|
token::CloseDelim(_) => {
|
|
|
|
// An unexpected closing delimiter (i.e., there is no
|
|
|
|
// matching opening delimiter).
|
2019-05-13 09:06:37 +00:00
|
|
|
let token_str = token_to_string(&self.token);
|
2017-01-12 23:32:00 +00:00
|
|
|
let msg = format!("unexpected close delimiter: `{}`", token_str);
|
2019-05-12 16:55:16 +00:00
|
|
|
let mut err = self.string_reader.sess.span_diagnostic
|
2019-06-04 21:02:59 +00:00
|
|
|
.struct_span_err(self.token.span, &msg);
|
|
|
|
err.span_label(self.token.span, "unexpected close delimiter");
|
2017-01-12 23:32:00 +00:00
|
|
|
Err(err)
|
|
|
|
},
|
|
|
|
_ => {
|
2019-06-05 06:39:34 +00:00
|
|
|
let tt = TokenTree::Token(self.token.take());
|
2019-05-13 09:06:37 +00:00
|
|
|
self.real_token();
|
2019-07-03 12:07:41 +00:00
|
|
|
let is_joint = self.joint_to_prev == Joint && self.token.is_op();
|
2018-12-19 03:53:52 +00:00
|
|
|
Ok((tt, if is_joint { Joint } else { NonJoint }))
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 16:55:16 +00:00
|
|
|
|
2019-05-13 09:06:37 +00:00
|
|
|
fn real_token(&mut self) {
|
2019-07-03 12:07:41 +00:00
|
|
|
self.joint_to_prev = Joint;
|
|
|
|
loop {
|
|
|
|
let token = self.string_reader.next_token();
|
|
|
|
match token.kind {
|
2019-07-30 09:31:41 +00:00
|
|
|
token::Whitespace | token::Comment | token::Shebang(_) | token::Unknown(_) => {
|
2019-07-03 12:07:41 +00:00
|
|
|
self.joint_to_prev = NonJoint;
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.token = token;
|
|
|
|
return;
|
2019-08-19 16:30:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
struct TokenStreamBuilder {
|
|
|
|
buf: Vec<TreeAndJoint>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TokenStreamBuilder {
|
|
|
|
fn push(&mut self, (tree, joint): TreeAndJoint) {
|
|
|
|
if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() {
|
|
|
|
if let TokenTree::Token(token) = &tree {
|
|
|
|
if let Some(glued) = prev_token.glue(token) {
|
|
|
|
self.buf.pop();
|
|
|
|
self.buf.push((TokenTree::Token(glued), joint));
|
|
|
|
return;
|
|
|
|
}
|
2019-07-03 12:07:41 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-19 16:30:44 +00:00
|
|
|
self.buf.push((tree, joint))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_token_stream(self) -> TokenStream {
|
|
|
|
TokenStream::new(self.buf)
|
2019-05-12 16:55:16 +00:00
|
|
|
}
|
2017-01-12 23:32:00 +00:00
|
|
|
}
|