scanner: clean up scanning of `>` (#11943)
parent
bf2569a9a8
commit
52b53f17b2
|
@ -919,56 +919,34 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
return s.new_token(.ge, '', 2)
|
return s.new_token(.ge, '', 2)
|
||||||
} else if nextc == `>` {
|
} else if nextc == `>` {
|
||||||
if s.pos + 2 < s.text.len {
|
if s.pos + 2 < s.text.len {
|
||||||
if s.text[s.pos + 2] == `=` {
|
// an algorithm to decide it's generic or non-generic
|
||||||
s.pos += 2
|
|
||||||
return s.new_token(.right_shift_assign, '', 3)
|
|
||||||
} else if s.last_lt >= 0 && s.pos - s.last_lt < 100 {
|
|
||||||
// an algorithm to discriminate two-level generic call and shift-right patterns
|
|
||||||
// such as `foo<Baz, Bar<int>>(a)` vs `a, b := Foo{}<Foo{}, bar>>(baz)`
|
// such as `foo<Baz, Bar<int>>(a)` vs `a, b := Foo{}<Foo{}, bar>>(baz)`
|
||||||
// @SleepyRoy if you have smarter algorithm :-)
|
// @SleepyRoy if you have smarter algorithm :-)
|
||||||
// almost correct heuristics: 2-level generic call's last <T> cannot be extremely long
|
// almost correct heuristics: last <T> of generic cannot be extremely long
|
||||||
// here we set the limit 100 which should be nice for real cases
|
// here we set the limit 100 which should be nice for real cases
|
||||||
// ...Bar<int, []Foo, [20]f64, map[string][]bool>> =>
|
// e.g. ...Bar<int, []Foo<int>, Baz_, [20]f64, map[string][]bool>> =>
|
||||||
// int, []Foo, [20]f64, map[string][]bool =>
|
// <int, Baz_, [20]f64, map[string][]bool => int, Baz_, f64, bool
|
||||||
// int, Foo, f64, bool
|
mut is_generic := true
|
||||||
|
if s.last_lt >= 0 && s.pos - s.last_lt < 100 {
|
||||||
typs := s.text[s.last_lt + 1..s.pos].split(',').map(it.trim_space().trim_right('>').after(']'))
|
typs := s.text[s.last_lt + 1..s.pos].split(',').map(it.trim_space().trim_right('>').after(']'))
|
||||||
// if any typ is neither Type nor builtin, then the case is shift-right
|
// if any typ is neither Type nor builtin, then the case is non-generic
|
||||||
for typ in typs {
|
for typ in typs {
|
||||||
// TODO: combine two ifs once logic shortcut with `.all()` is fixed
|
if typ.len == 0
|
||||||
if typ.len == 0 {
|
|| (!(typ[0].is_capital() && typ[1..].bytes().all(it.is_alnum()
|
||||||
if s.text[s.pos + 2] == `>` {
|
|| it == `_`)) && typ !in ast.builtin_type_names) {
|
||||||
if s.pos + 3 < s.text.len && s.text[s.pos + 3] == `=` {
|
is_generic = false
|
||||||
s.pos += 3
|
break
|
||||||
return s.new_token(.unsigned_right_shift_assign,
|
|
||||||
'', 4)
|
|
||||||
}
|
|
||||||
s.pos += 2
|
|
||||||
return s.new_token(.unsigned_right_shift, '',
|
|
||||||
3)
|
|
||||||
}
|
|
||||||
s.pos++
|
|
||||||
return s.new_token(.right_shift, '', 2)
|
|
||||||
}
|
|
||||||
if !(typ[0].is_capital() && typ[1..].bytes().all(it.is_alnum()))
|
|
||||||
&& typ !in ast.builtin_type_names {
|
|
||||||
if s.text[s.pos + 2] == `>` {
|
|
||||||
if s.pos + 3 < s.text.len && s.text[s.pos + 3] == `=` {
|
|
||||||
s.pos += 3
|
|
||||||
return s.new_token(.unsigned_right_shift_assign,
|
|
||||||
'', 4)
|
|
||||||
}
|
|
||||||
s.pos += 2
|
|
||||||
return s.new_token(.unsigned_right_shift, '',
|
|
||||||
3)
|
|
||||||
}
|
|
||||||
s.pos++
|
|
||||||
return s.new_token(.right_shift, '', 2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
is_generic = false
|
||||||
|
}
|
||||||
|
if is_generic {
|
||||||
return s.new_token(.gt, '', 1)
|
return s.new_token(.gt, '', 1)
|
||||||
}
|
} else if s.text[s.pos + 2] == `=` {
|
||||||
}
|
s.pos += 2
|
||||||
if s.text[s.pos + 2] == `>` {
|
return s.new_token(.right_shift_assign, '', 3)
|
||||||
|
} else if s.text[s.pos + 2] == `>` {
|
||||||
if s.pos + 3 < s.text.len && s.text[s.pos + 3] == `=` {
|
if s.pos + 3 < s.text.len && s.text[s.pos + 3] == `=` {
|
||||||
s.pos += 3
|
s.pos += 3
|
||||||
return s.new_token(.unsigned_right_shift_assign, '', 4)
|
return s.new_token(.unsigned_right_shift_assign, '', 4)
|
||||||
|
@ -976,6 +954,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.unsigned_right_shift, '', 3)
|
return s.new_token(.unsigned_right_shift, '', 3)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.right_shift, '', 2)
|
return s.new_token(.right_shift, '', 2)
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,9 +510,9 @@ fn test_multi_level_generics() {
|
||||||
two) == 20
|
two) == 20
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Empty {}
|
struct Empty_ {}
|
||||||
|
|
||||||
fn (e1 Empty) < (e2 Empty) bool {
|
fn (e1 Empty_) < (e2 Empty_) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,11 +551,11 @@ fn test_generic_detection() {
|
||||||
res1, res2 := foo < bar, baz >> (foo + 1 - 1)
|
res1, res2 := foo < bar, baz >> (foo + 1 - 1)
|
||||||
assert res1
|
assert res1
|
||||||
assert res2 == 8
|
assert res2 == 8
|
||||||
res3, res4 := Empty{} < Empty{}, baz >> (foo + 1 - 1)
|
res3, res4 := Empty_{} < Empty_{}, baz >> (foo + 1 - 1)
|
||||||
assert res3
|
assert res3
|
||||||
assert res4 == 8
|
assert res4 == 8
|
||||||
assert boring_function<TandU<Empty, int>>(TandU<Empty, int>{
|
assert boring_function<TandU<Empty_, int>>(TandU<Empty_, int>{
|
||||||
t: Empty{}
|
t: Empty_{}
|
||||||
u: 10
|
u: 10
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -573,11 +573,11 @@ fn test_generic_detection() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// this final case challenges your scanner :-)
|
// this final case challenges your scanner :-)
|
||||||
assert boring_function<TandU<TandU<int,MultiLevel<Empty>>, map[string][]int>>(TandU<TandU<int,MultiLevel<Empty>>, map[string][]int>{
|
assert boring_function<TandU<TandU<int,MultiLevel<Empty_>>, map[string][]int>>(TandU<TandU<int,MultiLevel<Empty_>>, map[string][]int>{
|
||||||
t: TandU<int,MultiLevel<Empty>>{
|
t: TandU<int,MultiLevel<Empty_>>{
|
||||||
t: 20
|
t: 20
|
||||||
u: MultiLevel<Empty>{
|
u: MultiLevel<Empty_>{
|
||||||
foo: Empty{}
|
foo: Empty_{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u: {
|
u: {
|
||||||
|
|
Loading…
Reference in New Issue