Skip to content

Commit a97f60e

Browse files
committed
syntax: Make is_path_start precise and improve some error messages about unexpected tokens
1 parent 6c44bea commit a97f60e

25 files changed

+88
-73
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,17 @@ impl<'a> Parser<'a> {
394394
Parser::token_to_string(&self.token)
395395
}
396396

397+
pub fn this_token_descr(&self) -> String {
398+
let s = self.this_token_to_string();
399+
if self.token.is_strict_keyword() {
400+
format!("keyword `{}`", s)
401+
} else if self.token.is_reserved_keyword() {
402+
format!("reserved keyword `{}`", s)
403+
} else {
404+
format!("`{}`", s)
405+
}
406+
}
407+
397408
pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
398409
let token_str = Parser::token_to_string(t);
399410
let last_span = self.last_span;
@@ -1466,7 +1477,7 @@ impl<'a> Parser<'a> {
14661477
self.parse_qualified_path(PathStyle::Type)?;
14671478

14681479
TyKind::Path(Some(qself), path)
1469-
} else if self.is_path_start() {
1480+
} else if self.token.is_path_start() {
14701481
let path = self.parse_path(PathStyle::Type)?;
14711482
if self.check(&token::Not) {
14721483
// MACRO INVOCATION
@@ -1485,9 +1496,8 @@ impl<'a> Parser<'a> {
14851496
// TYPE TO BE INFERRED
14861497
TyKind::Infer
14871498
} else {
1488-
let this_token_str = self.this_token_to_string();
1489-
let msg = format!("expected type, found `{}`", this_token_str);
1490-
return Err(self.fatal(&msg[..]));
1499+
let msg = format!("expected type, found {}", self.this_token_descr());
1500+
return Err(self.fatal(&msg));
14911501
};
14921502

14931503
let sp = mk_sp(lo, self.last_span.hi);
@@ -1604,12 +1614,12 @@ impl<'a> Parser<'a> {
16041614
}
16051615

16061616
/// Matches token_lit = LIT_INTEGER | ...
1607-
pub fn lit_from_token(&self, tok: &token::Token) -> PResult<'a, LitKind> {
1608-
match *tok {
1617+
pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
1618+
let out = match self.token {
16091619
token::Interpolated(token::NtExpr(ref v)) => {
16101620
match v.node {
1611-
ExprKind::Lit(ref lit) => { Ok(lit.node.clone()) }
1612-
_ => { return self.unexpected_last(tok); }
1621+
ExprKind::Lit(ref lit) => { lit.node.clone() }
1622+
_ => { return self.unexpected_last(&self.token); }
16131623
}
16141624
}
16151625
token::Literal(lit, suf) => {
@@ -1624,13 +1634,13 @@ impl<'a> Parser<'a> {
16241634
(false, parse::integer_lit(&s.as_str(),
16251635
suf.as_ref().map(|s| s.as_str()),
16261636
&self.sess.span_diagnostic,
1627-
self.last_span))
1637+
self.span))
16281638
}
16291639
token::Float(s) => {
16301640
(false, parse::float_lit(&s.as_str(),
16311641
suf.as_ref().map(|s| s.as_str()),
16321642
&self.sess.span_diagnostic,
1633-
self.last_span))
1643+
self.span))
16341644
}
16351645

16361646
token::Str_(s) => {
@@ -1652,14 +1662,17 @@ impl<'a> Parser<'a> {
16521662
};
16531663

16541664
if suffix_illegal {
1655-
let sp = self.last_span;
1665+
let sp = self.span;
16561666
self.expect_no_suffix(sp, &format!("{} literal", lit.short_name()), suf)
16571667
}
16581668

1659-
Ok(out)
1669+
out
16601670
}
1661-
_ => { return self.unexpected_last(tok); }
1662-
}
1671+
_ => { return self.unexpected_last(&self.token); }
1672+
};
1673+
1674+
self.bump();
1675+
Ok(out)
16631676
}
16641677

16651678
/// Matches lit = true | false | token_lit
@@ -1670,8 +1683,7 @@ impl<'a> Parser<'a> {
16701683
} else if self.eat_keyword(keywords::False) {
16711684
LitKind::Bool(false)
16721685
} else {
1673-
let token = self.bump_and_get();
1674-
let lit = self.lit_from_token(&token)?;
1686+
let lit = self.parse_lit_token()?;
16751687
lit
16761688
};
16771689
Ok(codemap::Spanned { node: lit, span: mk_sp(lo, self.last_span.hi) })
@@ -2338,7 +2350,7 @@ impl<'a> Parser<'a> {
23382350
let mut db = self.fatal("expected expression, found statement (`let`)");
23392351
db.note("variable declaration using `let` is a statement");
23402352
return Err(db);
2341-
} else if self.is_path_start() {
2353+
} else if self.token.is_path_start() {
23422354
let pth = self.parse_path(PathStyle::Expr)?;
23432355

23442356
// `!`, as an operator, is prefix, so we know this isn't that
@@ -2419,10 +2431,18 @@ impl<'a> Parser<'a> {
24192431
hi = pth.span.hi;
24202432
ex = ExprKind::Path(None, pth);
24212433
} else {
2422-
// other literal expression
2423-
let lit = self.parse_lit()?;
2424-
hi = lit.span.hi;
2425-
ex = ExprKind::Lit(P(lit));
2434+
match self.parse_lit() {
2435+
Ok(lit) => {
2436+
hi = lit.span.hi;
2437+
ex = ExprKind::Lit(P(lit));
2438+
}
2439+
Err(mut err) => {
2440+
err.cancel();
2441+
let msg = format!("expected expression, found {}",
2442+
self.this_token_descr());
2443+
return Err(self.fatal(&msg));
2444+
}
2445+
}
24262446
}
24272447
}
24282448
}
@@ -3567,7 +3587,7 @@ impl<'a> Parser<'a> {
35673587
}
35683588

35693589
fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
3570-
if self.is_path_start() {
3590+
if self.token.is_path_start() {
35713591
let lo = self.span.lo;
35723592
let (qself, path) = if self.eat_lt() {
35733593
// Parse a qualified path
@@ -3585,12 +3605,6 @@ impl<'a> Parser<'a> {
35853605
}
35863606
}
35873607

3588-
fn is_path_start(&self) -> bool {
3589-
(self.token == token::Lt || self.token == token::ModSep
3590-
|| self.token.is_ident() || self.token.is_path())
3591-
&& !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False)
3592-
}
3593-
35943608
/// Parse a pattern.
35953609
pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
35963610
maybe_whole!(self, NtPat);
@@ -3641,7 +3655,7 @@ impl<'a> Parser<'a> {
36413655
// Parse box pat
36423656
let subpat = self.parse_pat()?;
36433657
pat = PatKind::Box(subpat);
3644-
} else if self.is_path_start() {
3658+
} else if self.token.is_path_start() {
36453659
// Parse pattern starting with a path
36463660
if self.token.is_ident() && self.look_ahead(1, |t| *t != token::DotDotDot &&
36473661
*t != token::OpenDelim(token::Brace) &&
@@ -3731,12 +3745,20 @@ impl<'a> Parser<'a> {
37313745
}
37323746
} else {
37333747
// Try to parse everything else as literal with optional minus
3734-
let begin = self.parse_pat_literal_maybe_minus()?;
3735-
if self.eat(&token::DotDotDot) {
3736-
let end = self.parse_pat_range_end()?;
3737-
pat = PatKind::Range(begin, end);
3738-
} else {
3739-
pat = PatKind::Lit(begin);
3748+
match self.parse_pat_literal_maybe_minus() {
3749+
Ok(begin) => {
3750+
if self.eat(&token::DotDotDot) {
3751+
let end = self.parse_pat_range_end()?;
3752+
pat = PatKind::Range(begin, end);
3753+
} else {
3754+
pat = PatKind::Lit(begin);
3755+
}
3756+
}
3757+
Err(mut err) => {
3758+
err.cancel();
3759+
let msg = format!("expected pattern, found {}", self.this_token_descr());
3760+
return Err(self.fatal(&msg));
3761+
}
37403762
}
37413763
}
37423764
}

src/libsyntax/parse/token.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ impl Token {
243243
self.is_keyword(keywords::Const)
244244
}
245245

246+
pub fn is_path_start(&self) -> bool {
247+
self == &ModSep || self == &Lt || self.is_path() ||
248+
self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword()
249+
}
250+
246251
/// Maps a token to its corresponding binary operator.
247252
pub fn to_binop(&self) -> Option<BinOpKind> {
248253
match *self {

src/test/compile-fail/fail-simple.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
12-
// error-pattern:unexpected token
1311
fn main() {
14-
panic!(@);
12+
panic!(@); //~ ERROR expected expression, found `@`
1513
}

src/test/compile-fail/issue-10636-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ pub fn trace_option(option: Option<isize>) {
1515
option.map(|some| 42; //~ NOTE: unclosed delimiter
1616
//~^ ERROR: expected one of
1717
} //~ ERROR: incorrect close delimiter
18-
//~^ ERROR: unexpected token
18+
//~^ ERROR: expected expression, found `)`

src/test/compile-fail/issue-31804.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313

1414
fn main() {
1515
let
16-
} //~ ERROR unexpected token: `}`
16+
} //~ ERROR expected pattern, found `}`

src/test/compile-fail/macro-context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
// (typeof used because it's surprisingly hard to find an unparsed token after a stmt)
1414
macro_rules! m {
15-
() => ( i ; typeof ); //~ ERROR `typeof` is a reserved keyword
15+
() => ( i ; typeof ); //~ ERROR expected expression, found reserved keyword `typeof`
1616
//~| ERROR macro expansion ignores token `typeof`
1717
//~| ERROR macro expansion ignores token `;`
1818
//~| ERROR macro expansion ignores token `;`

src/test/compile-fail/macro-incomplete-parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ macro_rules! ignored_item {
1919
}
2020

2121
macro_rules! ignored_expr {
22-
() => ( 1, //~ ERROR unexpected token: `,`
22+
() => ( 1, //~ ERROR expected expression, found `,`
2323
2 )
2424
}
2525

src/test/compile-fail/reserved-become.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010

1111
fn main() {
1212
let become = 0;
13-
//~^ ERROR `become` is a reserved keyword
13+
//~^ ERROR expected pattern, found reserved keyword `become`
1414
}

src/test/compile-fail/token-error-correct.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
fn main() {
1414
foo(bar(; //~ NOTE: unclosed delimiter
1515
//~^ NOTE: unclosed delimiter
16-
//~^^ ERROR: unexpected token: `;`
16+
//~^^ ERROR: expected expression, found `;`
1717
//~^^^ ERROR: unresolved name `bar`
1818
//~^^^^ ERROR: unresolved name `foo`
19+
//~^^^^^ ERROR: expected one of `)`, `,`, `.`, `<`, `?`
1920
} //~ ERROR: incorrect close delimiter: `}`
2021
//~^ ERROR: incorrect close delimiter: `}`
22+
//~^^ ERROR: expected expression, found `)`

src/test/compile-fail/vec-macro-with-comma-only.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
pub fn main() {
12-
vec!(,); //~ ERROR unexpected token
12+
vec!(,); //~ ERROR expected expression, found `,`
1313
}

0 commit comments

Comments
 (0)