2018-01-28 17:46:30 +03:00
|
|
|
use super::*;
|
|
|
|
|
|
2018-08-13 18:34:02 +03:00
|
|
|
pub(super) fn struct_def(p: &mut Parser) {
|
2018-01-28 17:46:30 +03:00
|
|
|
assert!(p.at(STRUCT_KW));
|
|
|
|
|
p.bump();
|
|
|
|
|
|
2018-02-10 14:10:02 +03:00
|
|
|
name(p);
|
2018-07-31 23:16:07 +03:00
|
|
|
type_params::type_param_list(p);
|
2018-01-28 17:46:30 +03:00
|
|
|
match p.current() {
|
|
|
|
|
WHERE_KW => {
|
2018-02-02 23:23:39 +03:00
|
|
|
type_params::where_clause(p);
|
2018-01-28 17:46:30 +03:00
|
|
|
match p.current() {
|
|
|
|
|
SEMI => {
|
|
|
|
|
p.bump();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
L_CURLY => named_fields(p),
|
|
|
|
|
_ => {
|
|
|
|
|
//TODO: special case `(` error message
|
2018-02-09 22:44:50 +03:00
|
|
|
p.error("expected `;` or `{`");
|
2018-01-28 17:46:30 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SEMI => {
|
|
|
|
|
p.bump();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
L_CURLY => named_fields(p),
|
|
|
|
|
L_PAREN => {
|
|
|
|
|
pos_fields(p);
|
|
|
|
|
p.expect(SEMI);
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
2018-02-09 22:44:50 +03:00
|
|
|
p.error("expected `;`, `{`, or `(`");
|
2018-01-28 17:46:30 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-13 18:34:02 +03:00
|
|
|
pub(super) fn enum_def(p: &mut Parser) {
|
2018-01-28 22:59:18 +03:00
|
|
|
assert!(p.at(ENUM_KW));
|
|
|
|
|
p.bump();
|
2018-02-10 14:10:50 +03:00
|
|
|
name(p);
|
2018-07-31 23:16:07 +03:00
|
|
|
type_params::type_param_list(p);
|
2018-02-02 23:23:39 +03:00
|
|
|
type_params::where_clause(p);
|
2018-01-28 22:59:18 +03:00
|
|
|
if p.expect(L_CURLY) {
|
|
|
|
|
while !p.at(EOF) && !p.at(R_CURLY) {
|
|
|
|
|
let var = p.start();
|
|
|
|
|
attributes::outer_attributes(p);
|
|
|
|
|
if p.at(IDENT) {
|
2018-08-01 10:44:23 +03:00
|
|
|
name(p);
|
2018-01-28 22:59:18 +03:00
|
|
|
match p.current() {
|
|
|
|
|
L_CURLY => named_fields(p),
|
|
|
|
|
L_PAREN => pos_fields(p),
|
|
|
|
|
EQ => {
|
|
|
|
|
p.bump();
|
|
|
|
|
expressions::expr(p);
|
|
|
|
|
}
|
2018-01-28 23:14:00 +03:00
|
|
|
_ => (),
|
2018-01-28 22:59:18 +03:00
|
|
|
}
|
|
|
|
|
var.complete(p, ENUM_VARIANT);
|
|
|
|
|
} else {
|
|
|
|
|
var.abandon(p);
|
|
|
|
|
p.err_and_bump("expected enum variant");
|
|
|
|
|
}
|
|
|
|
|
if !p.at(R_CURLY) {
|
|
|
|
|
p.expect(COMMA);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.expect(R_CURLY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-28 17:46:30 +03:00
|
|
|
fn named_fields(p: &mut Parser) {
|
|
|
|
|
assert!(p.at(L_CURLY));
|
|
|
|
|
p.bump();
|
|
|
|
|
while !p.at(R_CURLY) && !p.at(EOF) {
|
|
|
|
|
named_field(p);
|
|
|
|
|
if !p.at(R_CURLY) {
|
|
|
|
|
p.expect(COMMA);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.expect(R_CURLY);
|
|
|
|
|
|
|
|
|
|
fn named_field(p: &mut Parser) {
|
|
|
|
|
let field = p.start();
|
|
|
|
|
visibility(p);
|
2018-02-10 14:13:30 +03:00
|
|
|
if p.at(IDENT) {
|
|
|
|
|
name(p);
|
2018-01-28 17:46:30 +03:00
|
|
|
p.expect(COLON);
|
2018-02-11 11:01:00 +03:00
|
|
|
types::type_(p);
|
2018-01-28 17:46:30 +03:00
|
|
|
field.complete(p, NAMED_FIELD);
|
|
|
|
|
} else {
|
|
|
|
|
field.abandon(p);
|
|
|
|
|
p.err_and_bump("expected field declaration");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pos_fields(p: &mut Parser) {
|
|
|
|
|
if !p.expect(L_PAREN) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
while !p.at(R_PAREN) && !p.at(EOF) {
|
|
|
|
|
let pos_field = p.start();
|
|
|
|
|
visibility(p);
|
2018-02-11 11:01:00 +03:00
|
|
|
types::type_(p);
|
2018-01-28 17:46:30 +03:00
|
|
|
pos_field.complete(p, POS_FIELD);
|
|
|
|
|
|
|
|
|
|
if !p.at(R_PAREN) {
|
|
|
|
|
p.expect(COMMA);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p.expect(R_PAREN);
|
|
|
|
|
}
|