Merge pull request #40 from pelletier/pelletier/space-in-keys

Accept spaces in keys
diff --git a/keysparsing.go b/keysparsing.go
index 528f1de..7535379 100644
--- a/keysparsing.go
+++ b/keysparsing.go
@@ -13,7 +13,16 @@
 	var buffer bytes.Buffer
 	inQuotes := false
 	escapeNext := false
+	ignoreSpace := true
+	expectDot := false
+
 	for _, char := range key {
+		if ignoreSpace {
+			if char == ' ' {
+				continue
+			}
+			ignoreSpace = false
+		}
 		if escapeNext {
 			buffer.WriteRune(char)
 			escapeNext = false
@@ -25,18 +34,31 @@
 			continue
 		case '"':
 			inQuotes = !inQuotes
+			expectDot = false
 		case '.':
 			if inQuotes {
 				buffer.WriteRune(char)
 			} else {
 				groups = append(groups, buffer.String())
 				buffer.Reset()
+				ignoreSpace = true
+				expectDot = false
+			}
+		case ' ':
+			if inQuotes {
+				buffer.WriteRune(char)
+			} else {
+				expectDot = true
 			}
 		default:
 			if !inQuotes && !isValidBareChar(char) {
 				return nil, fmt.Errorf("invalid bare character: %c", char)
 			}
+			if !inQuotes && expectDot {
+				return nil, fmt.Errorf("what?")
+			}
 			buffer.WriteRune(char)
+			expectDot = false
 		}
 	}
 	if inQuotes {
diff --git a/lexer_test.go b/lexer_test.go
index 23b231b..de539c1 100644
--- a/lexer_test.go
+++ b/lexer_test.go
@@ -39,6 +39,15 @@
 	})
 }
 
+func TestNestedQuotedUnicodeKeyGroup(t *testing.T) {
+	testFlow(t, `[ j . "ʞ" . l ]`, []token{
+		token{Position{1, 1}, tokenLeftBracket, "["},
+		token{Position{1, 2}, tokenKeyGroup, ` j . "ʞ" . l `},
+		token{Position{1, 15}, tokenRightBracket, "]"},
+		token{Position{1, 16}, tokenEOF, ""},
+	})
+}
+
 func TestUnclosedKeyGroup(t *testing.T) {
 	testFlow(t, "[hello world", []token{
 		token{Position{1, 1}, tokenLeftBracket, "["},
diff --git a/parser_test.go b/parser_test.go
index 2998913..6672c06 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -157,6 +157,41 @@
 	})
 }
 
+func TestNestedQuotedUnicodeKeys(t *testing.T) {
+	tree, err := Load("[ j . \"ʞ\" . l ]\nd = 42")
+	assertTree(t, tree, err, map[string]interface{}{
+		"j": map[string]interface{}{
+			"ʞ": map[string]interface{}{
+				"l": map[string]interface{}{
+					"d": int64(42),
+				},
+			},
+		},
+	})
+
+	tree, err = Load("[ g . h . i ]\nd = 42")
+	assertTree(t, tree, err, map[string]interface{}{
+		"g": map[string]interface{}{
+			"h": map[string]interface{}{
+				"i": map[string]interface{}{
+					"d": int64(42),
+				},
+			},
+		},
+	})
+
+	tree, err = Load("[ d.e.f ]\nk = 42")
+	assertTree(t, tree, err, map[string]interface{}{
+		"d": map[string]interface{}{
+			"e": map[string]interface{}{
+				"f": map[string]interface{}{
+					"k": int64(42),
+				},
+			},
+		},
+	})
+}
+
 func TestArrayOne(t *testing.T) {
 	tree, err := Load("a = [1]")
 	assertTree(t, tree, err, map[string]interface{}{