// let _ = b"e";
// let _ = br"f";
// }
-pub(crate) const LITERAL_FIRST: TokenSet =
- TokenSet::new(&[TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, STRING, BYTE_STRING]);
+pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[
+ T![true],
+ T![false],
+ INT_NUMBER,
+ FLOAT_NUMBER,
+ BYTE,
+ CHAR,
+ STRING,
+ BYTE_STRING,
+]);
pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
if !p.at_ts(LITERAL_FIRST) {
T![continue],
T![async],
T![try],
+ T![const],
T![loop],
T![for],
- LIFETIME,
+ LIFETIME_IDENT,
]));
const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[LET_KW, R_DOLLAR]);
T![for] => for_expr(p, None),
T![while] => while_expr(p, None),
T![try] => try_block_expr(p, None),
- LIFETIME if la == T![:] => {
+ LIFETIME_IDENT if la == T![:] => {
let m = p.start();
label(p);
match p.current() {
block_expr(p);
m.complete(p, EFFECT_EXPR)
}
+ // test const_block
+ // fn f() { const { } }
+ T![const] if la == T!['{'] => {
+ let m = p.start();
+ p.bump(T![const]);
+ block_expr(p);
+ m.complete(p, EFFECT_EXPR)
+ }
T!['{'] => {
// test for_range_from
// fn foo() {
let mut saw_expr = false;
while !p.at(EOF) && !p.at(T![')']) {
saw_expr = true;
- if !p.at_ts(EXPR_FIRST) {
- p.error("expected expression");
+
+ // test tuple_attrs
+ // const A: (i64, i64) = (1, #[cfg(test)] 2);
+ if !expr_with_attrs(p) {
break;
}
- expr(p);
+
if !p.at(T![')']) {
saw_comma = true;
p.expect(T![,]);
// 'c: for x in () {}
// }
fn label(p: &mut Parser) {
- assert!(p.at(LIFETIME) && p.nth(1) == T![:]);
+ assert!(p.at(LIFETIME_IDENT) && p.nth(1) == T![:]);
let m = p.start();
- p.bump(LIFETIME);
+ lifetime(p);
p.bump_any();
m.complete(p, LABEL);
}
assert!(p.at(T![continue]));
let m = p.start();
p.bump(T![continue]);
- p.eat(LIFETIME);
+ if p.at(LIFETIME_IDENT) {
+ lifetime(p);
+ }
m.complete(p, CONTINUE_EXPR)
}
assert!(p.at(T![break]));
let m = p.start();
p.bump(T![break]);
- p.eat(LIFETIME);
+ if p.at(LIFETIME_IDENT) {
+ lifetime(p);
+ }
// test break_ambiguity
// fn foo(){
// if break {}