Dict literal now accepts expressions as keys. Key values are computed at evalutetion time and still must be integer or string

This commit is contained in:
2026-05-20 05:14:22 +02:00
parent 1aea1c14d2
commit 1055569dd6
6 changed files with 60 additions and 46 deletions
+39 -22
View File
@@ -257,24 +257,41 @@ func (parser *parser) parseIterDef(scanner *scan.Scanner, ctx parserContext) (su
return
}
func (parser *parser) parseDictKey(scanner *scan.Scanner) (key any, err error) {
tk := parser.Next(scanner)
if tk.Sym == scan.SymError {
err = tk.Error()
return
}
if tk.Sym == scan.SymClosedBrace || tk.Sym == scan.SymEos {
return
}
if tk.Sym == scan.SymInteger || tk.Sym == scan.SymString {
tkSep := parser.Next(scanner)
if tkSep.Sym != scan.SymColon {
// func (parser *parser) parseDictKey(scanner *scan.Scanner) (key any, err error) {
// tk := parser.Next(scanner)
// if tk.Sym == scan.SymError {
// err = tk.Error()
// return
// }
// if tk.Sym == scan.SymClosedBrace || tk.Sym == scan.SymEos {
// return
// }
// if tk.Sym == scan.SymInteger || tk.Sym == scan.SymString || tk.Sym == scan.SymIdentifier {
// tkSep := parser.Next(scanner)
// if tkSep.Sym != scan.SymColon {
// err = tkSep.ErrorExpectedGot(":")
// } else {
// key = tk.Value
// }
// } else {
// err = tk.ErrorExpectedGot("dictionary-key or }")
// }
// return
// }
func (parser *parser) parseDictKey(scanner *scan.Scanner) (key *scan.Term, err error) {
var keyTree *scan.Ast
if keyTree, err = parser.parseItem(scanner, parserNoFlags, scan.SymColon, scan.SymClosedBrace); err == nil {
key = keyTree.Root()
tkSep := scanner.Previous()
sym := tkSep.Sym
if sym == scan.SymClosedBrace || sym == scan.SymEos {
if key != nil {
err = tkSep.ErrorExpectedGot(":")
}
} else if sym != scan.SymColon {
err = tkSep.ErrorExpectedGot(":")
} else {
key = tk.Value
}
} else {
err = tk.ErrorExpectedGot("dictionary-key or }")
}
return
}
@@ -284,11 +301,11 @@ func (parser *parser) parseDictionary(scanner *scan.Scanner, ctx parserContext)
lastSym := scan.SymUnknown
itemExpected := false
for lastSym != scan.SymClosedBrace && lastSym != scan.SymEos {
var subTree *scan.Ast
var valueTree *scan.Ast
var key any
if key, err = parser.parseDictKey(scanner); err != nil {
break
} else if key == nil {
} else if key.(*scan.Term) == nil {
tk := scanner.Previous()
lastSym = tk.Sym
if itemExpected {
@@ -296,9 +313,9 @@ func (parser *parser) parseDictionary(scanner *scan.Scanner, ctx parserContext)
}
break
}
if subTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedBrace); err == nil {
if subTree.Root() != nil {
args[key] = subTree.Root()
if valueTree, err = parser.parseItem(scanner, ctx, scan.SymComma, scan.SymClosedBrace); err == nil {
if valueTree.Root() != nil {
args[key] = valueTree.Root()
} else /*if key != nil*/ {
prev := scanner.Previous()
err = prev.ErrorExpectedGot("dictionary-value")
@@ -464,7 +481,7 @@ func (parser *parser) parseGeneral(scanner *scan.Scanner, ctx parserContext, ter
selectorTerm = nil
continue
} else {
err = tk.Errorf(`unexpected token %q, expected ",", "]", or ")"`, tk.Source())
err = tk.ErrorExpectedOneOfGot(termSymbols...)
break
}
}