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
}

src/test/parse-fail/issue-14303-path.rs

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

1313
fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {}
1414
//~^ ERROR lifetime parameters must be declared prior to type parameters
15-
//~^^ ERROR unexpected token
15+
//~^^ ERROR expected pattern, found `'c`

src/test/parse-fail/issue-32505.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// compile-flags: -Z parse-only -Z continue-parse-after-error
1212

1313
pub fn test() {
14-
foo(|_|) //~ ERROR unexpected token: `)`
14+
foo(|_|) //~ ERROR expected expression, found `)`
1515
}
1616

1717
fn main() { }

src/test/parse-fail/keyword-abstract.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn main() {
14-
let abstract = (); //~ ERROR `abstract` is a reserved keyword
14+
let abstract = (); //~ ERROR expected pattern, found reserved keyword `abstract`
1515
}

src/test/parse-fail/keyword-final.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn main() {
14-
let final = (); //~ ERROR `final` is a reserved keyword
14+
let final = (); //~ ERROR expected pattern, found reserved keyword `final`
1515
}

src/test/parse-fail/keyword-override.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn main() {
14-
let override = (); //~ ERROR `override` is a reserved keyword
14+
let override = (); //~ ERROR expected pattern, found reserved keyword `override`
1515
}

src/test/parse-fail/keyword-typeof.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn main() {
14-
let typeof = (); //~ ERROR `typeof` is a reserved keyword
14+
let typeof = (); //~ ERROR expected pattern, found reserved keyword `typeof`
1515
}

src/test/parse-fail/keywords-followed-by-double-colon.rs

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

1313
fn main() {
1414
struct::foo(); //~ ERROR expected identifier
15-
mut::baz(); //~ ERROR expected identifier
15+
mut::baz(); //~ ERROR expected expression, found keyword `mut`
1616
}

src/test/parse-fail/match-arrows-block-then-binop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ fn main() {
1414

1515
match 0 {
1616
0 => {
17-
} + 5 //~ ERROR unexpected token: `+`
17+
} + 5 //~ ERROR expected pattern, found `+`
1818
}
1919
}

src/test/parse-fail/obsolete-proc.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212

1313
// Test that we generate obsolete syntax errors around usages of `proc`.
1414

15-
fn foo(p: proc()) { } //~ ERROR `proc` is a reserved keyword
15+
fn foo(p: proc()) { } //~ ERROR expected type, found reserved keyword `proc`
1616

17-
fn bar() { proc() 1; } //~ ERROR `proc` is a reserved keyword
18-
//~^ ERROR expected
17+
fn bar() { proc() 1; } //~ ERROR expected expression, found reserved keyword `proc`
1918

2019
fn main() { }

src/test/parse-fail/removed-syntax-mode.rs

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

1111
// compile-flags: -Z parse-only
1212

13-
fn f(+x: isize) {} //~ ERROR unexpected token: `+`
13+
fn f(+x: isize) {} //~ ERROR expected pattern, found `+`

src/test/parse-fail/removed-syntax-mut-vec-expr.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn f() {
14-
let v = [mut 1, 2, 3, 4];
15-
//~^ ERROR expected identifier, found keyword `mut`
16-
//~^^ ERROR expected one of `!`, `,`, `.`, `::`, `;`, `?`, `]`, `{`, or an operator, found `1`
14+
let v = [mut 1, 2, 3, 4]; //~ ERROR expected expression, found keyword `mut`
1715
}

src/test/parse-fail/removed-syntax-mut-vec-ty.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,4 @@
1010

1111
// compile-flags: -Z parse-only
1212

13-
type v = [mut isize];
14-
//~^ ERROR expected identifier, found keyword `mut`
15-
//~^^ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `isize`
13+
type v = [mut isize]; //~ ERROR expected type, found keyword `mut`

src/test/parse-fail/removed-syntax-uniq-mut-expr.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,5 @@
1111
// compile-flags: -Z parse-only
1212

1313
fn f() {
14-
let a_box = box mut 42;
15-
//~^ ERROR expected identifier, found keyword `mut`
16-
//~^^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `42`
14+
let a_box = box mut 42; //~ ERROR expected expression, found keyword `mut`
1715
}

src/test/parse-fail/removed-syntax-uniq-mut-ty.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,4 @@
1010

1111
// compile-flags: -Z parse-only
1212

13-
type mut_box = Box<mut isize>;
14-
//~^ ERROR expected identifier, found keyword `mut`
15-
//~^^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `isize`
13+
type mut_box = Box<mut isize>; //~ ERROR expected type, found keyword `mut`

src/test/parse-fail/unsized2.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,5 @@
1515
fn f<X>() {}
1616

1717
pub fn main() {
18-
f<type>();
19-
//~^ ERROR expected identifier, found keyword `type`
20-
//~^^ ERROR: chained comparison
21-
//~^^^ HELP: use `::<
18+
f<type>(); //~ ERROR expected expression, found keyword `type`
2219
}

0 commit comments

Comments
 (0)