Allow numbers in keys parsing

This commit is contained in:
Thomas Pelletier
2015-07-14 19:56:28 -07:00
parent 9f36448571
commit 16a681db2a
6 changed files with 41 additions and 16 deletions
+2 -1
View File
@@ -5,6 +5,7 @@ package toml
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"unicode"
) )
func parseKey(key string) ([]string, error) { func parseKey(key string) ([]string, error) {
@@ -51,5 +52,5 @@ func parseKey(key string) ([]string, error) {
} }
func isValidBareChar(r rune) bool { func isValidBareChar(r rune) bool {
return isAlphanumeric(r) || r == '-' return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r)
} }
+7 -2
View File
@@ -253,9 +253,14 @@ func (l *tomlLexer) lexComma() tomlLexStateFn {
func (l *tomlLexer) lexKey() tomlLexStateFn { func (l *tomlLexer) lexKey() tomlLexStateFn {
l.ignore() l.ignore()
inQuotes := false
for r := l.next(); isKeyChar(r); r = l.next() { for r := l.next(); isKeyChar(r); r = l.next() {
if r == '#' { if r == '"' {
return l.errorf("keys cannot contain # character") inQuotes = !inQuotes
} else if isSpace(r) && !inQuotes {
break
} else if !isValidBareChar(r) && !inQuotes {
return l.errorf("keys cannot contain %c character", r)
} }
} }
l.backup() l.backup()
+10 -4
View File
@@ -124,10 +124,7 @@ func TestKeyWithSharpAndEqual(t *testing.T) {
func TestKeyWithSymbolsAndEqual(t *testing.T) { func TestKeyWithSymbolsAndEqual(t *testing.T) {
testFlow(t, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{ testFlow(t, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{
token{Position{1, 1}, tokenKey, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:'"}, token{Position{1, 1}, tokenError, "keys cannot contain ~ character"},
token{Position{1, 38}, tokenEqual, "="},
token{Position{1, 40}, tokenInteger, "5"},
token{Position{1, 41}, tokenEOF, ""},
}) })
} }
@@ -549,3 +546,12 @@ func TestKeyGroupArray(t *testing.T) {
token{Position{1, 8}, tokenEOF, ""}, token{Position{1, 8}, tokenEOF, ""},
}) })
} }
func TestQuotedKey(t *testing.T) {
testFlow(t, "\"a b\" = 42", []token{
token{Position{1, 1}, tokenKey, "\"a b\""},
token{Position{1, 7}, tokenEqual, "="},
token{Position{1, 9}, tokenInteger, "42"},
token{Position{1, 11}, tokenEOF, ""},
})
}
+11 -3
View File
@@ -192,13 +192,21 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
} }
// assign value to the found group // assign value to the found group
localKey := []string{key.val} keyVals, err := parseKey(key.val)
finalKey := append(groupKey, key.val) if err != nil {
p.raiseError(key, "%s", err)
}
if len(keyVals) != 1 {
p.raiseError(key, "Invalid key")
}
keyVal := keyVals[0]
localKey := []string{keyVal}
finalKey := append(groupKey, keyVal)
if targetNode.GetPath(localKey) != nil { if targetNode.GetPath(localKey) != nil {
p.raiseError(key, "The following key was defined twice: %s", p.raiseError(key, "The following key was defined twice: %s",
strings.Join(finalKey, ".")) strings.Join(finalKey, "."))
} }
targetNode.values[key.val] = &tomlValue{value, key.Position} targetNode.values[keyVal] = &tomlValue{value, key.Position}
return p.parseStart return p.parseStart
} }
+10 -5
View File
@@ -51,12 +51,10 @@ func TestSimpleKV(t *testing.T) {
}) })
} }
// NOTE: from the BurntSushi test suite func TestNumberInKey(t *testing.T) {
// NOTE: this test is pure evil due to the embedded '.' tree, err := Load("hello2 = 42")
func TestSpecialKV(t *testing.T) {
tree, err := Load("~!@$^&*()_+-`1234567890[]\\|/?><.,;: = 1")
assertTree(t, tree, err, map[string]interface{}{ assertTree(t, tree, err, map[string]interface{}{
"~!@$^&*()_+-`1234567890[]\\|/?><.,;:": int64(1), "hello2": int64(42),
}) })
} }
@@ -109,6 +107,13 @@ func TestSimpleString(t *testing.T) {
}) })
} }
func TestSpaceKey(t *testing.T) {
tree, err := Load("\"a b\" = \"hello world\"")
assertTree(t, tree, err, map[string]interface{}{
"a b": "hello world",
})
}
func TestStringEscapables(t *testing.T) { func TestStringEscapables(t *testing.T) {
tree, err := Load("a = \"a \\n b\"") tree, err := Load("a = \"a \\n b\"")
assertTree(t, tree, err, map[string]interface{}{ assertTree(t, tree, err, map[string]interface{}{
+1 -1
View File
@@ -120,7 +120,7 @@ func isKeyChar(r rune) bool {
// Keys start with the first character that isn't whitespace or [ and end // Keys start with the first character that isn't whitespace or [ and end
// with the last non-whitespace character before the equals sign. Keys // with the last non-whitespace character before the equals sign. Keys
// cannot contain a # character." // cannot contain a # character."
return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '=') return !(r == '\r' || r == '\n' || r == eof || r == '=')
} }
func isKeyStartChar(r rune) bool { func isKeyStartChar(r rune) bool {