@@ -13,7 +13,7 @@ use crate::symbol::kw;
1313use crate :: ThinVec ;
1414use errors:: { Applicability , DiagnosticBuilder } ;
1515use log:: debug;
16- use syntax_pos:: Span ;
16+ use syntax_pos:: { Span , DUMMY_SP } ;
1717
1818pub trait RecoverQPath : Sized + ' static {
1919 const PATH_STYLE : PathStyle = PathStyle :: Expr ;
@@ -201,7 +201,7 @@ impl<'a> Parser<'a> {
201201
202202 let mut path = ast:: Path {
203203 segments : Vec :: new ( ) ,
204- span : syntax_pos :: DUMMY_SP ,
204+ span : DUMMY_SP ,
205205 } ;
206206 self . parse_path_segments ( & mut path. segments , T :: PATH_STYLE ) ?;
207207 path. span = ty_span. to ( self . prev_span ) ;
@@ -267,6 +267,58 @@ impl<'a> Parser<'a> {
267267 }
268268 }
269269
270+ /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
271+ /// closing delimiter.
272+ pub fn unexpected_try_recover (
273+ & mut self ,
274+ t : & token:: Token ,
275+ ) -> PResult < ' a , bool /* recovered */ > {
276+ let token_str = pprust:: token_to_string ( t) ;
277+ let this_token_str = self . this_token_descr ( ) ;
278+ let ( prev_sp, sp) = match ( & self . token , self . subparser_name ) {
279+ // Point at the end of the macro call when reaching end of macro arguments.
280+ ( token:: Token :: Eof , Some ( _) ) => {
281+ let sp = self . sess . source_map ( ) . next_point ( self . span ) ;
282+ ( sp, sp)
283+ }
284+ // We don't want to point at the following span after DUMMY_SP.
285+ // This happens when the parser finds an empty TokenStream.
286+ _ if self . prev_span == DUMMY_SP => ( self . span , self . span ) ,
287+ // EOF, don't want to point at the following char, but rather the last token.
288+ ( token:: Token :: Eof , None ) => ( self . prev_span , self . span ) ,
289+ _ => ( self . sess . source_map ( ) . next_point ( self . prev_span ) , self . span ) ,
290+ } ;
291+ let msg = format ! (
292+ "expected `{}`, found {}" ,
293+ token_str,
294+ match ( & self . token, self . subparser_name) {
295+ ( token:: Token :: Eof , Some ( origin) ) => format!( "end of {}" , origin) ,
296+ _ => this_token_str,
297+ } ,
298+ ) ;
299+ let mut err = self . struct_span_err ( sp, & msg) ;
300+ let label_exp = format ! ( "expected `{}`" , token_str) ;
301+ match self . recover_closing_delimiter ( & [ t. clone ( ) ] , err) {
302+ Err ( e) => err = e,
303+ Ok ( recovered) => {
304+ return Ok ( recovered) ;
305+ }
306+ }
307+ let cm = self . sess . source_map ( ) ;
308+ match ( cm. lookup_line ( prev_sp. lo ( ) ) , cm. lookup_line ( sp. lo ( ) ) ) {
309+ ( Ok ( ref a) , Ok ( ref b) ) if a. line == b. line => {
310+ // When the spans are in the same line, it means that the only content
311+ // between them is whitespace, point only at the found token.
312+ err. span_label ( sp, label_exp) ;
313+ }
314+ _ => {
315+ err. span_label ( prev_sp, label_exp) ;
316+ err. span_label ( sp, "unexpected token" ) ;
317+ }
318+ }
319+ Err ( err)
320+ }
321+
270322 /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
271323 /// and `await { <expr> }`.
272324 crate fn parse_incorrect_await_syntax (
@@ -562,4 +614,23 @@ impl<'a> Parser<'a> {
562614 }
563615 }
564616
617+ crate fn expected_expression_found ( & self ) -> DiagnosticBuilder < ' a > {
618+ let ( span, msg) = match ( & self . token , self . subparser_name ) {
619+ ( & token:: Token :: Eof , Some ( origin) ) => {
620+ let sp = self . sess . source_map ( ) . next_point ( self . span ) ;
621+ ( sp, format ! ( "expected expression, found end of {}" , origin) )
622+ }
623+ _ => ( self . span , format ! (
624+ "expected expression, found {}" ,
625+ self . this_token_descr( ) ,
626+ ) ) ,
627+ } ;
628+ let mut err = self . struct_span_err ( span, & msg) ;
629+ let sp = self . sess . source_map ( ) . start_point ( self . span ) ;
630+ if let Some ( sp) = self . sess . ambiguous_block_expr_parse . borrow ( ) . get ( & sp) {
631+ self . sess . expr_parentheses_needed ( & mut err, * sp, None ) ;
632+ }
633+ err. span_label ( span, "expected expression" ) ;
634+ err
635+ }
565636}
0 commit comments