Rename group to table (#115)

* Rename Group to Table Fixes #45 
* Change fmt.Errorf to errors.new for simple strings
This commit is contained in:
Thomas Pelletier
2016-12-03 12:32:16 +01:00
committed by GitHub
parent d464759235
commit ce7be745f0
7 changed files with 67 additions and 66 deletions
+6 -5
View File
@@ -4,6 +4,7 @@ package toml
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"unicode" "unicode"
) )
@@ -47,7 +48,7 @@ func parseKey(key string) ([]string, error) {
} else { } else {
if !wasInQuotes { if !wasInQuotes {
if buffer.Len() == 0 { if buffer.Len() == 0 {
return nil, fmt.Errorf("empty key group") return nil, errors.New("empty table key")
} }
groups = append(groups, buffer.String()) groups = append(groups, buffer.String())
buffer.Reset() buffer.Reset()
@@ -67,23 +68,23 @@ func parseKey(key string) ([]string, error) {
return nil, fmt.Errorf("invalid bare character: %c", char) return nil, fmt.Errorf("invalid bare character: %c", char)
} }
if !inQuotes && expectDot { if !inQuotes && expectDot {
return nil, fmt.Errorf("what?") return nil, errors.New("what?")
} }
buffer.WriteRune(char) buffer.WriteRune(char)
expectDot = false expectDot = false
} }
} }
if inQuotes { if inQuotes {
return nil, fmt.Errorf("mismatched quotes") return nil, errors.New("mismatched quotes")
} }
if escapeNext { if escapeNext {
return nil, fmt.Errorf("unfinished escape sequence") return nil, errors.New("unfinished escape sequence")
} }
if buffer.Len() > 0 { if buffer.Len() > 0 {
groups = append(groups, buffer.String()) groups = append(groups, buffer.String())
} }
if len(groups) == 0 { if len(groups) == 0 {
return nil, fmt.Errorf("empty key") return nil, errors.New("empty key")
} }
return groups, nil return groups, nil
} }
+12 -12
View File
@@ -129,7 +129,7 @@ func (l *tomlLexer) lexVoid() tomlLexStateFn {
next := l.peek() next := l.peek()
switch next { switch next {
case '[': case '[':
return l.lexKeyGroup return l.lexTableKey
case '#': case '#':
return l.lexComment return l.lexComment
case '=': case '=':
@@ -516,21 +516,21 @@ func (l *tomlLexer) lexString() tomlLexStateFn {
return l.lexRvalue return l.lexRvalue
} }
func (l *tomlLexer) lexKeyGroup() tomlLexStateFn { func (l *tomlLexer) lexTableKey() tomlLexStateFn {
l.next() l.next()
if l.peek() == '[' { if l.peek() == '[' {
// token '[[' signifies an array of anonymous key groups // token '[[' signifies an array of tables
l.next() l.next()
l.emit(tokenDoubleLeftBracket) l.emit(tokenDoubleLeftBracket)
return l.lexInsideKeyGroupArray return l.lexInsideTableArrayKey
} }
// vanilla key group // vanilla table key
l.emit(tokenLeftBracket) l.emit(tokenLeftBracket)
return l.lexInsideKeyGroup return l.lexInsideTableKey
} }
func (l *tomlLexer) lexInsideKeyGroupArray() tomlLexStateFn { func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() { for r := l.peek(); r != eof; r = l.peek() {
switch r { switch r {
case ']': case ']':
@@ -545,15 +545,15 @@ func (l *tomlLexer) lexInsideKeyGroupArray() tomlLexStateFn {
l.emit(tokenDoubleRightBracket) l.emit(tokenDoubleRightBracket)
return l.lexVoid return l.lexVoid
case '[': case '[':
return l.errorf("group name cannot contain ']'") return l.errorf("table array key cannot contain ']'")
default: default:
l.next() l.next()
} }
} }
return l.errorf("unclosed key group array") return l.errorf("unclosed table array key")
} }
func (l *tomlLexer) lexInsideKeyGroup() tomlLexStateFn { func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn {
for r := l.peek(); r != eof; r = l.peek() { for r := l.peek(); r != eof; r = l.peek() {
switch r { switch r {
case ']': case ']':
@@ -564,12 +564,12 @@ func (l *tomlLexer) lexInsideKeyGroup() tomlLexStateFn {
l.emit(tokenRightBracket) l.emit(tokenRightBracket)
return l.lexVoid return l.lexVoid
case '[': case '[':
return l.errorf("group name cannot contain ']'") return l.errorf("table key cannot contain ']'")
default: default:
l.next() l.next()
} }
} }
return l.errorf("unclosed key group") return l.errorf("unclosed table key")
} }
func (l *tomlLexer) lexRightBracket() tomlLexStateFn { func (l *tomlLexer) lexRightBracket() tomlLexStateFn {
+1 -1
View File
@@ -56,7 +56,7 @@ func TestNestedQuotedUnicodeKeyGroup(t *testing.T) {
func TestUnclosedKeyGroup(t *testing.T) { func TestUnclosedKeyGroup(t *testing.T) {
testFlow(t, "[hello world", []token{ testFlow(t, "[hello world", []token{
{Position{1, 1}, tokenLeftBracket, "["}, {Position{1, 1}, tokenLeftBracket, "["},
{Position{1, 2}, tokenError, "unclosed key group"}, {Position{1, 2}, tokenError, "unclosed table key"},
}) })
} }
+35 -34
View File
@@ -3,6 +3,7 @@
package toml package toml
import ( import (
"errors"
"fmt" "fmt"
"reflect" "reflect"
"regexp" "regexp"
@@ -15,8 +16,8 @@ type tomlParser struct {
flow chan token flow chan token
tree *TomlTree tree *TomlTree
tokensBuffer []token tokensBuffer []token
currentGroup []string currentTable []string
seenGroupKeys []string seenTableKeys []string
} }
type tomlParserStateFn func() tomlParserStateFn type tomlParserStateFn func() tomlParserStateFn
@@ -95,13 +96,13 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
startToken := p.getToken() // discard the [[ startToken := p.getToken() // discard the [[
key := p.getToken() key := p.getToken()
if key.typ != tokenKeyGroupArray { if key.typ != tokenKeyGroupArray {
p.raiseError(key, "unexpected token %s, was expecting a key group array", key) p.raiseError(key, "unexpected token %s, was expecting a table array key", key)
} }
// get or create group array element at the indicated part in the path // get or create table array element at the indicated part in the path
keys, err := parseKey(key.val) keys, err := parseKey(key.val)
if err != nil { if err != nil {
p.raiseError(key, "invalid group array key: %s", err) p.raiseError(key, "invalid table array key: %s", err)
} }
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
destTree := p.tree.GetPath(keys) destTree := p.tree.GetPath(keys)
@@ -111,32 +112,32 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
} else if target, ok := destTree.([]*TomlTree); ok && target != nil { } else if target, ok := destTree.([]*TomlTree); ok && target != nil {
array = destTree.([]*TomlTree) array = destTree.([]*TomlTree)
} else { } else {
p.raiseError(key, "key %s is already assigned and not of type group array", key) p.raiseError(key, "key %s is already assigned and not of type table array", key)
} }
p.currentGroup = keys p.currentTable = keys
// add a new tree to the end of the group array // add a new tree to the end of the table array
newTree := newTomlTree() newTree := newTomlTree()
newTree.position = startToken.Position newTree.position = startToken.Position
array = append(array, newTree) array = append(array, newTree)
p.tree.SetPath(p.currentGroup, array) p.tree.SetPath(p.currentTable, array)
// remove all keys that were children of this group array // remove all keys that were children of this table array
prefix := key.val + "." prefix := key.val + "."
found := false found := false
for ii := 0; ii < len(p.seenGroupKeys); { for ii := 0; ii < len(p.seenTableKeys); {
groupKey := p.seenGroupKeys[ii] tableKey := p.seenTableKeys[ii]
if strings.HasPrefix(groupKey, prefix) { if strings.HasPrefix(tableKey, prefix) {
p.seenGroupKeys = append(p.seenGroupKeys[:ii], p.seenGroupKeys[ii+1:]...) p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...)
} else { } else {
found = (groupKey == key.val) found = (tableKey == key.val)
ii++ ii++
} }
} }
// keep this key name from use by other kinds of assignments // keep this key name from use by other kinds of assignments
if !found { if !found {
p.seenGroupKeys = append(p.seenGroupKeys, key.val) p.seenTableKeys = append(p.seenTableKeys, key.val)
} }
// move to next parser state // move to next parser state
@@ -148,24 +149,24 @@ func (p *tomlParser) parseGroup() tomlParserStateFn {
startToken := p.getToken() // discard the [ startToken := p.getToken() // discard the [
key := p.getToken() key := p.getToken()
if key.typ != tokenKeyGroup { if key.typ != tokenKeyGroup {
p.raiseError(key, "unexpected token %s, was expecting a key group", key) p.raiseError(key, "unexpected token %s, was expecting a table key", key)
} }
for _, item := range p.seenGroupKeys { for _, item := range p.seenTableKeys {
if item == key.val { if item == key.val {
p.raiseError(key, "duplicated tables") p.raiseError(key, "duplicated tables")
} }
} }
p.seenGroupKeys = append(p.seenGroupKeys, key.val) p.seenTableKeys = append(p.seenTableKeys, key.val)
keys, err := parseKey(key.val) keys, err := parseKey(key.val)
if err != nil { if err != nil {
p.raiseError(key, "invalid group array key: %s", err) p.raiseError(key, "invalid table array key: %s", err)
} }
if err := p.tree.createSubTree(keys, startToken.Position); err != nil { if err := p.tree.createSubTree(keys, startToken.Position); err != nil {
p.raiseError(key, "%s", err) p.raiseError(key, "%s", err)
} }
p.assume(tokenRightBracket) p.assume(tokenRightBracket)
p.currentGroup = keys p.currentTable = keys
return p.parseStart return p.parseStart
} }
@@ -174,26 +175,26 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
p.assume(tokenEqual) p.assume(tokenEqual)
value := p.parseRvalue() value := p.parseRvalue()
var groupKey []string var tableKey []string
if len(p.currentGroup) > 0 { if len(p.currentTable) > 0 {
groupKey = p.currentGroup tableKey = p.currentTable
} else { } else {
groupKey = []string{} tableKey = []string{}
} }
// find the group to assign, looking out for arrays of groups // find the table to assign, looking out for arrays of tables
var targetNode *TomlTree var targetNode *TomlTree
switch node := p.tree.GetPath(groupKey).(type) { switch node := p.tree.GetPath(tableKey).(type) {
case []*TomlTree: case []*TomlTree:
targetNode = node[len(node)-1] targetNode = node[len(node)-1]
case *TomlTree: case *TomlTree:
targetNode = node targetNode = node
default: default:
p.raiseError(key, "Unknown group type for path: %s", p.raiseError(key, "Unknown table type for path: %s",
strings.Join(groupKey, ".")) strings.Join(tableKey, "."))
} }
// assign value to the found group // assign value to the found table
keyVals, err := parseKey(key.val) keyVals, err := parseKey(key.val)
if err != nil { if err != nil {
p.raiseError(key, "%s", err) p.raiseError(key, "%s", err)
@@ -203,7 +204,7 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
} }
keyVal := keyVals[0] keyVal := keyVals[0]
localKey := []string{keyVal} localKey := []string{keyVal}
finalKey := append(groupKey, keyVal) finalKey := append(tableKey, 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, "."))
@@ -224,7 +225,7 @@ var numberUnderscoreInvalidRegexp *regexp.Regexp
func cleanupNumberToken(value string) (string, error) { func cleanupNumberToken(value string) (string, error) {
if numberUnderscoreInvalidRegexp.MatchString(value) { if numberUnderscoreInvalidRegexp.MatchString(value) {
return "", fmt.Errorf("invalid use of _ in number") return "", errors.New("invalid use of _ in number")
} }
cleanedVal := strings.Replace(value, "_", "", -1) cleanedVal := strings.Replace(value, "_", "", -1)
return cleanedVal, nil return cleanedVal, nil
@@ -380,8 +381,8 @@ func parseToml(flow chan token) *TomlTree {
flow: flow, flow: flow,
tree: result, tree: result,
tokensBuffer: make([]token, 0), tokensBuffer: make([]token, 0),
currentGroup: make([]string, 0), currentTable: make([]string, 0),
seenGroupKeys: make([]string, 0), seenTableKeys: make([]string, 0),
} }
parser.run() parser.run()
return result return result
+6 -6
View File
@@ -456,7 +456,7 @@ func TestDuplicateKeys(t *testing.T) {
func TestEmptyIntermediateTable(t *testing.T) { func TestEmptyIntermediateTable(t *testing.T) {
_, err := Load("[foo..bar]") _, err := Load("[foo..bar]")
if err.Error() != "(1, 2): invalid group array key: empty key group" { if err.Error() != "(1, 2): invalid table array key: empty table key" {
t.Error("Bad error message:", err.Error()) t.Error("Bad error message:", err.Error())
} }
} }
@@ -580,12 +580,12 @@ func TestParseKeyGroupArray(t *testing.T) {
func TestParseKeyGroupArrayUnfinished(t *testing.T) { func TestParseKeyGroupArrayUnfinished(t *testing.T) {
_, err := Load("[[foo.bar]\na = 42") _, err := Load("[[foo.bar]\na = 42")
if err.Error() != "(1, 10): was expecting token [[, but got unclosed key group array instead" { if err.Error() != "(1, 10): was expecting token [[, but got unclosed table array key instead" {
t.Error("Bad error message:", err.Error()) t.Error("Bad error message:", err.Error())
} }
_, err = Load("[[foo.[bar]\na = 42") _, err = Load("[[foo.[bar]\na = 42")
if err.Error() != "(1, 3): unexpected token group name cannot contain ']', was expecting a key group array" { if err.Error() != "(1, 3): unexpected token table array key cannot contain ']', was expecting a table array key" {
t.Error("Bad error message:", err.Error()) t.Error("Bad error message:", err.Error())
} }
} }
@@ -753,13 +753,13 @@ func TestNestedTreePosition(t *testing.T) {
} }
func TestInvalidGroupArray(t *testing.T) { func TestInvalidGroupArray(t *testing.T) {
_, err := Load("[key#group]\nanswer = 42") _, err := Load("[table#key]\nanswer = 42")
if err == nil { if err == nil {
t.Error("Should error") t.Error("Should error")
} }
_, err = Load("[foo.[bar]\na = 42") _, err = Load("[foo.[bar]\na = 42")
if err.Error() != "(1, 2): unexpected token group name cannot contain ']', was expecting a key group" { if err.Error() != "(1, 2): unexpected token table key cannot contain ']', was expecting a table key" {
t.Error("Bad error message:", err.Error()) t.Error("Bad error message:", err.Error())
} }
} }
@@ -773,7 +773,7 @@ func TestDoubleEqual(t *testing.T) {
func TestGroupArrayReassign(t *testing.T) { func TestGroupArrayReassign(t *testing.T) {
_, err := Load("[hello]\n[[hello]]") _, err := Load("[hello]\n[[hello]]")
if err.Error() != "(2, 3): key \"hello\" is already assigned and not of type group array" { if err.Error() != "(2, 3): key \"hello\" is already assigned and not of type table array" {
t.Error("Bad error message:", err.Error()) t.Error("Bad error message:", err.Error())
} }
} }
+1 -1
View File
@@ -92,7 +92,7 @@ func toTomlValue(item interface{}, indent int) string {
} }
// Recursive support function for ToString() // Recursive support function for ToString()
// Outputs a tree, using the provided keyspace to prefix group names // Outputs a tree, using the provided keyspace to prefix table names
func (t *TomlTree) toToml(indent, keyspace string) string { func (t *TomlTree) toToml(indent, keyspace string) string {
resultChunks := []string{} resultChunks := []string{}
for k, v := range t.values { for k, v := range t.values {
+1 -2
View File
@@ -2,9 +2,9 @@ package toml
import ( import (
"reflect" "reflect"
"strings"
"testing" "testing"
"time" "time"
"strings"
) )
func TestTomlTreeConversionToString(t *testing.T) { func TestTomlTreeConversionToString(t *testing.T) {
@@ -47,7 +47,6 @@ func TestTomlTreeConversionToStringKeysOrders(t *testing.T) {
r := strings.NewReader(stringRepr) r := strings.NewReader(stringRepr)
toml, err := LoadReader(r) toml, err := LoadReader(r)
if err != nil { if err != nil {
t.Fatal("Unexpected error:", err) t.Fatal("Unexpected error:", err)
} }