Merge branch 'master' into pelletier/inline-tables
diff --git a/lexer_test.go b/lexer_test.go index 3509367..df2cac9 100644 --- a/lexer_test.go +++ b/lexer_test.go
@@ -457,6 +457,13 @@ token{Position{1, 7}, tokenInteger, "1_2_3_4_5"}, token{Position{1, 16}, tokenEOF, ""}, }) + + testFlow(t, "flt8 = 9_224_617.445_991_228_313", []token{ + token{Position{1, 1}, tokenKey, "flt8"}, + token{Position{1, 6}, tokenEqual, "="}, + token{Position{1, 8}, tokenFloat, "9_224_617.445_991_228_313"}, + token{Position{1, 33}, tokenEOF, ""}, + }) } func TestMultiline(t *testing.T) {
diff --git a/parser.go b/parser.go index 0fe0457..c3afa04 100644 --- a/parser.go +++ b/parser.go
@@ -232,7 +232,8 @@ } return val case tokenFloat: - val, err := strconv.ParseFloat(tok.val, 64) + cleanedVal := strings.Replace(tok.val, "_", "", -1) + val, err := strconv.ParseFloat(cleanedVal, 64) if err != nil { p.raiseError(tok, "%s", err) } @@ -312,18 +313,7 @@ } if follow.typ == tokenRightBracket { p.getToken() - // An array of TomlTrees is actually an array of inline - // tables, which is a shorthand for a table array. If the - // array was not converted from []interface{} to []*TomlTree, - // the two notations would not be equivalent. - if arrayType == reflect.TypeOf(newTomlTree()) { - tomlArray := make([]*TomlTree, len(array)) - for i, v := range array { - tomlArray[i] = v.(*TomlTree) - } - return tomlArray - } - return array + break } val := p.parseRvalue() if arrayType == nil { @@ -334,7 +324,7 @@ } array = append(array, val) follow = p.peek() - if follow == nil { + if follow == nil || follow.typ == tokenEOF { p.raiseError(follow, "unterminated array") } if follow.typ != tokenRightBracket && follow.typ != tokenComma { @@ -344,6 +334,17 @@ p.getToken() } } + // An array of TomlTrees is actually an array of inline + // tables, which is a shorthand for a table array. If the + // array was not converted from []interface{} to []*TomlTree, + // the two notations would not be equivalent. + if arrayType == reflect.TypeOf(newTomlTree()) { + tomlArray := make([]*TomlTree, len(array)) + for i, v := range array { + tomlArray[i] = v.(*TomlTree) + } + return tomlArray + } return array }
diff --git a/parser_test.go b/parser_test.go index 93d0e78..365c247 100644 --- a/parser_test.go +++ b/parser_test.go
@@ -68,7 +68,7 @@ }) } -func TestIntegersWithUnderscores(t *testing.T) { +func TestNumbersWithUnderscores(t *testing.T) { tree, err := Load("a = 1_000") assertTree(t, tree, err, map[string]interface{}{ "a": int64(1000), @@ -83,6 +83,16 @@ assertTree(t, tree, err, map[string]interface{}{ "a": int64(12345), }) + + tree, err = Load("flt8 = 9_224_617.445_991_228_313") + assertTree(t, tree, err, map[string]interface{}{ + "flt8": float64(9224617.445991228313), + }) + + tree, err = Load("flt9 = 1e1_00") + assertTree(t, tree, err, map[string]interface{}{ + "flt9": float64(1e100), + }) } func TestFloatsWithExponents(t *testing.T) { @@ -287,6 +297,16 @@ if err.Error() != "(1, 8): unterminated array" { t.Error("Bad error message:", err.Error()) } + + _, err = Load("a = [1") + if err.Error() != "(1, 7): unterminated array" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a = [1 2") + if err.Error() != "(1, 8): missing comma" { + t.Error("Bad error message:", err.Error()) + } } func TestNewlinesInArrays(t *testing.T) {