parser: parse `map{key_expr: val_expr}` (#8608)
parent
db0fc8fbc9
commit
f5f65f929f
|
@ -128,13 +128,17 @@ fn test_map() {
|
|||
}
|
||||
|
||||
fn test_map_init() {
|
||||
m := {
|
||||
'one': 1
|
||||
one := 'one'
|
||||
three := 'three'
|
||||
m := map{
|
||||
one: 1
|
||||
'two': 2
|
||||
three: 1 + 2
|
||||
}
|
||||
assert m['one'] == 1
|
||||
assert m['two'] == 2
|
||||
assert m['three'] == 0
|
||||
assert m['three'] == 3
|
||||
assert m['unknown'] == 0
|
||||
}
|
||||
|
||||
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]
|
||||
if key_i is ast.StringLiteral {
|
||||
for j in 0 .. i {
|
||||
key_j := node.keys[j] as ast.StringLiteral
|
||||
if key_i.val == key_j.val {
|
||||
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
||||
key_j := node.keys[j]
|
||||
if key_j is ast.StringLiteral {
|
||||
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 {
|
||||
for j in 0 .. i {
|
||||
key_j := node.keys[j] as ast.IntegerLiteral
|
||||
if key_i.val == key_j.val {
|
||||
c.error('duplicate key "$key_i.val" in map literal', key_i.pos)
|
||||
key_j := node.keys[j]
|
||||
if key_j is ast.IntegerLiteral {
|
||||
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 {
|
||||
first_pos := p.prev_tok.position()
|
||||
mut keys := []ast.Expr{}
|
||||
|
|
|
@ -128,7 +128,13 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
|
|||
p.next()
|
||||
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 {
|
||||
e = ast.ArrayDecompose{
|
||||
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_case && (!p.inside_if || p.inside_select)
|
||||
&& (!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
|
||||
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||
// T.name
|
||||
|
@ -1351,11 +1361,8 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
pos: p.tok.position()
|
||||
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 {
|
||||
// JS. function call with more than 1 dot
|
||||
node = p.call_expr(language, mod)
|
||||
} else {
|
||||
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 }`
|
||||
p.next()
|
||||
if p.tok.kind in [.chartoken, .number, .string] {
|
||||
// TODO deprecate
|
||||
node = p.map_init()
|
||||
} else {
|
||||
// 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