81 lines
2.3 KiB
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(tArray), 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(tArray, 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
|
|
}
|
|
}
|
|
}
|