@@ -2159,6 +2159,32 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
2159
2159
}
2160
2160
}
2161
2161
2162
+ fn (p &Parser) is_generic_struct_init () bool {
2163
+ lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0 ].is_capital ()
2164
+ if ! lit0_ is_capital || p.peek_tok.kind ! in [.lt, .lsbr] {
2165
+ return false
2166
+ }
2167
+ if p.peek_tok.kind == .lt {
2168
+ return true
2169
+ } else {
2170
+ mut i := 2
2171
+ for {
2172
+ cur_tok := p.peek_token (i)
2173
+ if cur_tok.kind == .eof || cur_tok.kind ! in [.amp, .dot, .comma, .name, .lsbr, .rsbr] {
2174
+ break
2175
+ }
2176
+ if cur_tok.kind == .rsbr {
2177
+ if p.peek_token (i + 1 ).kind == .lcbr {
2178
+ return true
2179
+ }
2180
+ break
2181
+ }
2182
+ i++
2183
+ }
2184
+ }
2185
+ return false
2186
+ }
2187
+
2162
2188
fn (p &Parser) is_typename (t token.Token) bool {
2163
2189
return t.kind == .name && (t.lit[0 ].is_capital () || p.table.known_type (t.lit))
2164
2190
}
@@ -2177,7 +2203,7 @@ fn (p &Parser) is_typename(t token.Token) bool {
2177
2203
// see also test_generic_detection in vlib/v/tests/generics_test.v
2178
2204
fn (p &Parser) is_generic_call () bool {
2179
2205
lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0 ].is_capital ()
2180
- if lit0_ is_capital || p.peek_tok.kind != .lt {
2206
+ if lit0_ is_capital || p.peek_tok.kind ! in [ .lt, .lsbr] {
2181
2207
return false
2182
2208
}
2183
2209
mut tok2 := p.peek_token (2 )
@@ -2206,13 +2232,31 @@ fn (p &Parser) is_generic_call() bool {
2206
2232
// case 2
2207
2233
return true
2208
2234
}
2209
- return match kind3 {
2210
- .gt { true } // case 3
2211
- .lt { ! (tok4 .lit.len == 1 && tok4 .lit[0 ].is_capital ()) } // case 4
2212
- .comma { p.is_typename (tok2 ) } // case 5
2213
- // case 6 and 7
2214
- .dot { kind4 == .name && (kind5 == .gt || (kind5 == .comma && p.is_typename (tok4 ))) }
2215
- else { false }
2235
+ if p.peek_tok.kind == .lt {
2236
+ return match kind3 {
2237
+ .gt { true } // case 3
2238
+ .lt { ! (tok4 .lit.len == 1 && tok4 .lit[0 ].is_capital ()) } // case 4
2239
+ .comma { p.is_typename (tok2 ) } // case 5
2240
+ // case 6 and 7
2241
+ .dot { kind4 == .name && (kind5 == .gt || (kind5 == .comma && p.is_typename (tok4 ))) }
2242
+ else { false }
2243
+ }
2244
+ } else if p.peek_tok.kind == .lsbr {
2245
+ mut i := 3
2246
+ for {
2247
+ cur_tok := p.peek_token (i)
2248
+ if cur_tok.kind == .eof
2249
+ || cur_tok.kind ! in [.amp, .dot, .comma, .name, .lsbr, .rsbr] {
2250
+ break
2251
+ }
2252
+ if cur_tok.kind == .rsbr {
2253
+ if p.peek_token (i + 1 ).kind == .lpar {
2254
+ return true
2255
+ }
2256
+ break
2257
+ }
2258
+ i++
2259
+ }
2216
2260
}
2217
2261
}
2218
2262
return false
@@ -2231,10 +2275,10 @@ fn (mut p Parser) is_generic_cast() bool {
2231
2275
i++
2232
2276
tok := p.peek_token (i)
2233
2277
2234
- if tok.kind == .lt {
2278
+ if tok.kind in [ .lt, .lsbr] {
2235
2279
lt_count++
2236
2280
level++
2237
- } else if tok.kind == .gt {
2281
+ } else if tok.kind in [ .gt, .rsbr] {
2238
2282
level--
2239
2283
}
2240
2284
if lt_count > 0 && level == 0 {
@@ -2414,6 +2458,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
2414
2458
is_optional := p.tok.kind == .question
2415
2459
is_generic_call := p.is_generic_call ()
2416
2460
is_generic_cast := p.is_generic_cast ()
2461
+ is_generic_struct_init := p.is_generic_struct_init ()
2417
2462
// p.warn('name expr $p.tok.lit $p.peek_tok.str()')
2418
2463
same_line := p.tok.line_nr == p.peek_tok.line_nr
2419
2464
// `(` must be on same line as name token otherwise it's a ParExpr
@@ -2494,7 +2539,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
2494
2539
}
2495
2540
}
2496
2541
}
2497
- } else if (p.peek_tok.kind == .lcbr || (p.peek_tok. kind == .lt && lit 0_ is_capital) )
2542
+ } else if (p.peek_tok.kind == .lcbr || is_generic_struct_init )
2498
2543
&& (! p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_ is_capital))
2499
2544
&& ! p.inside_match_case && (! p.inside_if || p.inside_select)
2500
2545
&& (! p.inside_for || p.inside_select) && ! known_var {
@@ -2975,13 +3020,14 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
2975
3020
fn (mut p Parser) parse_generic_types () ([]ast.Type, []string ) {
2976
3021
mut types := []ast.Type{}
2977
3022
mut param_names := []string {}
2978
- if p.tok.kind != .lt {
3023
+ if p.tok.kind ! in [ .lt, .lsbr] {
2979
3024
return types, param_names
2980
3025
}
2981
- p.check (.lt)
3026
+ end_kind := if p.tok.kind == .lt { token.Kind.gt } else { token.Kind.rsbr }
3027
+ p.next ()
2982
3028
mut first_done := false
2983
3029
mut count := 0
2984
- for p.tok.kind ! in [.gt , .eof] {
3030
+ for p.tok.kind ! in [end_kind , .eof] {
2985
3031
if first_done {
2986
3032
p.check (.comma)
2987
3033
}
@@ -3018,25 +3064,26 @@ fn (mut p Parser) parse_generic_types() ([]ast.Type, []string) {
3018
3064
first_done = true
3019
3065
count++
3020
3066
}
3021
- p.check (.gt )
3067
+ p.check (end_kind )
3022
3068
return types, param_names
3023
3069
}
3024
3070
3025
3071
fn (mut p Parser) parse_concrete_types () []ast.Type {
3026
3072
mut types := []ast.Type{}
3027
- if p.tok.kind != .lt {
3073
+ if p.tok.kind ! in [ .lt, .lsbr] {
3028
3074
return types
3029
3075
}
3076
+ end_kind := if p.tok.kind == .lt { token.Kind.gt } else { token.Kind.rsbr }
3030
3077
p.next () // `<`
3031
3078
mut first_done := false
3032
- for p.tok.kind ! in [.eof, .gt ] {
3079
+ for p.tok.kind ! in [.eof, end_kind ] {
3033
3080
if first_done {
3034
3081
p.check (.comma)
3035
3082
}
3036
3083
types << p.parse_type ()
3037
3084
first_done = true
3038
3085
}
3039
- p.check (.gt ) // `>`
3086
+ p.check (end_kind ) // `>`
3040
3087
return types
3041
3088
}
3042
3089
0 commit comments