Handle dots in keys

This commit is contained in:
Thomas Pelletier
2013-12-10 21:51:40 +01:00
parent 0c4e891f3e
commit dc20c454d7
4 changed files with 33 additions and 17 deletions
+4 -4
View File
@@ -169,10 +169,6 @@ func lexVoid(l *lexer) stateFn {
return lexEqual return lexEqual
} }
if isAlphanumeric(next) {
return lexKey
}
if isSpace(next) { if isSpace(next) {
l.ignore() l.ignore()
} }
@@ -181,6 +177,10 @@ func lexVoid(l *lexer) stateFn {
return lexRvalue return lexRvalue
} }
if isKeyChar(next) {
return lexKey
}
if l.next() == eof { if l.next() == eof {
break break
} }
+8
View File
@@ -121,6 +121,14 @@ func TestKeyWithSharpAndEqual(t *testing.T) {
token{tokenEOF, ""}, token{tokenEOF, ""},
}) })
} }
func TestKeyWithSymbolsAndEqual(t *testing.T) {
testFlow(t, "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{
token{tokenKey, "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:'"},
token{tokenEqual, "="},
token{tokenInteger, "5"},
token{tokenEOF, ""},
})
}
func TestKeyEqualStringEscape(t *testing.T) { func TestKeyEqualStringEscape(t *testing.T) {
testFlow(t, "foo = \"hello\\\"\"", []token{ testFlow(t, "foo = \"hello\\\"\"", []token{
+13 -11
View File
@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"strconv" "strconv"
"strings"
"time" "time"
) )
@@ -13,7 +14,7 @@ type parser struct {
flow chan token flow chan token
tree *TomlTree tree *TomlTree
tokensBuffer []token tokensBuffer []token
currentGroup string currentGroup []string
seenGroupKeys []string seenGroupKeys []string
} }
@@ -96,7 +97,7 @@ func parseGroup(p *parser) parserStateFn {
p.seenGroupKeys = append(p.seenGroupKeys, key.val) p.seenGroupKeys = append(p.seenGroupKeys, key.val)
p.tree.createSubTree(key.val) p.tree.createSubTree(key.val)
p.assume(tokenRightBracket) p.assume(tokenRightBracket)
p.currentGroup = key.val p.currentGroup = strings.Split(key.val, ".")
return parseStart(p) return parseStart(p)
} }
@@ -104,14 +105,17 @@ func parseAssign(p *parser) parserStateFn {
key := p.getToken() key := p.getToken()
p.assume(tokenEqual) p.assume(tokenEqual)
value := parseRvalue(p) value := parseRvalue(p)
final_key := key.val var final_key []string
if p.currentGroup != "" { if len(p.currentGroup) > 0 {
final_key = p.currentGroup + "." + key.val final_key = p.currentGroup
} else {
final_key = make([]string, 0)
} }
if p.tree.Get(final_key) != nil { final_key = append(final_key, key.val)
panic(fmt.Sprintf("the following key was defined twice: %s", final_key)) if p.tree.GetPath(final_key) != nil {
panic(fmt.Sprintf("the following key was defined twice: %s", strings.Join(final_key, ".")))
} }
p.tree.Set(final_key, value) p.tree.SetPath(final_key, value)
return parseStart(p) return parseStart(p)
} }
@@ -182,8 +186,6 @@ func parseArray(p *parser) []interface{} {
panic("unterminated array") panic("unterminated array")
} }
if follow.typ != tokenRightBracket && follow.typ != tokenComma { if follow.typ != tokenRightBracket && follow.typ != tokenComma {
fmt.Println(follow.typ)
fmt.Println(follow.val)
panic("missing comma") panic("missing comma")
} }
if follow.typ == tokenComma { if follow.typ == tokenComma {
@@ -199,7 +201,7 @@ func parse(flow chan token) *TomlTree {
flow: flow, flow: flow,
tree: &result, tree: &result,
tokensBuffer: make([]token, 0), tokensBuffer: make([]token, 0),
currentGroup: "", currentGroup: make([]string, 0),
seenGroupKeys: make([]string, 0), seenGroupKeys: make([]string, 0),
} }
parser.run() parser.run()
+8 -2
View File
@@ -42,8 +42,11 @@ func (t *TomlTree) Keys() []string {
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Returns nil if the path does not exist in the tree. // Returns nil if the path does not exist in the tree.
func (t *TomlTree) Get(key string) interface{} { func (t *TomlTree) Get(key string) interface{} {
return t.GetPath(strings.Split(key, "."))
}
func (t *TomlTree) GetPath(keys []string) interface{} {
subtree := t subtree := t
keys := strings.Split(key, ".")
for _, intermediate_key := range keys[:len(keys)-1] { for _, intermediate_key := range keys[:len(keys)-1] {
_, exists := (*subtree)[intermediate_key] _, exists := (*subtree)[intermediate_key]
if !exists { if !exists {
@@ -67,8 +70,11 @@ func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
// Key is a dot-separated path (e.g. a.b.c). // Key is a dot-separated path (e.g. a.b.c).
// Creates all necessary intermediates trees, if needed. // Creates all necessary intermediates trees, if needed.
func (t *TomlTree) Set(key string, value interface{}) { func (t *TomlTree) Set(key string, value interface{}) {
t.SetPath(strings.Split(key, "."), value)
}
func (t *TomlTree) SetPath(keys []string, value interface{}) {
subtree := t subtree := t
keys := strings.Split(key, ".")
for _, intermediate_key := range keys[:len(keys)-1] { for _, intermediate_key := range keys[:len(keys)-1] {
_, exists := (*subtree)[intermediate_key] _, exists := (*subtree)[intermediate_key]
if !exists { if !exists {