parser: parse `map{key_expr: val_expr}` (#8608)
parent
db0fc8fbc9
commit
f5f65f929f
|
@ -128,13 +128,17 @@ fn test_map() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_map_init() {
|
fn test_map_init() {
|
||||||
m := {
|
one := 'one'
|
||||||
'one': 1
|
three := 'three'
|
||||||
|
m := map{
|
||||||
|
one: 1
|
||||||
'two': 2
|
'two': 2
|
||||||
|
three: 1 + 2
|
||||||
}
|
}
|
||||||
assert m['one'] == 1
|
assert m['one'] == 1
|
||||||
assert m['two'] == 2
|
assert m['two'] == 2
|
||||||
assert m['three'] == 0
|
assert m['three'] == 3
|
||||||
|
assert m['unknown'] == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_string_map() {
|
fn test_string_map() {
|
||||||
|
|
|
@ -5335,16 +5335,20 @@ pub fn (mut c Checker) check_dup_keys(node &ast.MapInit, i int) {
|
||||||
key_i := node.keys[i]
|
key_i := node.keys[i]
|
||||||
if key_i is ast.StringLiteral {
|
if key_i is ast.StringLiteral {
|
||||||
for j in 0 .. i {
|
for j in 0 .. i {
|
||||||
key_j := node.keys[j] as ast.StringLiteral
|
key_j := node.keys[j]
|
||||||
if key_i.val == key_j.val {
|
if key_j is ast.StringLiteral {
|
||||||
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
if key_i.val == key_j.val {
|
||||||
|
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if key_i is ast.IntegerLiteral {
|
} else if key_i is ast.IntegerLiteral {
|
||||||
for j in 0 .. i {
|
for j in 0 .. i {
|
||||||
key_j := node.keys[j] as ast.IntegerLiteral
|
key_j := node.keys[j]
|
||||||
if key_i.val == key_j.val {
|
if key_j is ast.IntegerLiteral {
|
||||||
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
if key_i.val == key_j.val {
|
||||||
|
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse tokens between braces
|
||||||
fn (mut p Parser) map_init() ast.MapInit {
|
fn (mut p Parser) map_init() ast.MapInit {
|
||||||
first_pos := p.prev_tok.position()
|
first_pos := p.prev_tok.position()
|
||||||
mut keys := []ast.Expr{}
|
mut keys := []ast.Expr{}
|
||||||
|
|
|
@ -128,7 +128,13 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
|
||||||
p.next()
|
p.next()
|
||||||
array_decompose = true
|
array_decompose = true
|
||||||
}
|
}
|
||||||
mut e := p.expr(0)
|
mut e := ast.Expr{}
|
||||||
|
if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
||||||
|
// `foo(key:val, key2:val2)`
|
||||||
|
e = p.struct_init(true) // short_syntax:true
|
||||||
|
} else {
|
||||||
|
e = p.expr(0)
|
||||||
|
}
|
||||||
if array_decompose {
|
if array_decompose {
|
||||||
e = ast.ArrayDecompose{
|
e = ast.ArrayDecompose{
|
||||||
expr: e
|
expr: e
|
||||||
|
|
|
@ -1314,6 +1314,16 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
|
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
|
||||||
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
|
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
|
||||||
&& (!p.inside_for || p.inside_select) { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
&& (!p.inside_for || p.inside_select) { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
|
||||||
|
// map.v has struct literal: map{field: expr}
|
||||||
|
if p.peek_tok.kind == .lcbr && !(p.builtin_mod && p.file_base == 'map.v')
|
||||||
|
&& p.tok.lit == 'map' {
|
||||||
|
// map{key_expr: val_expr}
|
||||||
|
p.check(.name)
|
||||||
|
p.check(.lcbr)
|
||||||
|
map_init := p.map_init()
|
||||||
|
p.check(.rcbr)
|
||||||
|
return map_init
|
||||||
|
}
|
||||||
return p.struct_init(false) // short_syntax: false
|
return p.struct_init(false) // short_syntax: false
|
||||||
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||||
// T.name
|
// T.name
|
||||||
|
@ -1351,11 +1361,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
mod: mod
|
mod: mod
|
||||||
}
|
}
|
||||||
} else if p.peek_tok.kind == .colon && p.prev_tok.kind != .str_dollar {
|
|
||||||
// `foo(key:val, key2:val2)`
|
|
||||||
return p.struct_init(true) // short_syntax:true
|
|
||||||
// JS. function call with more than 1 dot
|
|
||||||
} else if language == .js && p.peek_tok.kind == .dot && p.peek_tok2.kind == .name {
|
} else if language == .js && p.peek_tok.kind == .dot && p.peek_tok2.kind == .name {
|
||||||
|
// JS. function call with more than 1 dot
|
||||||
node = p.call_expr(language, mod)
|
node = p.call_expr(language, mod)
|
||||||
} else {
|
} else {
|
||||||
node = p.parse_ident(language)
|
node = p.parse_ident(language)
|
||||||
|
|
|
@ -240,6 +240,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
// Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
|
// Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind in [.chartoken, .number, .string] {
|
if p.tok.kind in [.chartoken, .number, .string] {
|
||||||
|
// TODO deprecate
|
||||||
node = p.map_init()
|
node = p.map_init()
|
||||||
} else {
|
} else {
|
||||||
// it should be a struct
|
// it should be a struct
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
const (
|
||||||
|
alpha = 'a'
|
||||||
|
beta = 'b'
|
||||||
|
m = map{
|
||||||
|
alpha : 'Alpha'
|
||||||
|
beta : 'Beta'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fn test_const_keys() {
|
||||||
|
assert m[alpha] == 'Alpha'
|
||||||
|
assert m[beta] == 'Beta'
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Enum {
|
||||||
|
a b
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
m2 = map{
|
||||||
|
Enum.a.str() : 'first'
|
||||||
|
Enum.b.str() : 'second'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
fn test_method_call() {
|
||||||
|
assert m2.keys() == ['a', 'b']
|
||||||
|
assert m2[Enum.a.str()] == 'first'
|
||||||
|
assert m2[Enum.b.str()] == 'second'
|
||||||
|
}
|
Loading…
Reference in New Issue