Handle dots in keys
diff --git a/lexer.go b/lexer.go index 5efbf6b..5dfff38 100644 --- a/lexer.go +++ b/lexer.go
@@ -169,10 +169,6 @@ return lexEqual } - if isAlphanumeric(next) { - return lexKey - } - if isSpace(next) { l.ignore() } @@ -181,6 +177,10 @@ return lexRvalue } + if isKeyChar(next) { + return lexKey + } + if l.next() == eof { break }
diff --git a/lexer_test.go b/lexer_test.go index 6436378..8582520 100644 --- a/lexer_test.go +++ b/lexer_test.go
@@ -121,6 +121,14 @@ 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) { testFlow(t, "foo = \"hello\\\"\"", []token{
diff --git a/parser.go b/parser.go index 6328d12..672bb35 100644 --- a/parser.go +++ b/parser.go
@@ -6,6 +6,7 @@ "fmt" "reflect" "strconv" + "strings" "time" ) @@ -13,7 +14,7 @@ flow chan token tree *TomlTree tokensBuffer []token - currentGroup string + currentGroup []string seenGroupKeys []string } @@ -96,7 +97,7 @@ p.seenGroupKeys = append(p.seenGroupKeys, key.val) p.tree.createSubTree(key.val) p.assume(tokenRightBracket) - p.currentGroup = key.val + p.currentGroup = strings.Split(key.val, ".") return parseStart(p) } @@ -104,14 +105,17 @@ key := p.getToken() p.assume(tokenEqual) value := parseRvalue(p) - final_key := key.val - if p.currentGroup != "" { - final_key = p.currentGroup + "." + key.val + var final_key []string + if len(p.currentGroup) > 0 { + final_key = p.currentGroup + } else { + final_key = make([]string, 0) } - if p.tree.Get(final_key) != nil { - panic(fmt.Sprintf("the following key was defined twice: %s", final_key)) + final_key = append(final_key, key.val) + 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) } @@ -182,8 +186,6 @@ panic("unterminated array") } if follow.typ != tokenRightBracket && follow.typ != tokenComma { - fmt.Println(follow.typ) - fmt.Println(follow.val) panic("missing comma") } if follow.typ == tokenComma { @@ -199,7 +201,7 @@ flow: flow, tree: &result, tokensBuffer: make([]token, 0), - currentGroup: "", + currentGroup: make([]string, 0), seenGroupKeys: make([]string, 0), } parser.run()
diff --git a/toml.go b/toml.go index e1a137f..dbf8ae8 100644 --- a/toml.go +++ b/toml.go
@@ -42,8 +42,11 @@ // Key is a dot-separated path (e.g. a.b.c). // Returns nil if the path does not exist in the tree. func (t *TomlTree) Get(key string) interface{} { + return t.GetPath(strings.Split(key, ".")) +} + +func (t *TomlTree) GetPath(keys []string) interface{} { subtree := t - keys := strings.Split(key, ".") for _, intermediate_key := range keys[:len(keys)-1] { _, exists := (*subtree)[intermediate_key] if !exists { @@ -67,8 +70,11 @@ // Key is a dot-separated path (e.g. a.b.c). // Creates all necessary intermediates trees, if needed. func (t *TomlTree) Set(key string, value interface{}) { + t.SetPath(strings.Split(key, "."), value) +} + +func (t *TomlTree) SetPath(keys []string, value interface{}) { subtree := t - keys := strings.Split(key, ".") for _, intermediate_key := range keys[:len(keys)-1] { _, exists := (*subtree)[intermediate_key] if !exists {