179 lines
4.6 KiB
Rust
179 lines
4.6 KiB
Rust
//! FIXME: write short doc here
|
|
|
|
use super::*;
|
|
|
|
pub(super) fn strukt(p: &mut Parser, m: Marker) {
|
|
assert!(p.at(T![struct]));
|
|
p.bump(T![struct]);
|
|
struct_or_union(p, m, T![struct], STRUCT);
|
|
}
|
|
|
|
pub(super) fn union(p: &mut Parser, m: Marker) {
|
|
assert!(p.at_contextual_kw("union"));
|
|
p.bump_remap(T![union]);
|
|
struct_or_union(p, m, T![union], UNION);
|
|
}
|
|
|
|
fn struct_or_union(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
|
|
name_r(p, ITEM_RECOVERY_SET);
|
|
type_params::opt_generic_param_list(p);
|
|
match p.current() {
|
|
T![where] => {
|
|
type_params::opt_where_clause(p);
|
|
match p.current() {
|
|
T![;] => {
|
|
p.bump(T![;]);
|
|
}
|
|
T!['{'] => record_field_list(p),
|
|
_ => {
|
|
//FIXME: special case `(` error message
|
|
p.error("expected `;` or `{`");
|
|
}
|
|
}
|
|
}
|
|
T![;] if kw == T![struct] => {
|
|
p.bump(T![;]);
|
|
}
|
|
T!['{'] => record_field_list(p),
|
|
T!['('] if kw == T![struct] => {
|
|
tuple_field_list(p);
|
|
// test tuple_struct_where
|
|
// struct Test<T>(T) where T: Clone;
|
|
// struct Test<T>(T);
|
|
type_params::opt_where_clause(p);
|
|
p.expect(T![;]);
|
|
}
|
|
_ if kw == T![struct] => {
|
|
p.error("expected `;`, `{`, or `(`");
|
|
}
|
|
_ => {
|
|
p.error("expected `{`");
|
|
}
|
|
}
|
|
m.complete(p, def);
|
|
}
|
|
|
|
pub(super) fn enum_(p: &mut Parser, m: Marker) {
|
|
assert!(p.at(T![enum]));
|
|
p.bump(T![enum]);
|
|
name_r(p, ITEM_RECOVERY_SET);
|
|
type_params::opt_generic_param_list(p);
|
|
type_params::opt_where_clause(p);
|
|
if p.at(T!['{']) {
|
|
variant_list(p);
|
|
} else {
|
|
p.error("expected `{`")
|
|
}
|
|
m.complete(p, ENUM);
|
|
}
|
|
|
|
pub(crate) fn variant_list(p: &mut Parser) {
|
|
assert!(p.at(T!['{']));
|
|
let m = p.start();
|
|
p.bump(T!['{']);
|
|
while !p.at(EOF) && !p.at(T!['}']) {
|
|
if p.at(T!['{']) {
|
|
error_block(p, "expected enum variant");
|
|
continue;
|
|
}
|
|
let var = p.start();
|
|
attributes::outer_attrs(p);
|
|
if p.at(IDENT) {
|
|
name(p);
|
|
match p.current() {
|
|
T!['{'] => record_field_list(p),
|
|
T!['('] => tuple_field_list(p),
|
|
_ => (),
|
|
}
|
|
|
|
// test variant_discriminant
|
|
// enum E { X(i32) = 10 }
|
|
if p.eat(T![=]) {
|
|
expressions::expr(p);
|
|
}
|
|
var.complete(p, VARIANT);
|
|
} else {
|
|
var.abandon(p);
|
|
p.err_and_bump("expected enum variant");
|
|
}
|
|
if !p.at(T!['}']) {
|
|
p.expect(T![,]);
|
|
}
|
|
}
|
|
p.expect(T!['}']);
|
|
m.complete(p, VARIANT_LIST);
|
|
}
|
|
|
|
pub(crate) fn record_field_list(p: &mut Parser) {
|
|
assert!(p.at(T!['{']));
|
|
let m = p.start();
|
|
p.bump(T!['{']);
|
|
while !p.at(T!['}']) && !p.at(EOF) {
|
|
if p.at(T!['{']) {
|
|
error_block(p, "expected field");
|
|
continue;
|
|
}
|
|
record_field_def(p);
|
|
if !p.at(T!['}']) {
|
|
p.expect(T![,]);
|
|
}
|
|
}
|
|
p.expect(T!['}']);
|
|
m.complete(p, RECORD_FIELD_LIST);
|
|
|
|
fn record_field_def(p: &mut Parser) {
|
|
let m = p.start();
|
|
// test record_field_attrs
|
|
// struct S {
|
|
// #[serde(with = "url_serde")]
|
|
// pub uri: Uri,
|
|
// }
|
|
attributes::outer_attrs(p);
|
|
opt_visibility(p);
|
|
if p.at(IDENT) {
|
|
name(p);
|
|
p.expect(T![:]);
|
|
types::type_(p);
|
|
m.complete(p, RECORD_FIELD);
|
|
} else {
|
|
m.abandon(p);
|
|
p.err_and_bump("expected field declaration");
|
|
}
|
|
}
|
|
}
|
|
|
|
fn tuple_field_list(p: &mut Parser) {
|
|
assert!(p.at(T!['(']));
|
|
let m = p.start();
|
|
if !p.expect(T!['(']) {
|
|
return;
|
|
}
|
|
while !p.at(T![')']) && !p.at(EOF) {
|
|
let m = p.start();
|
|
// test tuple_field_attrs
|
|
// struct S (
|
|
// #[serde(with = "url_serde")]
|
|
// pub Uri,
|
|
// );
|
|
//
|
|
// enum S {
|
|
// Uri(#[serde(with = "url_serde")] Uri),
|
|
// }
|
|
attributes::outer_attrs(p);
|
|
opt_visibility(p);
|
|
if !p.at_ts(types::TYPE_FIRST) {
|
|
p.error("expected a type");
|
|
m.complete(p, ERROR);
|
|
break;
|
|
}
|
|
types::type_(p);
|
|
m.complete(p, TUPLE_FIELD);
|
|
|
|
if !p.at(T![')']) {
|
|
p.expect(T![,]);
|
|
}
|
|
}
|
|
p.expect(T![')']);
|
|
m.complete(p, TUPLE_FIELD_LIST);
|
|
}
|