Implemented inline tables + tests.
This commit is contained in:
parent
97153fc806
commit
fd9365b842
|
@ -49,7 +49,11 @@ func (t *parser) startKeyValuePair(p *parse.API) {
|
||||||
key, ok := t.parseKey(p, []string{})
|
key, ok := t.parseKey(p, []string{})
|
||||||
if ok && p.Handle(t.startAssignment) {
|
if ok && p.Handle(t.startAssignment) {
|
||||||
if value, ok := t.parseValue(p); ok {
|
if value, ok := t.parseValue(p); ok {
|
||||||
t.setKeyValuePair(key, value)
|
err := t.setKeyValuePair(key, value)
|
||||||
|
if err != nil {
|
||||||
|
p.Error("%s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -48,6 +48,7 @@ func TestKeyValuePair(t *testing.T) {
|
||||||
{`another = "# This is not a comment"`, `{"another": "# This is not a comment"}`, ``},
|
{`another = "# This is not a comment"`, `{"another": "# This is not a comment"}`, ``},
|
||||||
{"key1=\"value1\"key2=\"value2\"\r\nkey3a.key3b=\"value3\"", `{"key1": "value1", "key2": "value2", "key3a": {"key3b": "value3"}}`, ``},
|
{"key1=\"value1\"key2=\"value2\"\r\nkey3a.key3b=\"value3\"", `{"key1": "value1", "key2": "value2", "key3a": {"key3b": "value3"}}`, ``},
|
||||||
{"with=\"comments\"# boring \nanother.cool =\"one\" \t # to the end\r\n", `{"another": {"cool": "one"}, "with": "comments"}`, ``},
|
{"with=\"comments\"# boring \nanother.cool =\"one\" \t # to the end\r\n", `{"another": {"cool": "one"}, "with": "comments"}`, ``},
|
||||||
|
{"key='value'\nkey='another value'", `{"key": "value"}`, `invalid key/value pair: string item already exists at key [key] at line 2, column 20`},
|
||||||
} {
|
} {
|
||||||
p := newParser()
|
p := newParser()
|
||||||
testParse(t, p, p.startKeyValuePair, test)
|
testParse(t, p, p.startKeyValuePair, test)
|
||||||
|
@ -129,6 +130,14 @@ func TestKeyValuePair_ExamplesFromSpecification(t *testing.T) {
|
||||||
{`arr6 = [ 1, 2.0 ] # INVALID`, `{}`, `type mismatch in array of integers: found an item of type float at line 1, column 16`},
|
{`arr6 = [ 1, 2.0 ] # INVALID`, `{}`, `type mismatch in array of integers: found an item of type float at line 1, column 16`},
|
||||||
{"arr7 = [\n 1, 2, 3\n]", `{"arr7": [1, 2, 3]}`, ``},
|
{"arr7 = [\n 1, 2, 3\n]", `{"arr7": [1, 2, 3]}`, ``},
|
||||||
{"arr8 = [\n 1,\n 2, # this is ok\n]", `{"arr8": [1, 2]}`, ``},
|
{"arr8 = [\n 1,\n 2, # this is ok\n]", `{"arr8": [1, 2]}`, ``},
|
||||||
|
{`name = { first = "Tom", last = "Preston-Werner" }`,
|
||||||
|
`{"name": {"first": "Tom", "last": "Preston-Werner"}}`, ``},
|
||||||
|
{`point = { x = 1, y = 2 }`,
|
||||||
|
`{"point": {"x": 1, "y": 2}}`, ``},
|
||||||
|
{`animal = { type.name = "pug" }`,
|
||||||
|
`{"animal": {"type": {"name": "pug"}}}`, ``},
|
||||||
|
{"points = [ { x = 1, y = 2, z = 3 },\n { x = 7, y = 8, z = 9 },\n { x = 2, y = 4, z = 8 } ]",
|
||||||
|
`{"points": [{"x": 1, "y": 2, "z": 3}, {"x": 7, "y": 8, "z": 9}, {"x": 2, "y": 4, "z": 8}]}`, ``},
|
||||||
} {
|
} {
|
||||||
p := newParser()
|
p := newParser()
|
||||||
testParse(t, p, p.startKeyValuePair, test)
|
testParse(t, p, p.startKeyValuePair, test)
|
||||||
|
|
3
value.go
3
value.go
|
@ -11,6 +11,7 @@ var (
|
||||||
detectDateTime = a.Digits.Then(a.Minus.Or(a.Colon))
|
detectDateTime = a.Digits.Then(a.Minus.Or(a.Colon))
|
||||||
detectNumber = a.Digit
|
detectNumber = a.Digit
|
||||||
detectArray = a.SquareOpen
|
detectArray = a.SquareOpen
|
||||||
|
detectInlineTable = a.CurlyOpen
|
||||||
)
|
)
|
||||||
|
|
||||||
// Values must be of the following types: String, Integer, Float, Boolean,
|
// Values must be of the following types: String, Integer, Float, Boolean,
|
||||||
|
@ -29,6 +30,8 @@ func (t *parser) parseValue(p *parse.API) (*item, bool) {
|
||||||
return t.parseNumber(p)
|
return t.parseNumber(p)
|
||||||
case p.Peek(detectArray):
|
case p.Peek(detectArray):
|
||||||
return t.parseArray(p)
|
return t.parseArray(p)
|
||||||
|
case p.Peek(detectInlineTable):
|
||||||
|
return t.parseInlineTable(p)
|
||||||
default:
|
default:
|
||||||
p.Expected("a value")
|
p.Expected("a value")
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|
|
@ -83,10 +83,9 @@ func (t *parser) parseDateTime(p *parse.API) (*item, bool) {
|
||||||
input, value, err := getDateTimeValue(&tokens)
|
input, value, err := getDateTimeValue(&tokens)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return newItem(valueType, value), true
|
return newItem(valueType, value), true
|
||||||
} else {
|
|
||||||
p.Error("invalid date/time value %s: %s", input, err)
|
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
p.Error("invalid date/time value %s: %s", input, err)
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first token is a token that wraps the complete date/time input.
|
// The first token is a token that wraps the complete date/time input.
|
||||||
|
|
239
value_table.go
239
value_table.go
|
@ -5,107 +5,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Tables (also known as hash tables or dictionaries) are collections of
|
// Opener and closer for [table].
|
||||||
// key/value pairs. They appear in square brackets on a line by themselves.
|
|
||||||
// You can tell them apart from arrays because arrays are only ever values.
|
|
||||||
//
|
|
||||||
// Under that, and until the next table or EOF are the key/values of that
|
|
||||||
// table. Key/value pairs within tables are not guaranteed to be in any
|
|
||||||
// specific order.
|
|
||||||
//
|
|
||||||
// [table-1]
|
|
||||||
// key1 = "some string"
|
|
||||||
// key2 = 123
|
|
||||||
//
|
|
||||||
// [table-2]
|
|
||||||
// key1 = "another string"
|
|
||||||
// key2 = 456
|
|
||||||
//
|
|
||||||
// Naming rules for tables are the same as for keys.
|
|
||||||
//
|
|
||||||
// [dog."tater.man"]
|
|
||||||
// type.name = "pug"
|
|
||||||
//
|
|
||||||
// Whitespace around the key is ignored, however, best practice is to not
|
|
||||||
// use any extraneous whitespace.
|
|
||||||
//
|
|
||||||
// [a.b.c] # this is best practice
|
|
||||||
// [ d.e.f ] # same as [d.e.f]
|
|
||||||
// [ g . h . i ] # same as [g.h.i]
|
|
||||||
// [ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
|
|
||||||
//
|
|
||||||
// You don't need to specify all the super-tables if you don't want to.
|
|
||||||
// TOML knows how to do it for you.
|
|
||||||
//
|
|
||||||
// # [x] you
|
|
||||||
// # [x.y] don't
|
|
||||||
// # [x.y.z] need these
|
|
||||||
// [x.y.z.w] # for this to work
|
|
||||||
//
|
|
||||||
// Empty tables are allowed and simply have no key/value pairs within them.
|
|
||||||
//
|
|
||||||
tableOpen = c.Seq(dropBlanks, a.SquareOpen, dropBlanks)
|
tableOpen = c.Seq(dropBlanks, a.SquareOpen, dropBlanks)
|
||||||
tableClose = c.Seq(dropBlanks, a.SquareClose, dropBlanks, a.EndOfLine.Or(comment))
|
tableClose = c.Seq(dropBlanks, a.SquareClose, dropBlanks, a.EndOfLine.Or(comment))
|
||||||
|
|
||||||
// Arrays of tables can be expressed by using a table name in double brackets.
|
// Opener and closer for [[array.of.tables]].
|
||||||
// Each table with the same double bracketed name will be an element in the
|
|
||||||
// array. The tables are inserted in the order encountered. A double bracketed
|
|
||||||
// table without any key/value pairs will be considered an empty table.
|
|
||||||
//
|
|
||||||
// [[products]]
|
|
||||||
// name = "Hammer"
|
|
||||||
// sku = 738594937
|
|
||||||
//
|
|
||||||
// [[products]]
|
|
||||||
//
|
|
||||||
// [[products]]
|
|
||||||
// name = "Nail"
|
|
||||||
// sku = 284758393
|
|
||||||
// color = "gray"
|
|
||||||
//
|
|
||||||
// You can create nested arrays of tables as well. Just use the same double
|
|
||||||
// bracket syntax on sub-tables. Each double-bracketed sub-table will belong
|
|
||||||
// to the most recently defined table element above it.
|
|
||||||
//
|
|
||||||
// [[fruit]]
|
|
||||||
// name = "apple"
|
|
||||||
//
|
|
||||||
// [fruit.physical]
|
|
||||||
// color = "red"
|
|
||||||
// shape = "round"
|
|
||||||
//
|
|
||||||
// [[fruit.variety]]
|
|
||||||
// name = "red delicious"
|
|
||||||
//
|
|
||||||
// [[fruit.variety]]
|
|
||||||
// name = "granny smith"
|
|
||||||
//
|
|
||||||
// [[fruit]]
|
|
||||||
// name = "banana"
|
|
||||||
//
|
|
||||||
// [[fruit.variety]]
|
|
||||||
// name = "plantain"
|
|
||||||
tableArrayOpen = c.Seq(dropBlanks, a.SquareOpen, a.SquareOpen, dropBlanks)
|
tableArrayOpen = c.Seq(dropBlanks, a.SquareOpen, a.SquareOpen, dropBlanks)
|
||||||
tableArrayClose = c.Seq(dropBlanks, a.SquareClose, a.SquareClose, dropBlanks, a.EndOfLine.Or(comment))
|
tableArrayClose = c.Seq(dropBlanks, a.SquareClose, a.SquareClose, dropBlanks, a.EndOfLine.Or(comment))
|
||||||
|
|
||||||
// Inline tables provide a more compact syntax for expressing tables.
|
// Opener, separator and closer for { inline: "tables" }.
|
||||||
// They are especially useful for grouped data that can otherwise quickly
|
inlineTableOpen = c.Seq(dropBlanks, a.CurlyOpen, dropBlanks)
|
||||||
// become verbose. Inline tables are enclosed in curly braces { and }.
|
inlineTableSeparator = c.Seq(dropBlanks, a.Comma, dropBlanks)
|
||||||
// Within the braces, zero or more comma separated key/value pairs may appear.
|
inlineTableClose = c.Seq(dropBlanks, a.CurlyClose, dropBlanks)
|
||||||
// Key/value pairs take the same form as key/value pairs in standard tables.
|
|
||||||
// All value types are allowed, including inline tables.
|
|
||||||
//
|
|
||||||
// Inline tables are intended to appear on a single line. No newlines are
|
|
||||||
// allowed between the curly braces unless they are valid within a value.
|
|
||||||
// Even so, it is strongly discouraged to break an inline table onto multiple
|
|
||||||
// lines. If you find yourself gripped with this desire, it means you should
|
|
||||||
// be using standard tables.
|
|
||||||
//
|
|
||||||
// name = { first = "Tom", last = "Preston-Werner" }
|
|
||||||
// point = { x = 1, y = 2 }
|
|
||||||
// animal = { type.name = "pug" }
|
|
||||||
inlineTableOpen = c.Seq(dropBlanks, a.CurlyOpen, dropBlanks)
|
|
||||||
inlineTableClose = c.Seq(dropBlanks, a.CurlyClose, dropBlanks, a.EndOfLine.Or(comment))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *parser) startTable(p *parse.API) {
|
func (t *parser) startTable(p *parse.API) {
|
||||||
|
@ -119,6 +30,44 @@ func (t *parser) startTable(p *parse.API) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arrays of tables can be expressed by using a table name in double brackets.
|
||||||
|
// Each table with the same double bracketed name will be an element in the
|
||||||
|
// array. The tables are inserted in the order encountered. A double bracketed
|
||||||
|
// table without any key/value pairs will be considered an empty table.
|
||||||
|
//
|
||||||
|
// [[products]]
|
||||||
|
// name = "Hammer"
|
||||||
|
// sku = 738594937
|
||||||
|
//
|
||||||
|
// [[products]]
|
||||||
|
//
|
||||||
|
// [[products]]
|
||||||
|
// name = "Nail"
|
||||||
|
// sku = 284758393
|
||||||
|
// color = "gray"
|
||||||
|
//
|
||||||
|
// You can create nested arrays of tables as well. Just use the same double
|
||||||
|
// bracket syntax on sub-tables. Each double-bracketed sub-table will belong
|
||||||
|
// to the most recently defined table element above it.
|
||||||
|
//
|
||||||
|
// [[fruit]]
|
||||||
|
// name = "apple"
|
||||||
|
//
|
||||||
|
// [fruit.physical]
|
||||||
|
// color = "red"
|
||||||
|
// shape = "round"
|
||||||
|
//
|
||||||
|
// [[fruit.variety]]
|
||||||
|
// name = "red delicious"
|
||||||
|
//
|
||||||
|
// [[fruit.variety]]
|
||||||
|
// name = "granny smith"
|
||||||
|
//
|
||||||
|
// [[fruit]]
|
||||||
|
// name = "banana"
|
||||||
|
//
|
||||||
|
// [[fruit.variety]]
|
||||||
|
// name = "plantain"
|
||||||
func (t *parser) startArrayOfTables(p *parse.API) {
|
func (t *parser) startArrayOfTables(p *parse.API) {
|
||||||
if key, ok := t.parseKey(p, []string{}); ok {
|
if key, ok := t.parseKey(p, []string{}); ok {
|
||||||
if !p.Accept(tableArrayClose) {
|
if !p.Accept(tableArrayClose) {
|
||||||
|
@ -133,6 +82,44 @@ func (t *parser) startArrayOfTables(p *parse.API) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tables (also known as hash tables or dictionaries) are collections of
|
||||||
|
// key/value pairs. They appear in square brackets on a line by themselves.
|
||||||
|
// You can tell them apart from arrays because arrays are only ever values.
|
||||||
|
//
|
||||||
|
// Under that, and until the next table or EOF are the key/values of that
|
||||||
|
// table. Key/value pairs within tables are not guaranteed to be in any
|
||||||
|
// specific order.
|
||||||
|
//
|
||||||
|
// [table-1]
|
||||||
|
// key1 = "some string"
|
||||||
|
// key2 = 123
|
||||||
|
//
|
||||||
|
// [table-2]
|
||||||
|
// key1 = "another string"
|
||||||
|
// key2 = 456
|
||||||
|
//
|
||||||
|
// Naming rules for tables are the same as for keys.
|
||||||
|
//
|
||||||
|
// [dog."tater.man"]
|
||||||
|
// type.name = "pug"
|
||||||
|
//
|
||||||
|
// Whitespace around the key is ignored, however, best practice is to not
|
||||||
|
// use any extraneous whitespace.
|
||||||
|
//
|
||||||
|
// [a.b.c] # this is best practice
|
||||||
|
// [ d.e.f ] # same as [d.e.f]
|
||||||
|
// [ g . h . i ] # same as [g.h.i]
|
||||||
|
// [ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
|
||||||
|
//
|
||||||
|
// You don't need to specify all the super-tables if you don't want to.
|
||||||
|
// TOML knows how to do it for you.
|
||||||
|
//
|
||||||
|
// # [x] you
|
||||||
|
// # [x.y] don't
|
||||||
|
// # [x.y.z] need these
|
||||||
|
// [x.y.z.w] # for this to work
|
||||||
|
//
|
||||||
|
// Empty tables are allowed and simply have no key/value pairs within them.
|
||||||
func (t *parser) startPlainTable(p *parse.API) {
|
func (t *parser) startPlainTable(p *parse.API) {
|
||||||
if key, ok := t.parseKey(p, []string{}); ok {
|
if key, ok := t.parseKey(p, []string{}); ok {
|
||||||
if !p.Accept(tableClose) {
|
if !p.Accept(tableClose) {
|
||||||
|
@ -146,3 +133,65 @@ func (t *parser) startPlainTable(p *parse.API) {
|
||||||
p.Handle(t.startKeyValuePair)
|
p.Handle(t.startKeyValuePair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inline tables provide a more compact syntax for expressing tables.
|
||||||
|
// They are especially useful for grouped data that can otherwise quickly
|
||||||
|
// become verbose. Inline tables are enclosed in curly braces { and }.
|
||||||
|
// Within the braces, zero or more comma separated key/value pairs may appear.
|
||||||
|
// Key/value pairs take the same form as key/value pairs in standard tables.
|
||||||
|
// All value types are allowed, including inline tables.
|
||||||
|
//
|
||||||
|
// Inline tables are intended to appear on a single line. No newlines are
|
||||||
|
// allowed between the curly braces unless they are valid within a value.
|
||||||
|
// Even so, it is strongly discouraged to break an inline table onto multiple
|
||||||
|
// lines. If you find yourself gripped with this desire, it means you should
|
||||||
|
// be using standard tables.
|
||||||
|
//
|
||||||
|
// name = { first = "Tom", last = "Preston-Werner" }
|
||||||
|
// point = { x = 1, y = 2 }
|
||||||
|
// animal = { type.name = "pug" }
|
||||||
|
func (t *parser) parseInlineTable(p *parse.API) (*item, bool) {
|
||||||
|
// Check for the start of the array.
|
||||||
|
if !p.Accept(inlineTableOpen) {
|
||||||
|
p.Expected("an inline table")
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
subt := newParser()
|
||||||
|
|
||||||
|
// Check for an empty inline table.
|
||||||
|
if p.Accept(inlineTableClose) {
|
||||||
|
return newItem(tTable, subt.Root), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not an empty table, parse the table data.
|
||||||
|
for {
|
||||||
|
key, ok := subt.parseKey(p, []string{})
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if !p.Handle(subt.startAssignment) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
value, ok := subt.parseValue(p)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
err := subt.setKeyValuePair(key, value)
|
||||||
|
if err != nil {
|
||||||
|
p.Error("%s", err)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the end of the inline table.
|
||||||
|
if p.Accept(inlineTableClose) {
|
||||||
|
return newItem(tTable, subt.Root), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not the end of the inline table? Then we should find a key/value pair separator.
|
||||||
|
if !p.Accept(inlineTableSeparator) {
|
||||||
|
p.Expected("an array separator")
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -81,3 +81,35 @@ func TestArrayOfTables(t *testing.T) {
|
||||||
testParse(t, p, p.startTable, test)
|
testParse(t, p, p.startTable, test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStartInlineTable(t *testing.T) {
|
||||||
|
parser := newParser()
|
||||||
|
wrapper := func(p *parse.API) { parser.parseInlineTable(p) }
|
||||||
|
testParse(t, parser, wrapper, parseTest{"(not an inline table)", "{}", "unexpected input (expected an inline table) at start of file"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInlineTable(t *testing.T) {
|
||||||
|
for _, test := range []parseTest{
|
||||||
|
{"x={}", `{"x": {}}`, ``},
|
||||||
|
{"x={} # comments", `{"x": {}}`, ``},
|
||||||
|
{"x={ # comments }", `{}`, `unexpected input (expected a key name) at line 1, column 5`},
|
||||||
|
{"x={a = 1, b\t=2}", `{"x": {"a": 1, "b": 2}}`, ``},
|
||||||
|
{"x={a='string', b=\"values\"}", `{"x": {"a": "string", "b": "values"}}`, ``},
|
||||||
|
{"x={a={}}", `{"x": {"a": {}}}`, ``},
|
||||||
|
{"x={a=[{}]}", `{"x": {"a": [{}]}}`, ``},
|
||||||
|
{"x=[{b=1},{b=2},{b=3}]", `{"x": [{"b": 1}, {"b": 2}, {"b": 3}]}`, ``},
|
||||||
|
{"x={a=[{b=1},{b=2},{b=3}]}", `{"x": {"a": [{"b": 1}, {"b": 2}, {"b": 3}]}}`, ``},
|
||||||
|
{"x={", `{}`, `unexpected end of file (expected a key name) at line 1, column 4`},
|
||||||
|
{"x={a", `{}`, `unexpected end of file (expected a value assignment) at line 1, column 5`},
|
||||||
|
{"x={a=", `{}`, `unexpected end of file (expected a value) at line 1, column 6`},
|
||||||
|
{"x={a=,", `{}`, `unexpected input (expected a value) at line 1, column 6`},
|
||||||
|
{"x={a=1", `{}`, `unexpected end of file (expected an array separator) at line 1, column 7`},
|
||||||
|
{"x={a=1,", `{}`, `unexpected end of file (expected a key name) at line 1, column 8`},
|
||||||
|
{"x={a=1,}", `{}`, `unexpected input (expected a key name) at line 1, column 8`},
|
||||||
|
{"x={a=1,a=2}", `{}`, `invalid key/value pair: integer item already exists at key [a] at line 1, column 11`},
|
||||||
|
{"x={a={b=1,b=2}}", `{}`, `invalid key/value pair: integer item already exists at key [b] at line 1, column 14`},
|
||||||
|
} {
|
||||||
|
p := newParser()
|
||||||
|
testParse(t, p, p.startKeyValuePair, test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,42 +1,45 @@
|
||||||
package toml
|
package toml
|
||||||
|
|
||||||
// func TestValue(t *testing.T) {
|
import "testing"
|
||||||
// for _, test := range []parseTest{
|
|
||||||
// {``, []string{`Error: unexpected end of file (expected a value) at start of file`}},
|
func TestValue(t *testing.T) {
|
||||||
// {`"basic s\tring value"`, []string{`"basic s\tring value"`}},
|
for _, test := range []parseTest{
|
||||||
// {`'literal s\tring value'`, []string{`"literal s\\tring value"`}},
|
{`x=`, `{}`, `unexpected end of file (expected a value) at line 1, column 3`},
|
||||||
// {"\"\"\"basic multi-line\nstring value\"\"\"", []string{`"basic multi-line\nstring value"`}},
|
{`x="basic s\tring value"`, `{"x": "basic s\tring value"}`, ``},
|
||||||
// {"'''literal multi-line\nstring value'''", []string{`"literal multi-line\nstring value"`}},
|
{`x='literal s\tring value'`, `{"x": "literal s\\tring value"}`, ``},
|
||||||
// {"true", []string{`true`}},
|
{"x=\"\"\"basic multi-line\nstring value\"\"\"", `{"x": "basic multi-line\nstring value"}`, ``},
|
||||||
// {"false", []string{`false`}},
|
{"x='''literal multi-line\nstring value'''", `{"x": "literal multi-line\nstring value"}`, ``},
|
||||||
// {"0", []string{`0`}},
|
{"x=true", `{"x": true}`, ``},
|
||||||
// {"+0", []string{`0`}},
|
{"x=false", `{"x": false}`, ``},
|
||||||
// {"-0", []string{`0`}},
|
{"x=0", `{"x": 0}`, ``},
|
||||||
// {"0.0", []string{`0`}},
|
{"x=+0", `{"x": 0}`, ``},
|
||||||
// {"+0.0", []string{`0`}},
|
{"x=-0", `{"x": 0}`, ``},
|
||||||
// {"-0.0", []string{`-0`}},
|
{"x=0.0", `{"x": 0}`, ``},
|
||||||
// {"1234", []string{`1234`}},
|
{"x=+0.0", `{"x": 0}`, ``},
|
||||||
// {"-1234", []string{`-1234`}},
|
{"x=-0.0", `{"x": -0}`, ``},
|
||||||
// {"+9_8_7.6_5_4e-321", []string{`9.8765e-319`}},
|
{"x=1234", `{"x": 1234}`, ``},
|
||||||
// {"-1_234.5678e-33", []string{`-1.2345678e-30`}},
|
{"x=-1234", `{"x": -1234}`, ``},
|
||||||
// {"inf", []string{`+Inf`}},
|
{"x=+9_8_7.6_5_4e-321", `{"x": 9.8765e-319}`, ``},
|
||||||
// {"+inf", []string{`+Inf`}},
|
{"x=-1_234.5678e-33", `{"x": -1.2345678e-30}`, ``},
|
||||||
// {"-inf", []string{`-Inf`}},
|
{"x=inf", `{"x": +Inf}`, ``},
|
||||||
// {"nan", []string{`NaN`}},
|
{"x=+inf", `{"x": +Inf}`, ``},
|
||||||
// {"+nan", []string{`NaN`}},
|
{"x=-inf", `{"x": -Inf}`, ``},
|
||||||
// {"-nan", []string{`NaN`}},
|
{"x=nan", `{"x": NaN}`, ``},
|
||||||
// {"2019-06-19", []string{`2019-06-19`}},
|
{"x=+nan", `{"x": NaN}`, ``},
|
||||||
// {"08:38:54", []string{`08:38:54`}},
|
{"x=-nan", `{"x": NaN}`, ``},
|
||||||
// {"08:38:54.8765487654876", []string{`08:38:54.876548765`}},
|
{"x=2019-06-19", `{"x": 2019-06-19}`, ``},
|
||||||
// {"2019-06-19 08:38:54", []string{`2019-06-19 08:38:54`}},
|
{"x=08:38:54", `{"x": 08:38:54}`, ``},
|
||||||
// {"2019-06-19T08:38:54", []string{`2019-06-19 08:38:54`}},
|
{"x=08:38:54.8765487654876", `{"x": 08:38:54.876548765}`, ``},
|
||||||
// {"2019-06-19T08:38:54.88888", []string{`2019-06-19 08:38:54.88888`}},
|
{"x=2019-06-19 08:38:54", `{"x": 2019-06-19 08:38:54}`, ``},
|
||||||
// {"1979-05-27T07:32:00Z", []string{`1979-05-27T07:32:00Z`}},
|
{"x=2019-06-19T08:38:54", `{"x": 2019-06-19 08:38:54}`, ``},
|
||||||
// {"1979-05-27T00:32:00-07:00", []string{`1979-05-27T00:32:00-07:00`}},
|
{"x=2019-06-19T08:38:54.88888", `{"x": 2019-06-19 08:38:54.88888}`, ``},
|
||||||
// {"1979-05-27T00:32:00.999999-07:00", []string{`1979-05-27T00:32:00.999999-07:00`}},
|
{"x=1979-05-27T07:32:00Z", `{"x": 1979-05-27T07:32:00Z}`, ``},
|
||||||
// {"[1,2,3]", []string{`[1, 2, 3]`}},
|
{"x=1979-05-27T00:32:00-07:00", `{"x": 1979-05-27T00:32:00-07:00}`, ``},
|
||||||
// } {
|
{"x=1979-05-27T00:32:00.999999-07:00", `{"x": 1979-05-27T00:32:00.999999-07:00}`, ``},
|
||||||
// p := newParser()
|
{"x=[1,2,3]", `{"x": [1, 2, 3]}`, ``},
|
||||||
// testParseHandler(t, p, p.startValue, test)
|
{"x={1=1,2=2,3=3}", `{"x": {"1": 1, "2": 2, "3": 3}}`, ``},
|
||||||
// }
|
} {
|
||||||
// }
|
p := newParser()
|
||||||
|
testParse(t, p, p.startKeyValuePair, test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue