go-toml/value_array.go

81 lines
2.3 KiB
Go

package toml
import (
"git.makaay.nl/mauricem/go-parsekit/parse"
)
// Arrays are square brackets with values inside. Whitespace is ignored.
// Elements are separated by commas. Data types may not be mixed (different
// ways to define strings should be considered the same type, and so should
// arrays with different element types).
//
// arr1 = [ 1, 2, 3 ]
// arr2 = [ "red", "yellow", "green" ]
// arr3 = [ [ 1, 2 ], [3, 4, 5] ]
// arr4 = [ "all", 'strings', """are the same""", '''type''']
// arr5 = [ [ 1, 2 ], ["a", "b", "c"] ]
//
// arr6 = [ 1, 2.0 ] # INVALID
//
// Arrays can also be multiline. A terminating comma (also called trailing
// comma) is ok after the last value of the array. There can be an arbitrary
// number of newlines and comments before a value and before the closing bracket.
//
// arr7 = [
// 1, 2, 3
// ]
//
// arr8 = [
// 1,
// 2, # this is ok
// ]
var (
arraySpace = c.ZeroOrMore(c.Any(blank, newline, comment))
arrayOpen = a.SquareOpen.Then(arraySpace)
arraySeparator = c.Seq(arraySpace, a.Comma, arraySpace)
arrayClose = c.Seq(c.Optional(arraySpace.Then(a.Comma)), arraySpace, a.SquareClose)
)
func (t *parser) parseArray(p *parse.API) (*item, bool) {
// Check for the start of the array.
if !p.Accept(arrayOpen) {
p.Expected("an array")
return nil, false
}
// Check for an empty array.
if p.Accept(arrayClose) {
return newItem(pArray), true
}
// Not an empty array, parse the array items.
items := []interface{}{}
for {
// Check for a value item.
value, ok := t.parseValue(p)
if !ok {
return nil, false
}
// Data types may not be mixed (different ways to define strings should be
// considered the same type, and so should arrays with different element types).
if len(items) > 0 && value.Type != items[0].(*item).Type {
p.Error("type mismatch in array of %ss: found an item of type %s", items[0].(*item).Type, value.Type)
return nil, false
}
items = append(items, value)
// Check for the end of the array.
if p.Accept(arrayClose) {
return newItem(pArray, items...), true
}
// Not the end of the array? Then we should find an array separator.
if !p.Accept(arraySeparator) {
p.Expected("an array separator")
return nil, false
}
}
}