@@ -3,8 +3,9 @@ use super::{
3
3
Parser ,
4
4
} ;
5
5
use crate :: {
6
- ast:: { FixedArray , Type , TypeKind } ,
6
+ ast:: { CompileTimeArgument , Type , TypeKind } ,
7
7
inflow:: Inflow ,
8
+ source_files:: Source ,
8
9
token:: { Token , TokenKind } ,
9
10
} ;
10
11
@@ -28,6 +29,48 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
28
29
} ) ;
29
30
} ;
30
31
32
+ let generics = self . parse_generics ( ) ?;
33
+ self . parse_type_from_parts ( identifier, generics, source)
34
+ }
35
+
36
+ pub fn parse_generics ( & mut self ) -> Result < Vec < CompileTimeArgument > , ParseError > {
37
+ let mut generics = vec ! [ ] ;
38
+
39
+ if !self . input . eat ( TokenKind :: OpenAngle ) {
40
+ return Ok ( generics) ;
41
+ }
42
+
43
+ loop {
44
+ if self . parse_type_parameters_close ( ) . is_some ( ) {
45
+ break ;
46
+ } else if self . input . peek_is ( TokenKind :: EndOfFile ) {
47
+ // TODO: Improve error message
48
+ return Err ( self . unexpected_token_is_next ( ) ) ;
49
+ }
50
+
51
+ if !generics. is_empty ( ) && !self . input . eat ( TokenKind :: Comma ) {
52
+ // TODO: Improve error message
53
+ return Err ( self . unexpected_token_is_next ( ) ) ;
54
+ }
55
+
56
+ generics. push ( if self . input . peek ( ) . could_start_type ( ) {
57
+ CompileTimeArgument :: Type (
58
+ self . parse_type ( None :: < & str > , Some ( "for compile time argument" ) ) ?,
59
+ )
60
+ } else {
61
+ CompileTimeArgument :: Expr ( self . parse_expr ( ) ?)
62
+ } ) ;
63
+ }
64
+
65
+ Ok ( generics)
66
+ }
67
+
68
+ pub fn parse_type_from_parts (
69
+ & mut self ,
70
+ identifier : String ,
71
+ generics : Vec < CompileTimeArgument > ,
72
+ source : Source ,
73
+ ) -> Result < Type , ParseError > {
31
74
let type_kind = match identifier. as_str ( ) {
32
75
"bool" => Ok ( TypeKind :: Boolean ) ,
33
76
"char" => Ok ( TypeKind :: char ( ) ) ,
@@ -52,39 +95,38 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
52
95
"f32" | "float" => Ok ( TypeKind :: f32 ( ) ) ,
53
96
"f64" | "double" => Ok ( TypeKind :: f64 ( ) ) ,
54
97
"void" => Ok ( TypeKind :: Void ) ,
55
- "ptr" => Ok ( TypeKind :: Pointer ( Box :: new (
56
- if self . input . eat ( TokenKind :: OpenAngle ) {
57
- let inner = self . parse_type ( None :: < & str > , None :: < & str > ) ?;
58
- self . parse_type_parameters_close ( ) ?;
59
- inner
98
+ "ptr" => {
99
+ if generics. len ( ) == 1 {
100
+ if let CompileTimeArgument :: Type ( inner) = generics. into_iter ( ) . next ( ) . unwrap ( ) {
101
+ Ok ( TypeKind :: Pointer ( Box :: new ( inner) ) )
102
+ } else {
103
+ Err ( ParseError {
104
+ kind : ParseErrorKind :: ExpectedTypeParameterToBeType {
105
+ name : identifier,
106
+ word_for_nth : "first" . into ( ) ,
107
+ } ,
108
+ source,
109
+ } )
110
+ }
60
111
} else {
61
- TypeKind :: Void . at ( source)
62
- } ,
63
- ) ) ) ,
64
- "array" => {
65
- if !self . input . eat ( TokenKind :: OpenAngle ) {
66
- return Err ( ParseError {
67
- kind : ParseErrorKind :: ExpectedTypeParameters ,
112
+ Err ( ParseError {
113
+ kind : ParseErrorKind :: IncorrectNumberOfTypeParametersFor {
114
+ name : identifier,
115
+ expected : 1 ,
116
+ got : generics. len ( ) ,
117
+ } ,
68
118
source,
69
- } ) ;
70
- }
71
-
72
- let count = self . parse_expr ( ) ?;
73
-
74
- if !self . input . eat ( TokenKind :: Comma ) {
75
- return Err ( ParseError {
76
- kind : ParseErrorKind :: ExpectedCommaInTypeParameters ,
77
- source : self . source_here ( ) ,
78
- } ) ;
119
+ } )
79
120
}
121
+ }
122
+ "array" => {
123
+ // TODO: Update fixed array type to use compile time arguments
124
+ todo ! ( "array<$N, $T> not updated yet to use compile time arguments" ) ;
80
125
81
- let inner = self . parse_type ( None :: < & str > , None :: < & str > ) ?;
82
- self . parse_type_parameters_close ( ) ?;
83
-
84
- Ok ( TypeKind :: FixedArray ( Box :: new ( FixedArray {
85
- ast_type : inner,
86
- count,
87
- } ) ) )
126
+ // Ok(TypeKind::FixedArray(Box::new(FixedArray {
127
+ // ast_type: inner,
128
+ // count,
129
+ // })))
88
130
}
89
131
identifier => Ok ( TypeKind :: Named ( identifier. into ( ) ) ) ,
90
132
} ?;
@@ -96,14 +138,15 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
96
138
/// This function may partially consume tokens, so be
97
139
/// aware that any previously peeked tokens may no longer be in
98
140
/// the same lookahead position after calling this function.
99
- fn parse_type_parameters_close ( & mut self ) -> Result < ( ) , ParseError > {
100
- let closer = self . input . advance ( ) ;
141
+ fn parse_type_parameters_close ( & mut self ) -> Option < ( ) > {
142
+ let closer = self . input . peek ( ) ;
143
+ let source = closer. source ;
101
144
102
145
/// Sub-function for properly handling trailing `=` signs
103
146
/// resulting from partially consuming '>'-like tokens.
104
147
fn merge_trailing_equals < I : Inflow < Token > > (
105
148
parser : & mut Parser < I > ,
106
- closer : & Token ,
149
+ closer : Token ,
107
150
column_offset : u32 ,
108
151
) {
109
152
if parser. input . eat ( TokenKind :: Assign ) {
@@ -118,36 +161,42 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
118
161
}
119
162
120
163
match & closer. kind {
121
- TokenKind :: GreaterThan => Ok ( ( ) ) ,
164
+ TokenKind :: GreaterThan => {
165
+ self . input . advance ( ) ;
166
+ Some ( ( ) )
167
+ }
122
168
TokenKind :: RightShift => {
169
+ self . input . advance ( ) ;
123
170
self . input
124
- . unadvance ( TokenKind :: GreaterThan . at ( closer . source . shift_column ( 1 ) ) ) ;
125
- Ok ( ( ) )
171
+ . unadvance ( TokenKind :: GreaterThan . at ( source. shift_column ( 1 ) ) ) ;
172
+ Some ( ( ) )
126
173
}
127
174
TokenKind :: LogicalRightShift => {
175
+ self . input . advance ( ) ;
128
176
self . input
129
- . unadvance ( TokenKind :: RightShift . at ( closer . source . shift_column ( 1 ) ) ) ;
130
- Ok ( ( ) )
177
+ . unadvance ( TokenKind :: RightShift . at ( source. shift_column ( 1 ) ) ) ;
178
+ Some ( ( ) )
131
179
}
132
180
TokenKind :: RightShiftAssign => {
133
- merge_trailing_equals ( self , & closer, 2 ) ;
134
-
181
+ let closer = self . input . advance ( ) ;
182
+ merge_trailing_equals ( self , closer , 2 ) ;
135
183
self . input
136
- . unadvance ( TokenKind :: GreaterThan . at ( closer . source . shift_column ( 1 ) ) ) ;
137
- Ok ( ( ) )
184
+ . unadvance ( TokenKind :: GreaterThan . at ( source. shift_column ( 1 ) ) ) ;
185
+ Some ( ( ) )
138
186
}
139
187
TokenKind :: LogicalRightShiftAssign => {
140
- merge_trailing_equals ( self , & closer, 3 ) ;
141
-
188
+ let closer = self . input . advance ( ) ;
189
+ merge_trailing_equals ( self , closer , 3 ) ;
142
190
self . input
143
- . unadvance ( TokenKind :: RightShift . at ( closer . source . shift_column ( 1 ) ) ) ;
144
- Ok ( ( ) )
191
+ . unadvance ( TokenKind :: RightShift . at ( source. shift_column ( 1 ) ) ) ;
192
+ Some ( ( ) )
145
193
}
146
194
TokenKind :: GreaterThanEq => {
147
- merge_trailing_equals ( self , & closer, 1 ) ;
148
- Ok ( ( ) )
195
+ let closer = self . input . advance ( ) ;
196
+ merge_trailing_equals ( self , closer, 1 ) ;
197
+ Some ( ( ) )
149
198
}
150
- _ => Err ( self . unexpected_token ( & closer ) ) ,
199
+ _ => None ,
151
200
}
152
201
}
153
202
}
0 commit comments