fix: Fix parsing of integer/keyword name refs in various places

This commit is contained in:
Lukas Wirth 2024-12-05 14:37:38 +01:00
parent f499faf72b
commit df7ab62a06
33 changed files with 351 additions and 133 deletions

View file

@ -1733,7 +1733,7 @@ m!(C("0"));
macro_rules! m { macro_rules! m {
($k:expr) => { fn f() { K::$k; } } ($k:expr) => { fn f() { K::$k; } }
} }
/* parse error: expected identifier */ /* parse error: expected identifier, `self`, `super`, `crate`, or `Self` */
/* parse error: expected SEMICOLON */ /* parse error: expected SEMICOLON */
/* parse error: expected SEMICOLON */ /* parse error: expected SEMICOLON */
/* parse error: expected expression, item or let statement */ /* parse error: expected expression, item or let statement */

View file

@ -307,13 +307,49 @@ fn name(p: &mut Parser<'_>) {
name_r(p, TokenSet::EMPTY); name_r(p, TokenSet::EMPTY);
} }
fn name_ref(p: &mut Parser<'_>) { fn name_ref_or_self(p: &mut Parser<'_>) {
if p.at(IDENT) { if matches!(p.current(), T![ident] | T![self]) {
let m = p.start(); let m = p.start();
p.bump(IDENT); p.bump_any();
m.complete(p, NAME_REF); m.complete(p, NAME_REF);
} else { } else {
p.err_and_bump("expected identifier"); p.err_and_bump("expected identifier or `self`");
}
}
fn name_ref_or_upper_self(p: &mut Parser<'_>) {
if matches!(p.current(), T![ident] | T![Self]) {
let m = p.start();
p.bump_any();
m.complete(p, NAME_REF);
} else {
p.err_and_bump("expected identifier or `Self`");
}
}
const PATH_NAME_REF_KINDS: TokenSet =
TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self]]);
fn name_ref_mod_path(p: &mut Parser<'_>) {
if p.at_ts(PATH_NAME_REF_KINDS) {
let m = p.start();
p.bump_any();
m.complete(p, NAME_REF);
} else {
p.err_and_bump("expected identifier, `self`, `super`, `crate`, or `Self`");
}
}
const PATH_NAME_REF_OR_INDEX_KINDS: TokenSet =
PATH_NAME_REF_KINDS.union(TokenSet::new(&[INT_NUMBER]));
fn name_ref_mod_path_or_index(p: &mut Parser<'_>) {
if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
let m = p.start();
p.bump_any();
m.complete(p, NAME_REF);
} else {
p.err_and_bump("expected integer, identifier, `self`, `super`, `crate`, or `Self`");
} }
} }

View file

@ -449,7 +449,9 @@ fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
let nth1 = if FLOAT_RECOVERY { 0 } else { 1 }; let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
let nth2 = if FLOAT_RECOVERY { 1 } else { 2 }; let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
if p.nth(nth1) == IDENT && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::])) { if PATH_NAME_REF_KINDS.contains(p.nth(nth1))
&& (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::]))
{
return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs)); return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
} }
@ -510,21 +512,26 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
// y.bar::<T>(1, 2,); // y.bar::<T>(1, 2,);
// x.0.0.call(); // x.0.0.call();
// x.0. call(); // x.0. call();
// x.0()
// } // }
fn method_call_expr<const FLOAT_RECOVERY: bool>( fn method_call_expr<const FLOAT_RECOVERY: bool>(
p: &mut Parser<'_>, p: &mut Parser<'_>,
lhs: CompletedMarker, lhs: CompletedMarker,
) -> CompletedMarker { ) -> CompletedMarker {
if FLOAT_RECOVERY { if FLOAT_RECOVERY {
assert!(p.nth(0) == IDENT && (p.nth(1) == T!['('] || p.nth_at(1, T![::]))); assert!(p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
} else { } else {
assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::]))); assert!(
p.at(T![.])
&& PATH_NAME_REF_KINDS.contains(p.nth(1))
&& (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
);
} }
let m = lhs.precede(p); let m = lhs.precede(p);
if !FLOAT_RECOVERY { if !FLOAT_RECOVERY {
p.bump(T![.]); p.bump(T![.]);
} }
name_ref(p); name_ref_mod_path(p);
generic_args::opt_generic_arg_list_expr(p); generic_args::opt_generic_arg_list_expr(p);
if p.at(T!['(']) { if p.at(T!['(']) {
arg_list(p); arg_list(p);
@ -543,6 +550,8 @@ fn method_call_expr<const FLOAT_RECOVERY: bool>(
// test field_expr // test field_expr
// fn foo() { // fn foo() {
// x.self;
// x.Self;
// x.foo; // x.foo;
// x.0.bar; // x.0.bar;
// x.0.1; // x.0.1;
@ -560,8 +569,8 @@ fn field_expr<const FLOAT_RECOVERY: bool>(
if !FLOAT_RECOVERY { if !FLOAT_RECOVERY {
p.bump(T![.]); p.bump(T![.]);
} }
if p.at(IDENT) || p.at(INT_NUMBER) { if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
name_ref_or_index(p); name_ref_mod_path_or_index(p);
} else if p.at(FLOAT_NUMBER) { } else if p.at(FLOAT_NUMBER) {
return match p.split_float(m) { return match p.split_float(m) {
(true, m) => { (true, m) => {
@ -679,34 +688,37 @@ pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
IDENT | INT_NUMBER if p.nth_at(1, T![::]) => { IDENT | INT_NUMBER if p.nth_at(1, T![::]) => {
// test_err record_literal_missing_ellipsis_recovery // test_err record_literal_missing_ellipsis_recovery
// fn main() { // fn main() {
// S { S::default() } // S { S::default() };
// S { 0::default() };
// } // }
m.abandon(p); m.abandon(p);
p.expect(T![..]); p.expect(T![..]);
expr(p); expr(p);
} }
IDENT | INT_NUMBER if p.nth_at(1, T![..]) => {
// test_err record_literal_before_ellipsis_recovery
// fn main() {
// S { field ..S::default() }
// S { 0 ..S::default() }
// }
name_ref_or_index(p);
p.error("expected `:`");
m.complete(p, RECORD_EXPR_FIELD);
}
IDENT | INT_NUMBER => { IDENT | INT_NUMBER => {
if p.nth_at(1, T![..]) { // test_err record_literal_field_eq_recovery
// test_err record_literal_before_ellipsis_recovery // fn main() {
// fn main() { // S { field = foo }
// S { field ..S::default() } // S { 0 = foo }
// } // }
if p.nth_at(1, T![:]) {
name_ref_or_index(p); name_ref_or_index(p);
p.error("expected `:`"); p.bump(T![:]);
} else { } else if p.nth_at(1, T![=]) {
// test_err record_literal_field_eq_recovery name_ref_or_index(p);
// fn main() { p.err_and_bump("expected `:`");
// S { field = foo }
// }
if p.nth_at(1, T![:]) {
name_ref_or_index(p);
p.bump(T![:]);
} else if p.nth_at(1, T![=]) {
name_ref_or_index(p);
p.err_and_bump("expected `:`");
}
expr(p);
} }
expr(p);
m.complete(p, RECORD_EXPR_FIELD); m.complete(p, RECORD_EXPR_FIELD);
} }
T![.] if p.at(T![..]) => { T![.] if p.at(T![..]) => {

View file

@ -259,13 +259,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
type_(p); type_(p);
p.expect(T![,]); p.expect(T![,]);
while !p.at(EOF) && !p.at(T![')']) { while !p.at(EOF) && !p.at(T![')']) {
if p.at(IDENT) || p.at(INT_NUMBER) { name_ref_mod_path_or_index(p);
name_ref_or_index(p);
// } else if p.at(FLOAT_NUMBER) {
// FIXME: needs float hack
} else {
p.err_and_bump("expected field name or number");
}
if !p.at(T![')']) { if !p.at(T![')']) {
p.expect(T![.]); p.expect(T![.]);
} }
@ -465,9 +459,9 @@ fn parse_clobber_abi(p: &mut Parser<'_>) {
fn parse_reg(p: &mut Parser<'_>) { fn parse_reg(p: &mut Parser<'_>) {
p.expect(T!['(']); p.expect(T!['(']);
if p.at(T![ident]) { if p.at_ts(PATH_NAME_REF_KINDS) {
let m = p.start(); let m = p.start();
name_ref(p); name_ref_mod_path(p);
m.complete(p, ASM_REG_SPEC); m.complete(p, ASM_REG_SPEC);
} else if p.at(T![string]) { } else if p.at(T![string]) {
let m = p.start(); let m = p.start();

View file

@ -59,9 +59,9 @@ pub(crate) fn generic_arg(p: &mut Parser<'_>) -> bool {
// test macro_inside_generic_arg // test macro_inside_generic_arg
// type A = Foo<syn::Token![_]>; // type A = Foo<syn::Token![_]>;
IDENT => { k if PATH_NAME_REF_KINDS.contains(k) => {
let m = p.start(); let m = p.start();
name_ref(p); name_ref_mod_path(p);
paths::opt_path_type_args(p); paths::opt_path_type_args(p);
match p.current() { match p.current() {
T![=] => { T![=] => {

View file

@ -145,6 +145,9 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
T![for] => types::for_type(p, false), T![for] => types::for_type(p, false),
// test precise_capturing // test precise_capturing
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {} // fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T, Self> {}
// test_err precise_capturing_invalid
// type T = impl use<self, 1>;
T![use] if p.nth_at(1, T![<]) => { T![use] if p.nth_at(1, T![<]) => {
p.bump_any(); p.bump_any();
let m = p.start(); let m = p.start();
@ -156,14 +159,10 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
|| "expected identifier or lifetime".into(), || "expected identifier or lifetime".into(),
TokenSet::new(&[T![Self], IDENT, LIFETIME_IDENT]), TokenSet::new(&[T![Self], IDENT, LIFETIME_IDENT]),
|p| { |p| {
if p.at(T![Self]) { if p.at(LIFETIME_IDENT) {
let m = p.start();
p.bump(T![Self]);
m.complete(p, NAME_REF);
} else if p.at(LIFETIME_IDENT) {
lifetime(p); lifetime(p);
} else { } else {
name_ref(p); name_ref_or_upper_self(p);
} }
true true
}, },

View file

@ -254,22 +254,16 @@ fn opt_item_without_modifiers(p: &mut Parser<'_>, m: Marker) -> Result<(), Marke
// test extern_crate // test extern_crate
// extern crate foo; // extern crate foo;
// extern crate self;
fn extern_crate(p: &mut Parser<'_>, m: Marker) { fn extern_crate(p: &mut Parser<'_>, m: Marker) {
p.bump(T![extern]); p.bump(T![extern]);
p.bump(T![crate]); p.bump(T![crate]);
if p.at(T![self]) { name_ref_or_self(p);
// test extern_crate_self
// extern crate self;
let m = p.start();
p.bump(T![self]);
m.complete(p, NAME_REF);
} else {
name_ref(p);
}
// test extern_crate_rename // test extern_crate_rename
// extern crate foo as bar; // extern crate foo as bar;
// extern crate self as bar;
opt_rename(p); opt_rename(p);
p.expect(T![;]); p.expect(T![;]);
m.complete(p, EXTERN_CRATE); m.complete(p, EXTERN_CRATE);

View file

@ -107,37 +107,32 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
} }
} else { } else {
let mut empty = if first { !p.eat(T![::]) } else { true }; let mut empty = if first { !p.eat(T![::]) } else { true };
match p.current() { if p.at_ts(PATH_NAME_REF_KINDS) {
IDENT => {
name_ref(p);
opt_path_args(p, mode);
}
// test crate_path // test crate_path
// use crate::foo; // use crate::foo;
T![self] | T![super] | T![crate] | T![Self] => { name_ref_mod_path(p);
let m = p.start(); opt_path_args(p, mode);
p.bump_any(); } else {
m.complete(p, NAME_REF); let recover_set = match mode {
} Mode::Use => items::ITEM_RECOVERY_SET,
_ => { Mode::Attr => {
let recover_set = match mode { items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
Mode::Use => items::ITEM_RECOVERY_SET,
Mode::Attr => {
items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]]))
}
Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
};
empty &= p.err_recover("expected identifier", recover_set);
if empty {
// test_err empty_segment
// use crate::;
m.abandon(p);
return None;
} }
Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])),
Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
};
empty &= p.err_recover(
"expected identifier, `self`, `super`, `crate`, or `Self`",
recover_set,
);
if empty {
// test_err empty_segment
// use crate::;
m.abandon(p);
return None;
} }
}; }
} }
Some(m.complete(p, PATH_SEGMENT)) Some(m.complete(p, PATH_SEGMENT))
} }

View file

@ -210,10 +210,6 @@ mod ok {
run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_rename.rs"); run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_rename.rs");
} }
#[test] #[test]
fn extern_crate_self() {
run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_self.rs");
}
#[test]
fn field_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/field_expr.rs"); } fn field_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/field_expr.rs"); }
#[test] #[test]
fn fn_() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_.rs"); } fn fn_() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_.rs"); }
@ -774,6 +770,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs"); run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs");
} }
#[test] #[test]
fn precise_capturing_invalid() {
run_and_expect_errors("test_data/parser/inline/err/precise_capturing_invalid.rs");
}
#[test]
fn pub_expr() { run_and_expect_errors("test_data/parser/inline/err/pub_expr.rs"); } fn pub_expr() { run_and_expect_errors("test_data/parser/inline/err/pub_expr.rs"); }
#[test] #[test]
fn record_literal_before_ellipsis_recovery() { fn record_literal_before_ellipsis_recovery() {

View file

@ -13,4 +13,4 @@ SOURCE_FILE
ERROR ERROR
INT_NUMBER "92" INT_NUMBER "92"
SEMICOLON ";" SEMICOLON ";"
error 9: expected identifier error 9: expected identifier, `self`, `super`, `crate`, or `Self`

View file

@ -115,10 +115,10 @@ SOURCE_FILE
WHITESPACE "\n" WHITESPACE "\n"
R_CURLY "}" R_CURLY "}"
WHITESPACE "\n" WHITESPACE "\n"
error 30: expected identifier error 30: expected identifier, `self`, `super`, `crate`, or `Self`
error 31: expected COMMA error 31: expected COMMA
error 37: expected expression error 37: expected expression
error 75: expected identifier error 75: expected identifier, `self`, `super`, `crate`, or `Self`
error 76: expected SEMICOLON error 76: expected SEMICOLON
error 82: expected expression error 82: expected expression
error 83: expected SEMICOLON error 83: expected SEMICOLON

View file

@ -98,7 +98,7 @@ SOURCE_FILE
WHITESPACE "\n" WHITESPACE "\n"
R_CURLY "}" R_CURLY "}"
WHITESPACE "\n" WHITESPACE "\n"
error 25: expected identifier error 25: expected identifier, `self`, `super`, `crate`, or `Self`
error 39: expected COMMA error 39: expected COMMA
error 39: expected expression error 39: expected expression
error 55: expected expression error 55: expected expression

View file

@ -11,4 +11,4 @@ SOURCE_FILE
IDENT "S" IDENT "S"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
error 4: expected identifier error 4: expected identifier, `self`, `super`, `crate`, or `Self`

View file

@ -11,4 +11,4 @@ SOURCE_FILE
COLON2 "::" COLON2 "::"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
error 11: expected identifier error 11: expected identifier, `self`, `super`, `crate`, or `Self`

View file

@ -66,18 +66,18 @@ SOURCE_FILE
EQ "=" EQ "="
R_BRACK "]" R_BRACK "]"
WHITESPACE "\n" WHITESPACE "\n"
error 3: expected identifier error 3: expected identifier, `self`, `super`, `crate`, or `Self`
error 11: expected expression error 11: expected expression
error 11: expected expression error 11: expected expression
error 20: expected identifier error 20: expected identifier, `self`, `super`, `crate`, or `Self`
error 28: expected identifier error 28: expected identifier, `self`, `super`, `crate`, or `Self`
error 30: expected expression error 30: expected expression
error 30: expected expression error 30: expected expression
error 41: expected L_PAREN error 41: expected L_PAREN
error 41: expected identifier error 41: expected identifier, `self`, `super`, `crate`, or `Self`
error 41: expected R_PAREN error 41: expected R_PAREN
error 52: expected L_PAREN error 52: expected L_PAREN
error 52: expected identifier error 52: expected identifier, `self`, `super`, `crate`, or `Self`
error 54: expected expression error 54: expected expression
error 54: expected expression error 54: expected expression
error 54: expected R_PAREN error 54: expected R_PAREN

View file

@ -0,0 +1,28 @@
SOURCE_FILE
TYPE_ALIAS
TYPE_KW "type"
WHITESPACE " "
NAME
IDENT "T"
WHITESPACE " "
EQ "="
WHITESPACE " "
IMPL_TRAIT_TYPE
IMPL_KW "impl"
WHITESPACE " "
TYPE_BOUND_LIST
TYPE_BOUND
USE_KW "use"
USE_BOUND_GENERIC_ARGS
L_ANGLE "<"
ERROR
SELF_KW "self"
COMMA ","
WHITESPACE " "
ERROR
INT_NUMBER "1"
R_ANGLE ">"
SEMICOLON ";"
WHITESPACE "\n"
error 18: expected identifier or `Self`
error 24: expected identifier or `Self`

View file

@ -0,0 +1 @@
type T = impl use<self, 1>;

View file

@ -12,6 +12,38 @@ SOURCE_FILE
STMT_LIST STMT_LIST
L_CURLY "{" L_CURLY "{"
WHITESPACE "\n " WHITESPACE "\n "
EXPR_STMT
RECORD_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
WHITESPACE " "
RECORD_EXPR_FIELD_LIST
L_CURLY "{"
WHITESPACE " "
RECORD_EXPR_FIELD
NAME_REF
IDENT "field"
WHITESPACE " "
DOT2 ".."
CALL_EXPR
PATH_EXPR
PATH
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
COLON2 "::"
PATH_SEGMENT
NAME_REF
IDENT "default"
ARG_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n "
RECORD_EXPR RECORD_EXPR
PATH PATH
PATH_SEGMENT PATH_SEGMENT
@ -23,7 +55,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
RECORD_EXPR_FIELD RECORD_EXPR_FIELD
NAME_REF NAME_REF
IDENT "field" INT_NUMBER "0"
WHITESPACE " " WHITESPACE " "
DOT2 ".." DOT2 ".."
CALL_EXPR CALL_EXPR
@ -47,3 +79,6 @@ SOURCE_FILE
WHITESPACE "\n" WHITESPACE "\n"
error 25: expected `:` error 25: expected `:`
error 25: expected COMMA error 25: expected COMMA
error 42: expected SEMICOLON
error 52: expected `:`
error 52: expected COMMA

View file

@ -1,3 +1,4 @@
fn main() { fn main() {
S { field ..S::default() } S { field ..S::default() }
S { 0 ..S::default() }
} }

View file

@ -12,6 +12,31 @@ SOURCE_FILE
STMT_LIST STMT_LIST
L_CURLY "{" L_CURLY "{"
WHITESPACE "\n " WHITESPACE "\n "
EXPR_STMT
RECORD_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
WHITESPACE " "
RECORD_EXPR_FIELD_LIST
L_CURLY "{"
WHITESPACE " "
RECORD_EXPR_FIELD
NAME_REF
IDENT "field"
WHITESPACE " "
ERROR
EQ "="
WHITESPACE " "
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "foo"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n "
RECORD_EXPR RECORD_EXPR
PATH PATH
PATH_SEGMENT PATH_SEGMENT
@ -23,7 +48,7 @@ SOURCE_FILE
WHITESPACE " " WHITESPACE " "
RECORD_EXPR_FIELD RECORD_EXPR_FIELD
NAME_REF NAME_REF
IDENT "field" INT_NUMBER "0"
WHITESPACE " " WHITESPACE " "
ERROR ERROR
EQ "=" EQ "="
@ -39,3 +64,5 @@ SOURCE_FILE
R_CURLY "}" R_CURLY "}"
WHITESPACE "\n" WHITESPACE "\n"
error 26: expected `:` error 26: expected `:`
error 33: expected SEMICOLON
error 44: expected `:`

View file

@ -1,3 +1,4 @@
fn main() { fn main() {
S { field = foo } S { field = foo }
S { 0 = foo }
} }

View file

@ -12,32 +12,70 @@ SOURCE_FILE
STMT_LIST STMT_LIST
L_CURLY "{" L_CURLY "{"
WHITESPACE "\n " WHITESPACE "\n "
RECORD_EXPR EXPR_STMT
PATH RECORD_EXPR
PATH_SEGMENT PATH
NAME_REF PATH_SEGMENT
IDENT "S" NAME_REF
WHITESPACE " " IDENT "S"
RECORD_EXPR_FIELD_LIST
L_CURLY "{"
WHITESPACE " " WHITESPACE " "
CALL_EXPR RECORD_EXPR_FIELD_LIST
PATH_EXPR L_CURLY "{"
PATH WHITESPACE " "
CALL_EXPR
PATH_EXPR
PATH PATH
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
COLON2 "::"
PATH_SEGMENT PATH_SEGMENT
NAME_REF NAME_REF
IDENT "S" IDENT "default"
COLON2 "::" ARG_LIST
PATH_SEGMENT L_PAREN "("
NAME_REF R_PAREN ")"
IDENT "default" WHITESPACE " "
ARG_LIST R_CURLY "}"
L_PAREN "(" SEMICOLON ";"
R_PAREN ")" WHITESPACE "\n "
EXPR_STMT
RECORD_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
WHITESPACE " " WHITESPACE " "
R_CURLY "}" RECORD_EXPR_FIELD_LIST
L_CURLY "{"
WHITESPACE " "
LITERAL
INT_NUMBER "0"
ERROR
COLON ":"
ERROR
COLON ":"
RECORD_EXPR_FIELD
CALL_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "default"
ARG_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
R_CURLY "}"
SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
R_CURLY "}" R_CURLY "}"
WHITESPACE "\n" WHITESPACE "\n"
error 19: expected DOT2 error 19: expected DOT2
error 43: expected DOT2
error 45: expected COMMA
error 45: expected identifier
error 46: expected COMMA
error 46: expected identifier
error 47: expected COMMA

View file

@ -1,3 +1,4 @@
fn main() { fn main() {
S { S::default() } S { S::default() };
S { 0::default() };
} }

View file

@ -8,3 +8,12 @@ SOURCE_FILE
IDENT "foo" IDENT "foo"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
EXTERN_CRATE
EXTERN_KW "extern"
WHITESPACE " "
CRATE_KW "crate"
WHITESPACE " "
NAME_REF
SELF_KW "self"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +1,2 @@
extern crate foo; extern crate foo;
extern crate self;

View file

@ -14,3 +14,18 @@ SOURCE_FILE
IDENT "bar" IDENT "bar"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n" WHITESPACE "\n"
EXTERN_CRATE
EXTERN_KW "extern"
WHITESPACE " "
CRATE_KW "crate"
WHITESPACE " "
NAME_REF
SELF_KW "self"
WHITESPACE " "
RENAME
AS_KW "as"
WHITESPACE " "
NAME
IDENT "bar"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +1,2 @@
extern crate foo as bar; extern crate foo as bar;
extern crate self as bar;

View file

@ -1,10 +0,0 @@
SOURCE_FILE
EXTERN_CRATE
EXTERN_KW "extern"
WHITESPACE " "
CRATE_KW "crate"
WHITESPACE " "
NAME_REF
SELF_KW "self"
SEMICOLON ";"
WHITESPACE "\n"

View file

@ -1 +0,0 @@
extern crate self;

View file

@ -12,6 +12,30 @@ SOURCE_FILE
STMT_LIST STMT_LIST
L_CURLY "{" L_CURLY "{"
WHITESPACE "\n " WHITESPACE "\n "
EXPR_STMT
FIELD_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "x"
DOT "."
NAME_REF
SELF_KW "self"
SEMICOLON ";"
WHITESPACE "\n "
EXPR_STMT
FIELD_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "x"
DOT "."
NAME_REF
SELF_TYPE_KW "Self"
SEMICOLON ";"
WHITESPACE "\n "
EXPR_STMT EXPR_STMT
FIELD_EXPR FIELD_EXPR
PATH_EXPR PATH_EXPR

View file

@ -1,4 +1,6 @@
fn foo() { fn foo() {
x.self;
x.Self;
x.foo; x.foo;
x.0.bar; x.0.bar;
x.0.1; x.0.1;

View file

@ -101,6 +101,20 @@ SOURCE_FILE
L_PAREN "(" L_PAREN "("
R_PAREN ")" R_PAREN ")"
SEMICOLON ";" SEMICOLON ";"
WHITESPACE "\n "
CALL_EXPR
FIELD_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
IDENT "x"
DOT "."
NAME_REF
INT_NUMBER "0"
ARG_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE "\n" WHITESPACE "\n"
R_CURLY "}" R_CURLY "}"
WHITESPACE "\n" WHITESPACE "\n"

View file

@ -3,4 +3,5 @@ fn foo() {
y.bar::<T>(1, 2,); y.bar::<T>(1, 2,);
x.0.0.call(); x.0.0.call();
x.0. call(); x.0. call();
x.0()
} }