Basic keys parsing

This commit is contained in:
Thomas Pelletier
2015-07-14 16:33:33 -07:00
parent 222e90a7d3
commit 9f36448571
4 changed files with 114 additions and 2 deletions
+55
View File
@@ -0,0 +1,55 @@
// Parsing keys handling both bare and quoted keys.
package toml
import (
"bytes"
"fmt"
)
func parseKey(key string) ([]string, error) {
groups := []string{}
var buffer bytes.Buffer
inQuotes := false
escapeNext := false
for _, char := range key {
if escapeNext {
buffer.WriteRune(char)
escapeNext = false
continue
}
switch char {
case '\\':
escapeNext = true
continue
case '"':
inQuotes = !inQuotes
case '.':
if inQuotes {
buffer.WriteRune(char)
} else {
groups = append(groups, buffer.String())
buffer.Reset()
}
default:
if !inQuotes && !isValidBareChar(char) {
return nil, fmt.Errorf("invalid bare character: %c", char)
}
buffer.WriteRune(char)
}
}
if inQuotes {
return nil, fmt.Errorf("mismatched quotes")
}
if escapeNext {
return nil, fmt.Errorf("unfinished escape sequence")
}
if buffer.Len() > 0 {
groups = append(groups, buffer.String())
}
return groups, nil
}
func isValidBareChar(r rune) bool {
return isAlphanumeric(r) || r == '-'
}
+44
View File
@@ -0,0 +1,44 @@
package toml
import (
"fmt"
"testing"
)
func testResult(t *testing.T, key string, expected []string) {
parsed, err := parseKey(key)
if err != nil {
t.Fatal("Unexpected error:", err)
}
if len(expected) != len(parsed) {
t.Fatal("Expected length", len(expected), "but", len(parsed), "parsed")
}
for index, expectedKey := range expected {
if expectedKey != parsed[index] {
t.Fatal("Expected", expectedKey, "at index", index, "but found", parsed[index])
}
}
}
func testError(t *testing.T, key string, expectedError string) {
_, err := parseKey(key)
if fmt.Sprintf("%s", err) != expectedError {
t.Fatalf("Expected error \"%s\", but got \"%s\".", expectedError, err)
}
}
func TestBareKeyBasic(t *testing.T) {
testResult(t, "test", []string{"test"})
}
func TestBareKeyDotted(t *testing.T) {
testResult(t, "this.is.a.key", []string{"this", "is", "a", "key"})
}
func TestDottedKeyBasic(t *testing.T) {
testResult(t, "\"a.dotted.key\"", []string{"a.dotted.key"})
}
func TestBaseKeyPound(t *testing.T) {
testError(t, "hello#world", "invalid bare character: #")
}
+8 -2
View File
@@ -98,7 +98,10 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
}
// get or create group array element at the indicated part in the path
keys := strings.Split(key.val, ".")
keys, err := parseKey(key.val)
if err != nil {
p.raiseError(key, "invalid group array key: %s", err)
}
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
destTree := p.tree.GetPath(keys)
var array []*TomlTree
@@ -153,7 +156,10 @@ func (p *tomlParser) parseGroup() tomlParserStateFn {
}
p.seenGroupKeys = append(p.seenGroupKeys, key.val)
keys := strings.Split(key.val, ".")
keys, err := parseKey(key.val)
if err != nil {
p.raiseError(key, "invalid group array key: %s", err)
}
if err := p.tree.createSubTree(keys, startToken.Position); err != nil {
p.raiseError(key, "%s", err)
}
+7
View File
@@ -461,3 +461,10 @@ func TestNestedTreePosition(t *testing.T) {
"foo.bar.b": Position{3, 1},
})
}
func TestInvalidGroupArray(t *testing.T) {
_, err := Load("[key#group]\nanswer = 42")
if err == nil {
t.Error("Should error")
}
}