Skip to content

Commit ab81e4c

Browse files
committed
Merge #29
29: Structs r=matklad a=matklad r? @CAD97
2 parents 08def60 + b9cbbfa commit ab81e4c

File tree

8 files changed

+415
-74
lines changed

8 files changed

+415
-74
lines changed

grammar.ron

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,8 @@ Grammar(
8888
"LITERAL",
8989
"ALIAS",
9090
"VISIBILITY",
91+
"TYPE_PARAM_LIST",
92+
"LIFETIME_PARAM",
93+
"TYPE_PARAM",
9194
]
92-
)
95+
)

src/parser/event_parser/grammar/items.rs renamed to src/parser/event_parser/grammar/items/mod.rs

Lines changed: 35 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::*;
22

3+
mod structs;
4+
35
pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
46
attributes::inner_attributes(p);
57
while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
@@ -29,7 +31,7 @@ fn item(p: &mut Parser) {
2931
USE_ITEM
3032
}
3133
STRUCT_KW => {
32-
struct_item(p);
34+
structs::struct_item(p);
3335
STRUCT_ITEM
3436
}
3537
FN_KW => {
@@ -57,90 +59,50 @@ fn item(p: &mut Parser) {
5759
item.complete(p, item_kind);
5860
}
5961

60-
fn struct_item(p: &mut Parser) {
61-
assert!(p.at(STRUCT_KW));
62-
p.bump();
63-
64-
if !p.expect(IDENT) {
62+
fn type_param_list(p: &mut Parser) {
63+
if !p.at(L_ANGLE) {
6564
return;
6665
}
67-
generic_parameters(p);
68-
match p.current() {
69-
WHERE_KW => {
70-
where_clause(p);
71-
match p.current() {
72-
SEMI => {
73-
p.bump();
74-
return;
75-
}
76-
L_CURLY => named_fields(p),
77-
_ => {
78-
//TODO: special case `(` error message
79-
p.error().message("expected `;` or `{`").emit();
80-
return;
81-
}
82-
}
83-
}
84-
SEMI => {
85-
p.bump();
86-
return;
87-
}
88-
L_CURLY => named_fields(p),
89-
L_PAREN => {
90-
pos_fields(p);
91-
p.expect(SEMI);
92-
}
93-
_ => {
94-
p.error().message("expected `;`, `{`, or `(`").emit();
95-
return;
96-
}
97-
}
98-
}
99-
100-
fn named_fields(p: &mut Parser) {
101-
assert!(p.at(L_CURLY));
66+
let m = p.start();
10267
p.bump();
103-
while !p.at(R_CURLY) && !p.at(EOF) {
104-
named_field(p);
105-
if !p.at(R_CURLY) {
106-
p.expect(COMMA);
107-
}
108-
}
109-
p.expect(R_CURLY);
11068

111-
fn named_field(p: &mut Parser) {
112-
let field = p.start();
113-
visibility(p);
114-
if p.expect(IDENT) {
115-
p.expect(COLON);
116-
types::type_ref(p);
117-
field.complete(p, NAMED_FIELD);
118-
} else {
119-
field.abandon(p);
120-
p.err_and_bump("expected field declaration");
69+
while !p.at(EOF) && !p.at(R_ANGLE) {
70+
match p.current() {
71+
LIFETIME => lifetime_param(p),
72+
IDENT => type_param(p),
73+
_ => p.err_and_bump("expected type parameter"),
74+
}
75+
if !p.at(R_ANGLE) && !p.expect(COMMA) {
76+
break;
12177
}
12278
}
123-
}
79+
p.expect(R_ANGLE);
80+
m.complete(p, TYPE_PARAM_LIST);
12481

125-
fn pos_fields(p: &mut Parser) {
126-
if !p.expect(L_PAREN) {
127-
return;
82+
fn lifetime_param(p: &mut Parser) {
83+
assert!(p.at(LIFETIME));
84+
let m = p.start();
85+
p.bump();
86+
if p.eat(COLON) {
87+
while p.at(LIFETIME) {
88+
p.bump();
89+
if !p.eat(PLUS) {
90+
break;
91+
}
92+
}
93+
}
94+
m.complete(p, LIFETIME_PARAM);
12895
}
129-
while !p.at(R_PAREN) && !p.at(EOF) {
130-
let pos_field = p.start();
131-
visibility(p);
132-
types::type_ref(p);
133-
pos_field.complete(p, POS_FIELD);
13496

135-
if !p.at(R_PAREN) {
136-
p.expect(COMMA);
137-
}
97+
fn type_param(p: &mut Parser) {
98+
assert!(p.at(IDENT));
99+
let m = p.start();
100+
p.bump();
101+
m.complete(p, TYPE_PARAM);
102+
//TODO: bounds
138103
}
139-
p.expect(R_PAREN);
140104
}
141105

142-
fn generic_parameters(_: &mut Parser) {}
143-
144106
fn where_clause(_: &mut Parser) {}
145107

146108
fn extern_crate_item(p: &mut Parser) {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use super::*;
2+
3+
pub(super) fn struct_item(p: &mut Parser) {
4+
assert!(p.at(STRUCT_KW));
5+
p.bump();
6+
7+
if !p.expect(IDENT) {
8+
return;
9+
}
10+
type_param_list(p);
11+
match p.current() {
12+
WHERE_KW => {
13+
where_clause(p);
14+
match p.current() {
15+
SEMI => {
16+
p.bump();
17+
return;
18+
}
19+
L_CURLY => named_fields(p),
20+
_ => {
21+
//TODO: special case `(` error message
22+
p.error().message("expected `;` or `{`").emit();
23+
return;
24+
}
25+
}
26+
}
27+
SEMI => {
28+
p.bump();
29+
return;
30+
}
31+
L_CURLY => named_fields(p),
32+
L_PAREN => {
33+
pos_fields(p);
34+
p.expect(SEMI);
35+
}
36+
_ => {
37+
p.error().message("expected `;`, `{`, or `(`").emit();
38+
return;
39+
}
40+
}
41+
}
42+
43+
fn named_fields(p: &mut Parser) {
44+
assert!(p.at(L_CURLY));
45+
p.bump();
46+
while !p.at(R_CURLY) && !p.at(EOF) {
47+
named_field(p);
48+
if !p.at(R_CURLY) {
49+
p.expect(COMMA);
50+
}
51+
}
52+
p.expect(R_CURLY);
53+
54+
fn named_field(p: &mut Parser) {
55+
let field = p.start();
56+
visibility(p);
57+
if p.expect(IDENT) {
58+
p.expect(COLON);
59+
types::type_ref(p);
60+
field.complete(p, NAMED_FIELD);
61+
} else {
62+
field.abandon(p);
63+
p.err_and_bump("expected field declaration");
64+
}
65+
}
66+
}
67+
68+
fn pos_fields(p: &mut Parser) {
69+
if !p.expect(L_PAREN) {
70+
return;
71+
}
72+
while !p.at(R_PAREN) && !p.at(EOF) {
73+
let pos_field = p.start();
74+
visibility(p);
75+
types::type_ref(p);
76+
pos_field.complete(p, POS_FIELD);
77+
78+
if !p.at(R_PAREN) {
79+
p.expect(COMMA);
80+
}
81+
}
82+
p.expect(R_PAREN);
83+
}

src/syntax_kinds.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ pub enum SyntaxKind {
9090
LITERAL,
9191
ALIAS,
9292
VISIBILITY,
93+
TYPE_PARAM_LIST,
94+
LIFETIME_PARAM,
95+
TYPE_PARAM,
9396

9497
// Technical SyntaxKinds: they appear temporally during parsing,
9598
// but never end up in the final tree
@@ -187,6 +190,9 @@ impl SyntaxKind {
187190
LITERAL => &SyntaxInfo { name: "LITERAL" },
188191
ALIAS => &SyntaxInfo { name: "ALIAS" },
189192
VISIBILITY => &SyntaxInfo { name: "VISIBILITY" },
193+
TYPE_PARAM_LIST => &SyntaxInfo { name: "TYPE_PARAM_LIST" },
194+
LIFETIME_PARAM => &SyntaxInfo { name: "LIFETIME_PARAM" },
195+
TYPE_PARAM => &SyntaxInfo { name: "TYPE_PARAM" },
190196

191197
TOMBSTONE => &SyntaxInfo { name: "TOMBSTONE" },
192198
EOF => &SyntaxInfo { name: "EOF" },
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
struct S<90 + 2> {
2+
f: u32
3+
}
4+
5+
struct T;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
FILE@[0; 43)
2+
STRUCT_ITEM@[0; 12)
3+
STRUCT_KW@[0; 6)
4+
WHITESPACE@[6; 7)
5+
IDENT@[7; 8)
6+
TYPE_PARAM_LIST@[8; 12)
7+
L_ANGLE@[8; 9)
8+
ERROR@[9; 12)
9+
err: `expected type parameter`
10+
INT_NUMBER@[9; 11)
11+
WHITESPACE@[11; 12)
12+
err: `expected COMMA`
13+
err: `expected R_ANGLE`
14+
err: `expected `;`, `{`, or `(``
15+
ERROR@[12; 14)
16+
err: `expected item`
17+
PLUS@[12; 13)
18+
WHITESPACE@[13; 14)
19+
ERROR@[14; 15)
20+
err: `expected item`
21+
INT_NUMBER@[14; 15)
22+
ERROR@[15; 17)
23+
err: `expected item`
24+
R_ANGLE@[15; 16)
25+
WHITESPACE@[16; 17)
26+
ERROR@[17; 33)
27+
err: `expected item`
28+
L_CURLY@[17; 18)
29+
WHITESPACE@[18; 23)
30+
IDENT@[23; 24)
31+
COLON@[24; 25)
32+
WHITESPACE@[25; 26)
33+
IDENT@[26; 29)
34+
WHITESPACE@[29; 30)
35+
R_CURLY@[30; 31)
36+
WHITESPACE@[31; 33)
37+
STRUCT_ITEM@[33; 43)
38+
STRUCT_KW@[33; 39)
39+
WHITESPACE@[39; 40)
40+
IDENT@[40; 41)
41+
SEMI@[41; 42)
42+
WHITESPACE@[42; 43)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct S1<T>;
2+
struct S2<T>(u32);
3+
struct S3<T> { u: u32 }
4+
5+
struct S4<>;
6+
struct S5<'a>;
7+
struct S6<'a:>;
8+
struct S7<'a: 'b>;
9+
struct S8<'a: 'b + >;
10+
struct S9<'a: 'b + 'c>;
11+
struct S10<'a,>;
12+
struct S11<'a, 'b>;
13+
struct S12<'a: 'b+, 'b: 'c,>;
14+
15+
struct S13<T>;
16+
struct S14<T, U>;
17+
struct S15<'a, T, U>;

0 commit comments

Comments
 (0)